[LON-CAPA-cvs] cvs: loncom / lond

albertel lon-capa-cvs@mail.lon-capa.org
Tue, 31 Jan 2006 16:12:15 -0000


albertel		Tue Jan 31 11:12:15 2006 EDT

  Modified files:              
    /loncom	lond 
  Log:
  - BUG#4608 & BUG#4476, lond now should block for up to 13 seconds waiting for  lock on a db file
  
  
Index: loncom/lond
diff -u loncom/lond:1.312 loncom/lond:1.313
--- loncom/lond:1.312	Tue Jan 31 10:56:46 2006
+++ loncom/lond	Tue Jan 31 11:12:12 2006
@@ -2,7 +2,7 @@
 # The LearningOnline Network
 # lond "LON Daemon" Server (port "LOND" 5663)
 #
-# $Id: lond,v 1.312 2006/01/31 15:56:46 albertel Exp $
+# $Id: lond,v 1.313 2006/01/31 16:12:12 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.312 $'; #' stupid emacs
+my $VERSION='$Revision: 1.313 $'; #' stupid emacs
 my $remoteVERSION;
 my $currenthostid="default";
 my $currentdomainid;
@@ -972,11 +974,11 @@
     my $user_top_dir   = $perlvar{'lonUsersDir'};
     my $domain_dir     = $user_top_dir."/$domain";
     my $resource_file  = $domain_dir."/$namespace";
-    return &_do_hash_tie($resource_file,$namespace,$how,$loghead,$logtail);
+    return &_locking_hash_tie($resource_file,$namespace,$how,$loghead,$logtail);
 }
 
 sub untie_domain_hash {
-    return &_do_hash_untie(@_);
+    return &_locking_hash_untie(@_);
 }
 #
 #   Ties a user's resource file to a hash.  
@@ -1005,11 +1007,11 @@
     my $proname     = propath($domain, $user);
 
     my $file_prefix="$proname/$namespace";
-    return &_do_hash_tie($file_prefix,$namespace,$how,$loghead,$what);
+    return &_locking_hash_tie($file_prefix,$namespace,$how,$loghead,$what);
 }
 
 sub untie_user_hash {
-    return &_do_hash_untie(@_);
+    return &_locking_hash_untie(@_);
 }
 
 # internal routines that handle the actual tieing and untieing process
@@ -1041,6 +1043,71 @@
     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();
+	}
+    
+	&logthis("$$ for $namespace");
+	$sym=&Symbol::gensym();
+	open($sym,"$file_prefix.db");
+	&logthis("$$ for $namespace attempt lock");
+	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) {
+	    &logthis("$$ for $namespace got failed lock");
+	    $! = 100; # throwing error # 100
+	    return undef;
+	}
+	&logthis("$$ for $file_prefix.db got lock");
+	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
 #
 #   Returns a set of specific entries from a user's profile file.