--- loncom/lonsql 2003/02/03 13:43:38 1.55 +++ loncom/lonsql 2004/05/11 21:08:20 1.60 @@ -3,7 +3,7 @@ # The LearningOnline Network # lonsql - LON TCP-MySQL-Server Daemon for handling database requests. # -# $Id: lonsql,v 1.55 2003/02/03 13:43:38 albertel Exp $ +# $Id: lonsql,v 1.60 2004/05/11 21:08:20 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -39,9 +39,59 @@ lonsql - LON TCP-MySQL-Server Daemon for This script should be run as user=www. Note that a lonsql.pid file contains the pid of the parent process. -=head1 DESCRIPTION +=head1 OVERVIEW -lonsql is +=head2 Purpose within LON-CAPA + +LON-CAPA is meant to distribute A LOT of educational content to A LOT +of people. It is ineffective to directly rely on contents within the +ext2 filesystem to be speedily scanned for on-the-fly searches of +content descriptions. (Simply put, it takes a cumbersome amount of +time to open, read, analyze, and close thousands of files.) + +The solution is to index various data fields that are descriptive of +the educational resources on a LON-CAPA server machine in a +database. Descriptive data fields are referred to as "metadata". The +question then arises as to how this metadata is handled in terms of +the rest of the LON-CAPA network without burdening client and daemon +processes. + +The obvious solution, using lonc to send a query to a lond process, +doesn't work so well in general as you can see in the following +example: + + lonc= loncapa client process A-lonc= a lonc process on Server A + lond= loncapa daemon process + + database command + A-lonc --------TCP/IP----------------> B-lond + +The problem emerges that A-lonc and B-lond are kept waiting for the +MySQL server to "do its stuff", or in other words, perform the +conceivably sophisticated, data-intensive, time-sucking database +transaction. By tying up a lonc and lond process, this significantly +cripples the capabilities of LON-CAPA servers. + +The solution is to offload the work onto another process, and use +lonc and lond just for requests and notifications of completed +processing: + + database command + + A-lonc ---------TCP/IP-----------------> B-lond =====> B-lonsql + <---------------------------------/ | + "ok, I'll get back to you..." | + | + / + A-lond <------------------------------- B-lonc <====== + "Guess what? I have the result!" + +Of course, depending on success or failure, the messages may vary, but +the principle remains the same where a separate pool of children +processes (lonsql's) handle the MySQL database manipulations. + +Thus, lonc and lond spend effectively no time waiting on results from +the database. =head1 Internals @@ -53,6 +103,7 @@ use strict; use lib '/home/httpd/lib/perl/'; use LONCAPA::Configuration; +use LONCAPA::lonmetadata(); use IO::Socket; use Symbol; @@ -165,6 +216,11 @@ unless ($dbh = DBI->connect("DBI:mysql:l my $subj="LON: $perlvar{'lonHostID'} Cannot connect to database!"; system("echo 'Cannot connect to MySQL database!' |". " mailto $emailto -s '$subj' > /dev/null"); + + open(SMP,'>/home/httpd/html/lon-status/mysql.txt'); + print SMP 'time='.time.'&mysql=defunct'."\n"; + close(SMP); + exit 1; } else { $dbh->disconnect; @@ -226,7 +282,7 @@ my $execdir=$perlvar{'lonDaemons'}; open (PIDSAVE,">$execdir/logs/lonsql.pid"); print PIDSAVE "$$\n"; close(PIDSAVE); -&logthis("CRITICAL: ---------- Starting ----------"); +&logthis("CRITICAL: ---------- Starting ----------"); # # Ignore signals generated during initial startup @@ -297,7 +353,7 @@ sub make_new_child { $perlvar{'lonSqlAccess'}, { RaiseError =>0,PrintError=>0})) { sleep(10+int(rand(20))); - &logthis("WARNING: Couldn't connect to database". + &logthis("WARNING: Couldn't connect to database". ": $@"); # "($st secs): $@"); print "database handle error\n"; @@ -357,15 +413,13 @@ sub make_new_child { # result does not need to be escaped because it has already been # escaped. #$result=&escape($result); - # reply with result, append \n unless already there - $result.="\n" unless ($result=~/\n$/); &reply("queryreply:$queryid:$result",$conserver); } # tidy up gracefully and finish # # close the database handle $dbh->disconnect - or &logthis("WARNING: Couldn't disconnect". + or &logthis("WARNING: Couldn't disconnect". " from database $DBI::errstr : $@"); # this exit is VERY important, otherwise the child will become # a producer of more and more children, forking yourself into @@ -420,8 +474,9 @@ sub do_sql_query { #prepare and execute the query my $sth = $dbh->prepare($query); unless ($sth->execute()) { - &logthis("WARNING: ". - "Could not retrieve from database: $@"); + &logthis(''. + 'WARNING: Could not retrieve from database:'. + $sth->errstr().''); } else { my $aref=$sth->fetchall_arrayref; foreach my $row (@$aref) { @@ -853,7 +908,7 @@ sub HUNTSMAN { # si kill 'INT' => keys %children; my $execdir=$perlvar{'lonDaemons'}; unlink("$execdir/logs/lonsql.pid"); - &logthis("CRITICAL: Shutting down"); + &logthis("CRITICAL: Shutting down"); $unixsock = "mysqlsock"; my $port="$perlvar{'lonSockDir'}/$unixsock"; unlink($port); @@ -864,7 +919,7 @@ sub HUPSMAN { # sig local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children kill 'INT' => keys %children; close($server); # free up socket - &logthis("CRITICAL: Restarting"); + &logthis("CRITICAL: Restarting"); my $execdir=$perlvar{'lonDaemons'}; $unixsock = "mysqlsock"; my $port="$perlvar{'lonSockDir'}/$unixsock"; @@ -874,23 +929,12 @@ sub HUPSMAN { # sig sub DISCONNECT { $dbh->disconnect or - &logthis("WARNING: Couldn't disconnect from database ". + &logthis("WARNING: Couldn't disconnect from database ". " $DBI::errstr : $@"); exit; } - - - - - - - - - -# ----------------------------------- POD (plain old documentation, CPAN style) - =pod =back