--- loncom/LONCAPA.pm 2010/06/15 05:31:43 1.30 +++ loncom/LONCAPA.pm 2019/08/25 02:43:33 1.36 @@ -1,7 +1,7 @@ # The LearningOnline Network # Base routines # -# $Id: LONCAPA.pm,v 1.30 2010/06/15 05:31:43 raeburn Exp $ +# $Id: LONCAPA.pm,v 1.36 2019/08/25 02:43:33 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -37,10 +37,27 @@ use LONCAPA::Configuration; use Fcntl qw(:flock); use GDBM_File; use POSIX; +#use Apache::lonnet; my $loncapa_max_wait_time = 13; +#-------------------------------------------------------------------------- +# +# The constant definnitions below probably should really be in +# a configuration file somewhere (loncapa.conf?) and loaded so that they can be +# modified without requring source code changes: +# +# COURSE_CACHE_TIME - Number of minutes after which an unaccessed +# course.db or course_param.db file is considered +# to be a stale cache of this info. +# +# LONCAPA_TEMPDIR - Place loncapa puts temporary files +# + +my $COURSE_CACHE_TIME = 60; # minutes course cache file is considered valid. +my $LONCAPA_TEMPDIR = '/tmp/'; # relative to configuration{'lonTabDir'}. + use vars qw($match_domain $match_not_domain $match_username $match_not_username $match_courseid $match_not_courseid @@ -53,14 +70,14 @@ require Exporter; our @ISA = qw (Exporter); our @EXPORT = qw(&add_get_param &escape &unescape &tie_domain_hash &untie_domain_hash &tie_user_hash - &untie_user_hash &propath); + &untie_user_hash &propath &tie_course); our @EXPORT_OK = qw($match_domain $match_not_domain $match_username $match_not_username $match_courseid $match_not_courseid $match_community $match_name $match_lonid - $match_handle $match_not_handle); + $match_handle $match_not_handle &tie_course); our %EXPORT_TAGS = ( 'match' =>[qw($match_domain $match_not_domain $match_username $match_not_username $match_courseid $match_not_courseid @@ -71,6 +88,85 @@ our %EXPORT_TAGS = ( 'match' =>[qw($matc my %perlvar; +# +# If necessary fetch and tie a user's image of the course hash +# to the specified hash +# Parameters: +# domain - User's domain +# user - Name of user. +# course - Course number. +# cdom - Domain that is home to the course +# hash - reference to the has to tie. +# +# Side effects: +# a gdbm file and it's associated lock file will be created in the +# tmp directory tree. +# +# Returns: +# 0 - failure. +# 1 - success. +# +# Note: +# It's possible the required user's db file is already present in the tempdir. +# in that case a decision must be made about whether or not to just tie to it +# or to fetch it again. Remember this sub could be called in the context of a user +# other than the one whose data are being fetched. We don't know if that user already +# has a live session on this server. What we'll do is only re-fetch if the hash atime. +# is older than COURSE_CACHE_TIME...that is if it's been accessed relatively recently +# where COURSE_CACHE_TIME defines the caching time. +# +# The database files this function creates are of the form: +# $user@$domain_$course@$cdom.{db,lock} +# This differs from the prior filenames. Therefore if a module does its own +# caching (That's a coding no-no) and does not use this centralized sub, +# multiple cache files for the same course/user will be created. +# +sub tie_course { + my ($domain, $user, $course, $cdom, $hash) = @_; + + # + # See if we need to re-fetch the course data + # + + +} + +# Return a string that is the path in which loncapa puts temp files: + +sub tempdir { + my $result = $perlvar{'lonDaemons'}.$LONCAPA_TEMPDIR; # to allow debugging. + return $result; +} + +# Return the default engine to use to render content of tags unless +# a domain, course, or user specific value exists. + +sub texengine { + return 'MathJax'; +} + +# Return the Linux distro where this LON-CAPA instance is running + +sub distro { + my $distro; + if (open(PIPE,"/home/httpd/perl/distprobe |")) { + $distro = ; + close(PIPE); + } + return $distro; +} + +# Return the default password length. Can be overridden in a domain +# by specifying a larger value (integer) in the domain configuration. + +sub passwd_min { + return 7; +} + +#---------------------------------------------------------------------- +# +# some of these subs need a bit of documentation + sub add_get_param { my ($url,$form_data) = @_; my $needs_question_mark = ($url !~ /\?/); @@ -103,6 +199,14 @@ sub unescape { return $str; } +$LONCAPA::assess_re = qr{\.(problem|exam|quiz|assess|survey|form|library|task)$}; +$LONCAPA::assess_page_re = qr{\.(problem|exam|quiz|assess|survey|form|library|task|page)$}; +$LONCAPA::assess_page_seq_re = qr{\.(problem|exam|quiz|assess|survey|form|library|task|sequence|page)$}; +$LONCAPA::parse_re = qr{\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$}; +$LONCAPA::parse_page_re = qr{\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm|page)$}; +$LONCAPA::parse_page_sty_re = qr{\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm|page|sty)$}; + + $match_domain = $LONCAPA::domain_re = qr{[[:alnum:]\-.]+}; $match_not_domain = $LONCAPA::not_domain_re = qr{[^[:alnum:]\-.]+}; sub clean_domain { @@ -155,6 +259,47 @@ sub clean_handle { return $handle; } +# +# -- Ensure another process for same filesystem action is not running. +# lond uses for: apachereload; loncron uses for: lciptables +# + +sub try_to_lock { + my ($lockfile)=@_; + my $currentpid; + my $lastpid; + # Do not manipulate lock file as root + if ($>==0) { + return 0; + } + # Try to generate lock file. + # Wait 3 seconds. If same process id is in + # lock file, then assume lock file is stale, and + # go ahead. If process id's fluctuate, try + # for a maximum of 10 times. + for (0..10) { + if (-e $lockfile) { + open(LOCK,"<$lockfile"); + $currentpid=; + close LOCK; + if ($currentpid==$lastpid) { + last; + } + sleep 3; + $lastpid=$currentpid; + } else { + last; + } + if ($_==10) { + return 0; + } + } + open(LOCK,">$lockfile"); + print LOCK $$; + close LOCK; + return 1; +} + # -------------------------------------------- Return path to profile directory sub propath { @@ -366,6 +511,7 @@ sub _do_hash_untie { } } + BEGIN { %perlvar=%{&LONCAPA::Configuration::read_conf('loncapa.conf')}; } @@ -456,6 +602,37 @@ Returns: hash to which the database is tied. It's up to the caller to untie. undef if the has could not be tied. +=item tie_course + +Caches the course database into the temp directory in the context of a specific +user and ties it to a hash. +Parameters: + domain - Domain the user is in. + user - Username of the user. + course - Course specification + cdom - The course domain. + hash - Reference to the hash to tie. + +Returns: + 1 - Success + 0 - Failure. + +=item tie_course_params + +Caches the course parameter database into the temp directory in the context +of a specific user and ties it to a hash. +Parameters: + domain - Domain the user is in. + user - Username of the user. + course - course specification. + cdom - The course domain. + hash - reference to the hash to tie. + +Returns: + 1 - Success. + 0 - Failure./ + + =item locking_hash_tie() routines if you just have a filename return tied hashref or undef @@ -464,8 +641,17 @@ routines if you just have a filename ret =item db_filename_parts() +=back + +=item tempdir() + +Returns the file system path to the place loncapa temporary files should be placed/found. + + =head1 INTERNAL SUBROUTINES +=over + =item _do_hash_tie() =item _do_hash_untie()