--- loncom/lonsql 2001/03/22 19:25:52 1.10 +++ loncom/lonsql 2001/11/29 13:53:56 1.39 @@ -1,8 +1,22 @@ #!/usr/bin/perl + +# The LearningOnline Network +# lonsql - LON TCP-MySQL-Server +# +# YEAR=2000 # lonsql-based on the preforker:harsha jagasia:date:5/10/00 # 7/25 Gerd Kortemeyer # many different dates Scott Harrison +# YEAR=2001 +# many different dates Scott Harrison # 03/22/2001 Scott Harrison +# 8/30 Gerd Kortemeyer +# 10/17,11/28,11/29 Scott Harrison +# +# $Id: lonsql,v 1.39 2001/11/29 13:53:56 harris41 Exp $ +### + + use IO::Socket; use Symbol; use POSIX; @@ -19,11 +33,10 @@ require "find.pl"; sub wanted { (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && -f _ && - /^.*\.meta$/ && + /^.*\.meta$/ && !/^.+\.\d+\.[^\.]+\.meta$/ && push(@metalist,"$dir/$_"); } - $childmaxattempts=10; $run =0;#running counter to generate the query-id @@ -39,6 +52,24 @@ while ($configline=) { } close(CONFIG); +# ------------------------------------- Make sure that database can be accessed +{ + my $dbh; + unless ( + $dbh = DBI->connect("DBI:mysql:loncapa","www",$perlvar{'lonSqlAccess'},{ RaiseError =>0,PrintError=>0}) + ) { + print "Cannot connect to database!\n"; + $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}"; + $subj="LON: $perlvar{'lonHostID'} Cannot connect to database!"; + system("echo 'Cannot connect to MySQL database!' |\ + mailto $emailto -s '$subj' > /dev/null"); + exit 1; + } + else { + $dbh->disconnect; + } +} + # --------------------------------------------- Check if other instance running my $pidfile="$perlvar{'lonDaemons'}/logs/lonsql.pid"; @@ -60,13 +91,14 @@ while ($configline=) { chomp($ip); $hostip{$ip}=$id; - if ($id eq $perlvar{'lonHostID'}) { $thisserver=$name; } $PREFORK++; } close(CONFIG); +$PREFORK=int($PREFORK/4); + $unixsock = "mysqlsock"; my $localfile="$perlvar{'lonSockDir'}/$unixsock"; my $server; @@ -191,12 +223,11 @@ sub make_new_child { #open database handle # making dbh global to avoid garbage collector unless ( - $dbh = DBI->connect("DBI:mysql:loncapa","www","123",{ RaiseError =>0,PrintError=>0}) + $dbh = DBI->connect("DBI:mysql:loncapa","www",$perlvar{'lonSqlAccess'},{ RaiseError =>0,PrintError=>0}) ) { - my $st=120+int(rand(240)); + sleep(10+int(rand(20))); &logthis("WARNING: Couldn't connect to database ($st secs): $@"); print "database handle error\n"; - sleep($st); exit; }; @@ -212,9 +243,11 @@ sub make_new_child { my $userinput = <$client>; chomp($userinput); - my ($conserver,$querytmp,$customtmp)=split(/&/,$userinput); + my ($conserver,$querytmp, + $customtmp,$customshowtmp)=split(/&/,$userinput); my $query=unescape($querytmp); my $custom=unescape($customtmp); + my $customshow=unescape($customshowtmp); #send query id which is pid_unixdatetime_runningcounter $queryid = $thisserver; @@ -223,33 +256,90 @@ sub make_new_child { $queryid .= $run; print $client "$queryid\n"; + &logthis("QUERY: $query"); + &logthis("QUERY: $query"); + sleep 1; #prepare and execute the query my $sth = $dbh->prepare($query); my $result; - unless ($sth->execute()) - { - &logthis("WARNING: Could not retrieve from database: $@"); - $result=""; - } - else { - my $r1=$sth->fetchall_arrayref; - my @r2; map {my $a=$_; my @b=map {escape($_)} @$a; push @r2,join(",", @b)} (@$r1); - $result=join("&",@r2) . "\n"; + my @files; + my $subsetflag=0; + if ($query) { + unless ($sth->execute()) + { + &logthis("WARNING: Could not retrieve from database: $@"); + $result=""; + } + else { + my $r1=$sth->fetchall_arrayref; + my @r2; + map {my $a=$_; + my @b=map {escape($_)} @$a; + push @files,@{$a}[3]; + push @r2,join(",", @b) + } (@$r1); + $result=join("&",@r2); + } } - # do custom metadata searching here and build into result - if ($custom) { + if ($custom or $customshow) { &logthis("am going to do custom query for $custom"); - @metalist=(); pop @metalist; - &find("$perlvar{'lonDocRoot'}/res"); - &logthis("FILELIST:" . join(":::",@metalist)); + if ($query) { + @metalist=map {$perlvar{'lonDocRoot'}.$_.'.meta'} @files; + } + else { + @metalist=(); pop @metalist; + opendir(RESOURCES,"$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}"); + my @homeusers=grep + {&ishome("$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}/$_")} + grep {!/^\.\.?$/} readdir(RESOURCES); + closedir RESOURCES; + foreach my $user (@homeusers) { + &find("$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}/$user"); + } + } +# &logthis("FILELIST:" . join(":::",@metalist)); # if file is indicated in sql database and # not part of sql-relevant query, do not pattern match. # if file is not in sql database, output error. # if file is indicated in sql database and is # part of query result list, then do the pattern match. + my $customresult=''; + my @r2; + foreach my $m (@metalist) { + my $fh=IO::File->new($m); + my @lines=<$fh>; + my $stuff=join('',@lines); + if ($stuff=~/$custom/s) { + foreach my $f ('abstract','author','copyright', + 'creationdate','keywords','language', + 'lastrevisiondate','mime','notes', + 'owner','subject','title') { + $stuff=~s/\n?\<$f[^\>]*\>.*?<\/$f[^\>]*\>\n?//s; + } + my $m2=$m; my $docroot=$perlvar{'lonDocRoot'}; + $m2=~s/^$docroot//; + $m2=~s/\.meta$//; + unless ($query) { + my $q2="select * from metadata where url like binary '$m2'"; + my $sth = $dbh->prepare($q2); + $sth->execute(); + my $r1=$sth->fetchall_arrayref; + map {my $a=$_; + my @b=map {escape($_)} @$a; + push @files,@{$a}[3]; + push @r2,join(",", @b) + } (@$r1); + } +# &logthis("found: $stuff"); + $customresult.='&custom='.escape($m2).','.escape($stuff); + } + } + $result=join("&",@r2) unless $query; + $result.=$customresult; } # reply with result + $result.="\n" if $result; &reply("queryreply:$queryid:$result",$conserver); } @@ -300,6 +390,7 @@ sub reply { } } else { $answer='self_reply'; + $answer=subreply($cmd,$server); } return $answer; } @@ -319,3 +410,29 @@ sub unescape { $str =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; return $str; } + +# --------------------------------------- Is this the home server of an author? +# (copied from lond, modification of the return value) +sub ishome { + my $author=shift; + $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/; + my ($udom,$uname)=split(/\//,$author); + my $proname=propath($udom,$uname); + if (-e $proname) { + return 1; + } else { + return 0; + } +} + +# -------------------------------------------- Return path to profile directory +# (copied from lond) +sub propath { + my ($udom,$uname)=@_; + $udom=~s/\W//g; + $uname=~s/\W//g; + my $subdir=$uname.'__'; + $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/; + my $proname="$perlvar{'lonUsersDir'}/$udom/$subdir/$uname"; + return $proname; +}