--- loncom/lonnet/perl/lonnet.pm 2011/06/13 17:41:04 1.1116 +++ loncom/lonnet/perl/lonnet.pm 2011/08/01 22:13:49 1.1123 @@ -1,7 +1,7 @@ # The LearningOnline Network # TCP networking package # -# $Id: lonnet.pm,v 1.1116 2011/06/13 17:41:04 raeburn Exp $ +# $Id: lonnet.pm,v 1.1123 2011/08/01 22:13:49 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -95,6 +95,7 @@ use Math::Random; use File::MMagic; use LONCAPA qw(:DEFAULT :match); use LONCAPA::Configuration; + use File::Copy; my $readit; @@ -305,6 +306,44 @@ sub get_server_homeID { return &do_cache_new('serverhomeID',$hostname,$serverhomeID,$cachetime); } +sub get_remote_globals { + my ($lonhost,$whathash,$ignore_cache) = @_; + my (%returnhash,%whatneeded); + if (ref($whathash) eq 'ARRAY') { + foreach my $what (sort(keys(%{$whathash}))) { + my $type = $whathash->{$what}; + my $hashid = $lonhost.'-'.$what; + my ($result,$cached); + unless ($ignore_cache) { + ($result,$cached)=&is_cached_new('lonnetglobal',$hashid); + $returnhash{$what} = $result; + } + if (defined($cached)) { + $returnhash{$what} = $result; + } else { + $whatneeded{$what} = $type; + } + } + if (keys(%whatneeded) > 0) { + my $requested = &freeze_escape(\%whatneeded); + my $rep=&reply('readlonnetglobal:'.$requested,$lonhost); + unless (($rep=~/^refused/) || ($rep=~/^rejected/) || ($rep eq 'con_lost')) { + my @pairs=split(/\&/,$rep); + if ($rep !~ /^error/) { + foreach my $item (@pairs) { + my ($key,$value)=split(/=/,$item,2); + my $what = &unescape($key); + my $hashid = $lonhost.'-'.$what; + $returnhash{$what}=&thaw_unescape($value); + &do_cache_new('lonnetglobal',$hashid,$returnhash{$what},600); + } + } + } + } + } + return %returnhash; +} + # -------------------------------------------------- Non-critical communication sub subreply { my ($cmd,$server)=@_; @@ -772,26 +811,33 @@ sub spareserver { my %udomdefaults = &Apache::lonnet::get_domain_defaults($udom); $remotesessions = $udomdefaults{'remotesessions'}; } - foreach my $try_server (@{ $spareid{'primary'} }) { - if ($uint_dom) { - next unless (&spare_can_host($udom,$uint_dom,$remotesessions, - $try_server)); + my $spareshash = &this_host_spares($udom); + if (ref($spareshash) eq 'HASH') { + if (ref($spareshash->{'primary'}) eq 'ARRAY') { + foreach my $try_server (@{ $spareshash->{'primary'} }) { + if ($uint_dom) { + next unless (&spare_can_host($udom,$uint_dom,$remotesessions, + $try_server)); + } + ($spare_server, $lowest_load) = + &compare_server_load($try_server, $spare_server, $lowest_load); + } } - ($spare_server, $lowest_load) = - &compare_server_load($try_server, $spare_server, $lowest_load); - } - - my $found_server = ($spare_server ne '' && $lowest_load < 100); - if (!$found_server) { - foreach my $try_server (@{ $spareid{'default'} }) { - if ($uint_dom) { - next unless (&spare_can_host($udom,$uint_dom,$remotesessions, - $try_server)); - } - ($spare_server, $lowest_load) = - &compare_server_load($try_server, $spare_server, $lowest_load); - } + my $found_server = ($spare_server ne '' && $lowest_load < 100); + + if (!$found_server) { + if (ref($spareshash->{'default'}) eq 'ARRAY') { + foreach my $try_server (@{ $spareshash->{'default'} }) { + if ($uint_dom) { + next unless (&spare_can_host($udom,$uint_dom, + $remotesessions,$try_server)); + } + ($spare_server, $lowest_load) = + &compare_server_load($try_server, $spare_server, $lowest_load); + } + } + } } if (!$want_server_name) { @@ -842,9 +888,18 @@ sub compare_server_load { # --------------------------- ask offload servers if user already has a session sub find_existing_session { my ($udom,$uname) = @_; - foreach my $try_server (@{ $spareid{'primary'} }, - @{ $spareid{'default'} }) { - return $try_server if (&has_user_session($try_server, $udom, $uname)); + my $spareshash = &this_host_spares($udom); + if (ref($spareshash) eq 'HASH') { + if (ref($spareshash->{'primary'}) eq 'ARRAY') { + foreach my $try_server (@{ $spareshash->{'primary'} }) { + return $try_server if (&has_user_session($try_server, $udom, $uname)); + } + } + if (ref($spareshash->{'default'}) eq 'ARRAY') { + foreach my $try_server (@{ $spareshash->{'default'} }) { + return $try_server if (&has_user_session($try_server, $udom, $uname)); + } + } } return; } @@ -1034,15 +1089,19 @@ sub can_host_session { } if ($canhost) { if (ref($hostedsessions) eq 'HASH') { + my $uprimary_id = &Apache::lonnet::domain($udom,'primary'); + my $uint_dom = &Apache::lonnet::internet_dom($uprimary_id); if (ref($hostedsessions->{'excludedomain'}) eq 'ARRAY') { - if (grep(/^\Q$udom\E$/,@{$hostedsessions->{'excludedomain'}})) { + if (($uint_dom ne '') && + (grep(/^\Q$uint_dom\E$/,@{$hostedsessions->{'excludedomain'}}))) { $canhost = 0; } else { $canhost = 1; } } if (ref($hostedsessions->{'includedomain'}) eq 'ARRAY') { - if (grep(/^\Q$udom\E$/,@{$hostedsessions->{'includedomain'}})) { + if (($uint_dom ne '') && + (grep(/^\Q$uint_dom\E$/,@{$hostedsessions->{'includedomain'}}))) { $canhost = 1; } else { $canhost = 0; @@ -1073,6 +1132,47 @@ sub spare_can_host { return $canhost; } +sub this_host_spares { + my ($dom) = @_; + my $cachetime = 60*60*24; + my @hosts = ¤t_machine_ids(); + foreach my $lonhost (@hosts) { + if (&host_domain($lonhost) eq $dom) { + my ($result,$cached)=&is_cached_new('spares',$dom); + if (defined($cached)) { + return $result; + } else { + my %domconfig = + &Apache::lonnet::get_dom('configuration',['usersessions'],$dom); + if (ref($domconfig{'usersessions'}) eq 'HASH') { + if (ref($domconfig{'usersessions'}{'spares'}) eq 'HASH') { + if (ref($domconfig{'usersessions'}{'spares'}{$lonhost}) eq 'HASH') { + return &do_cache_new('spares',$dom,$domconfig{'usersessions'}{'spares'}{$lonhost},$cachetime); + } + } + } + } + last; + } + } + my $serverhomedom = &host_domain($perlvar{'lonHostID'}); + my ($result,$cached)=&is_cached_new('spares',$serverhomedom); + if (defined($cached)) { + return $result; + } else { + my %homedomconfig = + &Apache::lonnet::get_dom('configuration',['usersessions'],$serverhomedom); + if (ref($homedomconfig{'usersessions'}) eq 'HASH') { + if (ref($homedomconfig{'usersessions'}{'spares'}) eq 'HASH') { + if (ref($homedomconfig{'usersessions'}{'spares'}{$perlvar{'lonHostID'}}) eq 'HASH') { + return &do_cache_new('spares',$serverhomedom,$homedomconfig{'usersessions'}{'spares'}{$perlvar{'lonHostID'}},$cachetime); + } + } + } + } + return \%spareid; +} + # ---------------------- Find the homebase for a user from domain's lib servers my %homecache; @@ -2573,7 +2673,7 @@ sub finishuserfileupload { return '/adm/notfound.html'; } if ($context eq 'overwrite') { - my $source = $perlvar{'lonDaemons'}.'/tmp/overwrites/'.$docudom.'/'.$docuname.'/'.$fname; + my $source = LONCAPA::tempdir().'/overwrites/'.$docudom.'/'.$docuname.'/'.$fname; my $target = $filepath.'/'.$file; if (-e $source) { my @info = stat($source); @@ -3775,7 +3875,7 @@ sub tmpreset { if ($domain eq 'public' && $stuname eq 'public') { $stuname=$ENV{'REMOTE_ADDR'}; } - my $path=$perlvar{'lonDaemons'}.'/tmp'; + my $path=LONCAPA::tempdir(); my %hash; if (tie(%hash,'GDBM_File', $path.'/tmpstore_'.$stuname.'_'.$domain.'_'.$namespace.'.db', @@ -3814,7 +3914,7 @@ sub tmpstore { } my $now=time; my %hash; - my $path=$perlvar{'lonDaemons'}.'/tmp'; + my $path=LONCAPA::tempdir(); if (tie(%hash,'GDBM_File', $path.'/tmpstore_'.$stuname.'_'.$domain.'_'.$namespace.'.db', &GDBM_WRCREAT(),0640)) { @@ -3860,7 +3960,7 @@ sub tmprestore { $namespace=~s/\//\_/g; $namespace=~s/\W//g; my %hash; - my $path=$perlvar{'lonDaemons'}.'/tmp'; + my $path=LONCAPA::tempdir(); if (tie(%hash,'GDBM_File', $path.'/tmpstore_'.$stuname.'_'.$domain.'_'.$namespace.'.db', &GDBM_READER(),0640)) { @@ -3997,6 +4097,8 @@ sub restore { } # ---------------------------------------------------------- Course Description +# +# sub coursedescription { my ($courseid,$args)=@_; @@ -4026,7 +4128,8 @@ sub coursedescription { return %returnhash; } - # get the data agin + # get the data again + if (!$args->{'one_time'}) { $envhash{'course.'.$normalid.'.last_cache'}=time; } @@ -4034,6 +4137,10 @@ sub coursedescription { if ($chome ne 'no_host') { %returnhash=&dump('environment',$cdomain,$cnum); if (!exists($returnhash{'con_lost'})) { + my $username = $env{'user.name'}; # Defult username + if(defined $args->{'user'}) { + $username = $args->{'user'}; + } $returnhash{'home'}= $chome; $returnhash{'domain'} = $cdomain; $returnhash{'num'} = $cnum; @@ -4044,8 +4151,8 @@ sub coursedescription { $envhash{'course.'.$normalid.'.'.$name}=$value; } $returnhash{'url'}=&clutter($returnhash{'url'}); - $returnhash{'fn'}=$perlvar{'lonDaemons'}.'/tmp/'. - $env{'user.name'}.'_'.$cdomain.'_'.$cnum; + $returnhash{'fn'}=LONCAPA::tempdir() . + $username.'_'.$cdomain.'_'.$cnum; $envhash{'course.'.$normalid.'.home'}=$chome; $envhash{'course.'.$normalid.'.domain'}=$cdomain; $envhash{'course.'.$normalid.'.num'}=$cnum; @@ -5995,7 +6102,7 @@ sub fetch_enrollment_query { $$replyref{$key} = $value; } } else { - my $pathname = $perlvar{'lonDaemons'}.'/tmp'; + my $pathname = LONCAPA::tempdir(); foreach my $line (@responses) { my ($key,$value) = split(/=/,$line); $$replyref{$key} = $value; @@ -6025,7 +6132,7 @@ sub fetch_enrollment_query { sub get_query_reply { my $queryid=shift; - my $replyfile=$perlvar{'lonDaemons'}.'/tmp/'.$queryid; + my $replyfile=LONCAPA::tempdir().$queryid; my $reply=''; for (1..100) { sleep 2; @@ -7462,7 +7569,7 @@ sub save_selected_files { sub clear_selected_files { my ($user) = @_; my $filename = $user."savedfiles"; - open (OUT, '>'.$Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/'.$filename); + open (OUT, '>'.LONCAPA::tempdir().$filename); print (OUT undef); close (OUT); return ("ok"); @@ -7472,7 +7579,7 @@ sub files_in_path { my ($user, $path) = @_; my $filename = $user."savedfiles"; my %return_files; - open (IN, '<'.$Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/'.$filename); + open (IN, '<'.LONCAPA::tempdir().$filename); while (my $line_in = ) { chomp ($line_in); my @paths_and_file = split (m!/!, $line_in); @@ -7494,7 +7601,7 @@ sub files_not_in_path { my $filename = $user."savedfiles"; my @return_files; my $path_part; - open(IN, '<'.$Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/'.$filename); + open(IN, '<'.LONCAPA::.$filename); while (my $line = ) { #ok, I know it's clunky, but I want it to work my @paths_and_file = split(m|/|, $line); @@ -9788,7 +9895,7 @@ sub filelocation { my @ids=¤t_machine_ids(); foreach my $id (@ids) { if ($id eq $home) { $is_me=1; } } if ($is_me) { - $location=&propath($udom,$uname).'/userfiles/'.$filename; + $location=propath($udom,$uname).'/userfiles/'.$filename; } else { $location=$Apache::lonnet::perlvar{'lonDocRoot'}.'/userfiles/'. $udom.'/'.$uname.'/'.$filename; @@ -10543,7 +10650,7 @@ BEGIN { # ------------- set up temporary directory { - $tmpdir = $perlvar{'lonDaemons'}.'/tmp/'; + $tmpdir = LONCAPA::tempdir(); } @@ -11037,11 +11144,32 @@ revokecustomrole($udom,$uname,$url,$role =item * -coursedescription($courseid) : returns a hash of information about the +coursedescription($courseid,$options) : returns a hash of information about the specified course id, including all environment settings for the course, the description of the course will be in the hash under the key 'description' +$options is an optional parameter that if supplied is a hash reference that controls +what how this function works. It has the following key/values: + +=over 4 + +=item freshen_cache + +If defined, and the environment cache for the course is valid, it is +returned in the returned hash. + +=item one_time + +If defined, the last cache time is set to _now_ + +=item user + +If defined, the supplied username is used instead of the current user. + + +=back + =item * resdata($name,$domain,$type,@which) : request for current parameter @@ -11434,11 +11562,12 @@ splitting on '&', supports elements that =head2 Logging Routines -=over 4 These routines allow one to make log messages in the lonnet.log and lonnet.perm logfiles. +=over 4 + =item * logtouch() : make sure the logfile, lonnet.log, exists @@ -11454,6 +11583,7 @@ logperm() : append a permanent message t file never gets deleted by any automated portion of the system, only messages of critical importance should go in here. + =back =head2 General File Helper Routines