[LON-CAPA-cvs] cvs: loncom(version_2_1_X) / lond

albertel lon-capa-cvs@mail.lon-capa.org
Thu, 02 Feb 2006 10:32:32 -0000


This is a MIME encoded message

--albertel1138876352
Content-Type: text/plain

albertel		Thu Feb  2 05:32:32 2006 EDT

  Modified files:              (Branch: version_2_1_X)
    /loncom	lond 
  Log:
  - backport 1.309,310,311,312,313,314,315,316
  
  
--albertel1138876352
Content-Type: text/plain
Content-Disposition: attachment; filename="albertel-20060202053232.txt"

Index: loncom/lond
diff -u loncom/lond:1.305.2.1 loncom/lond:1.305.2.2
--- loncom/lond:1.305.2.1	Fri Jan 27 18:05:30 2006
+++ loncom/lond	Thu Feb  2 05:32:31 2006
@@ -2,7 +2,7 @@
 # The LearningOnline Network
 # lond "LON Daemon" Server (port "LOND" 5663)
 #
-# $Id: lond,v 1.305.2.1 2006/01/27 23:05:30 albertel Exp $
+# $Id: lond,v 1.305.2.2 2006/02/02 10:32:31 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -53,13 +53,15 @@
 use LONCAPA::lonlocal;
 use LONCAPA::lonssl;
 use Fcntl qw(:flock);
+use Symbol;
 
 my $DEBUG = 0;		       # Non zero to enable debug log entries.
 
 my $status='';
 my $lastlog='';
+my $lond_max_wait_time = 13;
 
-my $VERSION='$Revision: 1.305.2.1 $'; #' stupid emacs
+my $VERSION='$Revision: 1.305.2.2 $'; #' stupid emacs
 my $remoteVERSION;
 my $currenthostid="default";
 my $currentdomainid;
@@ -970,23 +972,13 @@
     
     my $user_top_dir   = $perlvar{'lonUsersDir'};
     my $domain_dir     = $user_top_dir."/$domain";
-    my $resource_file  = $domain_dir."/$namespace.db";
-    my %hash;
-    if(tie(%hash, 'GDBM_File', $resource_file, $how, 0640)) {
-	if (defined($loghead)) {	# Need to log the operation.
-	    my $logFh = IO::File->new(">>$domain_dir/$namespace.hist");
-	    if($logFh) {
-		my $timestamp = time;
-		print $logFh "$loghead:$timestamp:$logtail\n";
-	    }
-	    $logFh->close;
-	}
-	return \%hash;		# Return the tied hash.
-    } else {
-	return undef;		# Tie failed.
-    }
+    my $resource_file  = $domain_dir."/$namespace";
+    return &_locking_hash_tie($resource_file,$namespace,$how,$loghead,$logtail);
 }
 
+sub untie_domain_hash {
+    return &_locking_hash_untie(@_);
+}
 #
 #   Ties a user's resource file to a hash.  
 #   If necessary, an appropriate history
@@ -1012,18 +1004,27 @@
     $namespace=~s/\//\_/g;	# / -> _
     $namespace=~s/\W//g;		# whitespace eliminated.
     my $proname     = propath($domain, $user);
-   
-    #  Tie the database.
-    
+
+    my $file_prefix="$proname/$namespace";
+    return &_locking_hash_tie($file_prefix,$namespace,$how,$loghead,$what);
+}
+
+sub untie_user_hash {
+    return &_locking_hash_untie(@_);
+}
+
+# internal routines that handle the actual tieing and untieing process
+
+sub _do_hash_tie {
+    my ($file_prefix,$namespace,$how,$loghead,$what) = @_;
     my %hash;
-    if(tie(%hash, 'GDBM_File', "$proname/$namespace.db",
-	   $how, 0640)) {
+    if(tie(%hash, 'GDBM_File', "$file_prefix.db", $how, 0640)) {
 	# If this is a namespace for which a history is kept,
 	# make the history log entry:    
 	if (($namespace !~/^nohist\_/) && (defined($loghead))) {
 	    my $args = scalar @_;
-	    Debug(" Opening history: $namespace $args");
-	    my $hfh = IO::File->new(">>$proname/$namespace.hist"); 
+	    Debug(" Opening history: $file_prefix $args");
+	    my $hfh = IO::File->new(">>$file_prefix.hist"); 
 	    if($hfh) {
 		my $now = time;
 		print $hfh "$loghead:$now:$what\n";
@@ -1034,7 +1035,72 @@
     } else {
 	return undef;
     }
+}
+
+sub _do_hash_untie {
+    my ($hashref) = @_;
+    my $result = untie(%$hashref);
+    return $result;
+}
+
+{
+    my $sym;
+
+    sub _locking_hash_tie {
+	my ($file_prefix,$namespace,$how,$loghead,$what) = @_;
+
+	my ($lock);
+    
+	if ($how eq &GDBM_READER()) {
+	    $lock=LOCK_SH;
+	    $how=$how|&GDBM_NOLOCK();
+	    #if the db doesn't exist we can't read from it
+	    if (! -e "$file_prefix.db") {
+		$! = 2;
+		return undef;
+	    }
+	} elsif ($how eq &GDBM_WRCREAT()) {
+	    $lock=LOCK_EX;
+	    $how=$how|&GDBM_NOLOCK();
+	    if (! -e "$file_prefix.db") {
+		# doesn't exist but we need it to in order to successfully
+                # lock it so bring it into existance
+		open(TOUCH,">>$file_prefix.db");
+		close(TOUCH);
+	    }
+	} else {
+	    &logthis("Unknown method $how for $file_prefix");
+	    die();
+	}
     
+	$sym=&Symbol::gensym();
+	open($sym,"$file_prefix.db");
+	my $failed=0;
+	eval {
+	    local $SIG{__DIE__}='DEFAULT';
+	    local $SIG{ALRM}=sub { 
+		$failed=1;
+		die("failed lock");
+	    };
+	    alarm($lond_max_wait_time);
+	    flock($sym,$lock);
+	    alarm(0);
+	};
+	if ($failed) {
+	    $! = 100; # throwing error # 100
+	    return undef;
+	}
+	return &_do_hash_tie($file_prefix,$namespace,$how,$loghead,$what);
+    }
+
+    sub _locking_hash_untie {
+	my ($hashref) = @_;
+	my $result = untie(%$hashref);
+	flock($sym,LOCK_UN);
+	close($sym);
+	undef($sym);
+	return $result;
+    }
 }
 
 #   read_profile
@@ -1067,7 +1133,7 @@
 	    $qresult.="$hashref->{$queries[$i]}&";    # Presumably failure gives empty string.
 	}
 	$qresult=~s/\&$//;              # Remove trailing & from last lookup.
-	if (untie %$hashref) {
+	if (&untie_user_hash($hashref)) {
 	    return $qresult;
 	} else {
 	    return "error: ".($!+0)." untie (GDBM) Failed";
@@ -2376,7 +2442,7 @@
 		my ($key,$value)=split(/=/,$pair);
 		$hashref->{$key}=$value;
 	    }
-	    if (untie(%$hashref)) {
+	    if (&untie_user_hash($hashref)) {
 		&Reply( $client, "ok\n", $userinput);
 	    } else {
 		&Failure($client, "error: ".($!+0)." untie(GDBM) failed ".
@@ -2384,7 +2450,7 @@
 			$userinput);
 	    }
 	} else {
-	    &Failure( $client, "error: ".($!)." tie(GDBM) Failed ".
+	    &Failure( $client, "error: ".($!+0)." tie(GDBM) Failed ".
 		     "while attempting put\n", $userinput);
 	}
     } else {
@@ -2420,7 +2486,7 @@
     my $hashref = &tie_user_hash($udom, $uname, $namespace,
 				 &GDBM_WRCREAT(),"N",$what);
     if(!$hashref) {
-	&Failure( $client, "error: ".($!)." tie(GDBM) Failed ".
+	&Failure( $client, "error: ".($!+0)." tie(GDBM) Failed ".
 		  "while attempting put\n", $userinput);
 	return 1;
     }
@@ -2439,7 +2505,7 @@
 	$hashref->{$key}=$value;
     }
 
-    if (untie(%$hashref)) {
+    if (&untie_user_hash($hashref)) {
 	&Reply( $client, "ok\n", $userinput);
     } else {
 	&Failure($client, "error: ".($!+0)." untie(GDBM) failed ".
@@ -2492,7 +2558,7 @@
                     }
                 }
 	    }
-	    if (untie(%$hashref)) {
+	    if (&untie_user_hash($hashref)) {
 		&Reply( $client, "ok\n", $userinput);
 	    } else {
 		&Failure($client, "error: ".($!+0)." untie(GDBM) failed ".
@@ -2559,7 +2625,7 @@
 			       $auth_type);
 	    $hashref->{$key}=$value;
 	}
-	if (untie($hashref)) {
+	if (&untie_user_hash($hashref)) {
 	    &Reply($client, "ok\n", $userinput);
 	} else {
 	    &Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ".
@@ -2610,7 +2676,7 @@
 	foreach my $key (@rolekeys) {
 	    delete $hashref->{$key};
 	}
-	if (untie(%$hashref)) {
+	if (&untie_user_hash($hashref)) {
 	    &Reply($client, "ok\n", $userinput);
 	} else {
 	    &Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ".
@@ -2751,7 +2817,7 @@
 	foreach my $key (@keys) {
 	    delete($hashref->{$key});
 	}
-	if (untie(%$hashref)) {
+	if (&untie_user_hash($hashref)) {
 	    &Reply($client, "ok\n", $userinput);
 	} else {
 	    &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
@@ -2793,7 +2859,7 @@
 	foreach my $key (keys %$hashref) {
 	    $qresult.="$key&";
 	}
-	if (untie(%$hashref)) {
+	if (&untie_user_hash($hashref)) {
 	    $qresult=~s/\&$//;
 	    &Reply($client, "$qresult\n", $userinput);
 	} else {
@@ -2854,7 +2920,7 @@
 	    $data{$symb}->{$param}=$value;
 	    $data{$symb}->{'v.'.$param}=$v;
 	}
-	if (untie(%$hashref)) {
+	if (&untie_user_hash($hashref)) {
 	    while (my ($symb,$param_hash) = each(%data)) {
 		while(my ($param,$value) = each (%$param_hash)){
 		    next if ($param =~ /^v\./);       # Ignore versions...
@@ -2929,7 +2995,7 @@
 		}
 	    }
 	}
-	if (untie(%$hashref)) {
+	if (&untie_user_hash($hashref)) {
 	    chop($qresult);
 	    &Reply($client, "$qresult\n", $userinput);
 	} else {
@@ -2991,7 +3057,7 @@
 	    $hashref->{"$version:$rid:timestamp"}=$now;
 	    $allkeys.='timestamp';
 	    $hashref->{"$version:keys:$rid"}=$allkeys;
-	    if (untie($hashref)) {
+	    if (&untie_user_hash($hashref)) {
 		&Reply($client, "ok\n", $userinput);
 	    } else {
 		&Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
@@ -3043,24 +3109,22 @@
     $namespace=~s/\//\_/g;
     $namespace=~s/\W//g;
     chomp($rid);
-    my $proname=&propath($udom,$uname);
     my $qresult='';
-    my %hash;
-    if (tie(%hash,'GDBM_File',"$proname/$namespace.db",
-	    &GDBM_READER(),0640)) {
-	my $version=$hash{"version:$rid"};
+    my $hashref = &tie_user_hash($udom, $uname, $namespace, &GDBM_READER());
+    if ($hashref) {
+	my $version=$hashref->{"version:$rid"};
 	$qresult.="version=$version&";
 	my $scope;
 	for ($scope=1;$scope<=$version;$scope++) {
-	    my $vkeys=$hash{"$scope:keys:$rid"};
+	    my $vkeys=$hashref->{"$scope:keys:$rid"};
 	    my @keys=split(/:/,$vkeys);
 	    my $key;
 	    $qresult.="$scope:keys=$vkeys&";
 	    foreach $key (@keys) {
-		$qresult.="$scope:$key=".$hash{"$scope:$rid:$key"}."&";
+		$qresult.="$scope:$key=".$hashref->{"$scope:$rid:$key"}."&";
 	    }                                  
 	}
-	if (untie(%hash)) {
+	if (&untie_user_hash($hashref)) {
 	    $qresult=~s/\&$//;
 	    &Reply( $client, "$qresult\n", $userinput);
 	} else {
@@ -3293,7 +3357,7 @@
             }
 	    $hashref->{$key}=$courseinfo.':'.$now;
 	}
-	if (untie(%$hashref)) {
+	if (&untie_domain_hash($hashref)) {
 	    &Reply( $client, "ok\n", $userinput);
 	} else {
 	    &Failure($client, "error: ".($!+0)
@@ -3409,7 +3473,7 @@
                 $qresult.=$key.'='.$descr.':'.$inst_code.':'.$owner.'&';
             }
 	}
-	if (untie(%$hashref)) {
+	if (&untie_domain_hash($hashref)) {
 	    chop($qresult);
 	    &Reply($client, "$qresult\n", $userinput);
 	} else {
@@ -3458,7 +3522,7 @@
 	    my ($key,$value)=split(/=/,$pair);
 	    $hashref->{$key}=$value;
 	}
-	if (untie(%$hashref)) {
+	if (&untie_domain_hash($hashref)) {
 	    &Reply($client, "ok\n", $userinput);
 	} else {
 	    &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
@@ -3507,7 +3571,7 @@
 	for (my $i=0;$i<=$#queries;$i++) {
 	    $qresult.="$hashref->{$queries[$i]}&";
 	}
-	if (untie(%$hashref)) {
+	if (&untie_domain_hash($hashref)) {
 	    $qresult=~s/\&$//;
 	    &Reply($client, "$qresult\n", $userinput);
 	} else {
@@ -3551,7 +3615,7 @@
         my ($key,$value)=split(/=/,$what);
         $hashref->{$key}=$value;
     }
-    if (untie(%$hashref)) {
+    if (&untie_domain_hash($hashref)) {
         &Reply($client, "ok\n", $userinput);
     } else {
         &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
@@ -3631,7 +3695,7 @@
                 $qresult.=$key.'='.$value.'&';
             }
         }
-        if (untie(%$hashref)) {
+        if (&untie_domain_hash($hashref)) {
             chop($qresult);
             &Reply($client, "$qresult\n", $userinput);
         } else {
@@ -3678,7 +3742,7 @@
             my ($key,$value)=split(/=/,$pair);
             $hashref->{$key}=$value;
         }
-        if (untie(%$hashref)) {
+        if (&untie_domain_hash($hashref)) {
             &Reply($client, "ok\n", $userinput);
         } else {
             &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
@@ -3759,7 +3823,7 @@
                 $qresult.=$key.'='.$value.'&';
             }
         }
-        if (untie(%$hashref)) {
+        if (&untie_domain_hash($hashref)) {
             chop($qresult);
             &Reply($client, "$qresult\n", $userinput);
         } else {
@@ -5606,38 +5670,38 @@
 
 sub get_chat {
     my ($cdom,$cname,$udom,$uname)=@_;
-    my %hash;
-    my $proname=&propath($cdom,$cname);
+
     my @entries=();
-    if (tie(%hash,'GDBM_File',"$proname/nohist_chatroom.db",
-	    &GDBM_READER(),0640)) {
-	@entries=map { $_.':'.$hash{$_} } sort keys %hash;
-	untie %hash;
+    my $hashref = &tie_user_hash($cdom, $cname, 'nohist_chatroom',
+				 &GDBM_READER());
+    if ($hashref) {
+	@entries=map { $_.':'.$hashref->{$_} } sort(keys(%$hashref));
+	&untie_user_hash($hashref);
     }
     my @participants=();
     my $cutoff=time-60;
-    if (tie(%hash,'GDBM_File',"$proname/nohist_inchatroom.db",
-	    &GDBM_WRCREAT(),0640)) {
-        $hash{$uname.':'.$udom}=time;
-        foreach (sort keys %hash) {
-	    if ($hash{$_}>$cutoff) {
-		$participants[$#participants+1]='active_participant:'.$_;
+    $hashref = &tie_user_hash($cdom, $cname, 'nohist_inchatroom',
+			      &GDBM_WRCREAT());
+    if ($hashref) {
+        $hashref->{$uname.':'.$udom}=time;
+        foreach my $user (sort(keys(%$hashref))) {
+	    if ($hashref->{$user}>$cutoff) {
+		push(@participants, 'active_participant:'.$user);
             }
         }
-        untie %hash;
+        &untie_user_hash($hashref);
     }
     return (@participants,@entries);
 }
 
 sub chat_add {
     my ($cdom,$cname,$newchat)=@_;
-    my %hash;
-    my $proname=&propath($cdom,$cname);
     my @entries=();
     my $time=time;
-    if (tie(%hash,'GDBM_File',"$proname/nohist_chatroom.db",
-	    &GDBM_WRCREAT(),0640)) {
-	@entries=map { $_.':'.$hash{$_} } sort keys %hash;
+    my $hashref = &tie_user_hash($cdom, $cname, 'nohist_chatroom',
+				 &GDBM_WRCREAT());
+    if ($hashref) {
+	@entries=map { $_.':'.$hashref->{$_} } sort(keys(%$hashref));
 	my ($lastid)=($entries[$#entries]=~/^(\w+)\:/);
 	my ($thentime,$idnum)=split(/\_/,$lastid);
 	my $newid=$time.'_000000';
@@ -5647,21 +5711,22 @@
 	    $idnum=substr('000000'.$idnum,-6,6);
 	    $newid=$time.'_'.$idnum;
 	}
-	$hash{$newid}=$newchat;
+	$hashref->{$newid}=$newchat;
 	my $expired=$time-3600;
-	foreach (keys %hash) {
-	    my ($thistime)=($_=~/(\d+)\_/);
+	foreach my $comment (keys(%$hashref)) {
+	    my ($thistime) = ($comment=~/(\d+)\_/);
 	    if ($thistime<$expired) {
-		delete $hash{$_};
+		delete $hashref->{$comment};
 	    }
 	}
-	untie %hash;
-    }
-    {
-	my $hfh;
-	if ($hfh=IO::File->new(">>$proname/chatroom.log")) { 
-	    print $hfh "$time:".&unescape($newchat)."\n";
+	{
+	    my $proname=&propath($cdom,$cname);
+	    if (open(CHATLOG,">>$proname/chatroom.log")) { 
+		print CHATLOG ("$time:".&unescape($newchat)."\n");
+	    }
+	    close(CHATLOG);
 	}
+	&untie_user_hash($hashref);
     }
 }
 

--albertel1138876352--