Diff for /loncom/metadata_database/searchcat.pl between versions 1.32 and 1.44

version 1.32, 2003/03/26 20:15:57 version 1.44, 2003/12/23 15:47:26
Line 27 Line 27
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 ###  ###
   
 =pod  =pod
   
 =head1 NAME  =head1 NAME
Line 75  use POSIX qw(strftime mktime); Line 76  use POSIX qw(strftime mktime);
   
 my @metalist;  my @metalist;
   
   $simplestatus='';
   my %countext=();
   
   sub writesimple {
       open(SMP,'>/home/httpd/html/lon-status/mysql.txt');
       print SMP $simplestatus."\n";
       close(SMP);
   }
   
   sub writecount {
       open(RSMP,'>/home/httpd/html/lon-status/rescount.txt');
       foreach (keys %countext) {
    print RSMP $_.'='.$countext{$_}.'&';
       }
       print RSMP 'time='.time."\n";
       close(RSMP);
   }
   
   sub count {
       my $file=shift;
       $file=~/\.(\w+)$/;
       my $ext=lc($1);
       if (defined($countext{$ext})) {
    $countext{$ext}++;
       } else {
    $countext{$ext}=1;
       }
   }
 # ----------------------------------------------------- Un-Escape Special Chars  # ----------------------------------------------------- Un-Escape Special Chars
   
 sub unescape {  sub unescape {
Line 96  sub escape { Line 124  sub escape {
 # ------------------------------------------- Code to evaluate dynamic metadata  # ------------------------------------------- Code to evaluate dynamic metadata
   
 sub dynamicmeta {  sub dynamicmeta {
   
     my $url=&declutter(shift);      my $url=&declutter(shift);
     $url=~s/\.meta$//;      $url=~s/\.meta$//;
     my %returnhash=();      my %returnhash=();
     my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//);      my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//);
     my $prodir=&propath($adomain,$aauthor);      my $prodir=&propath($adomain,$aauthor);
     if ((tie(%evaldata,'GDBM_File',  # Get metadata except counts
             $prodir.'/nohist_resevaldata.db',&GDBM_READER(),0640)) &&      if (tie(%evaldata,'GDBM_File',
         (tie(%newevaldata,'GDBM_File',              $prodir.'/nohist_resevaldata.db',&GDBM_READER(),0640)) {
             $prodir.'/nohist_new_resevaldata.db',&GDBM_WRCREAT(),0640))) {   my %sum=();
        my %sum=();   my %cnt=();
        my %cnt=();   my %concat=();
        my %listitems=('count'        => 'add',   my %listitems=(
                       'course'       => 'add',         'course'       => 'add',
                       'avetries'     => 'avg',         'goto'         => 'add',
                       'stdno'        => 'add',         'comefrom'     => 'add',
                       'difficulty'   => 'avg',         'avetries'     => 'avg',
                       'clear'        => 'avg',         'stdno'        => 'add',
                       'technical'    => 'avg',         'difficulty'   => 'avg',
                       'helpful'      => 'avg',         'clear'        => 'avg',
                       'correct'      => 'avg',         'technical'    => 'avg',
                       'depth'        => 'avg',         'helpful'      => 'avg',
                       'comments'     => 'app',         'correct'      => 'avg',
                       'usage'        => 'cnt'         'depth'        => 'avg',
                       );         'comments'     => 'app',
        my $regexp=$url;         'usage'        => 'cnt'
        $regexp=~s/(\W)/\\$1/g;         );
        $regexp='___'.$regexp.'___([a-z]+)$';  
        foreach (keys %evaldata) {   my $regexp=$url;
  my $key=&unescape($_);   $regexp=~s/(\W)/\\$1/g;
  if ($key=~/$regexp/) {   $regexp='___'.$regexp.'___([a-z]+)$';
     my $ctype=$1;   while (my ($esckey,$value)=each %evaldata) {
             if (defined($cnt{$ctype})) {       $key=&unescape($esckey);
                $cnt{$ctype}++;       if ($key=~/$regexp/) {
             } else {    my ($item,$purl,$cat)=split(/___/,$_);
                $cnt{$ctype}=1;    if (defined($cnt{$cat})) { $cnt{$cat}++; } else { $cnt{$cat}=1; }
             }   unless ($listitems{$cat} eq 'app') {
             unless ($listitems{$ctype} eq 'app') {      if (defined($sum{$cat})) {
                if (defined($sum{$ctype})) {   $sum{$cat}+=$evaldata{$_};
                   $sum{$ctype}+=$evaldata{$_};   $concat{$cat}.=','.$item;
           } else {      } else {
                   $sum{$ctype}=$evaldata{$_};   $sum{$cat}=$evaldata{$_};
        }   $concat{$cat}=$item;
             } else {      }
                if (defined($sum{$ctype})) {   } else {
                   if ($evaldata{$_}) {      if (defined($sum{$cat})) {
                      $sum{$ctype}.='<hr>'.$evaldata{$_};   if ($evaldata{$_}) {
           }      $sum{$cat}.='<hr>'.$evaldata{$_};
         } else {   }
              $sum{$ctype}=''.$evaldata{$_};      } else {
        }   $sum{$cat}=''.$evaldata{$_};
       }
    }
     }      }
     if ($ctype ne 'count') {   }
        $newevaldata{$_}=$evaldata{$_};   untie(%evaldata);
    }      }
  }  # construct the return hash for non-count data
       }      my %returnhash=();
       foreach (keys %cnt) {      while ($_=each(%cnt)) {
          if ($listitems{$_} eq 'avg') {   if ($listitems{$_} eq 'avg') {
      $returnhash{$_}=int(($sum{$_}/$cnt{$_})*100.0+0.5)/100.0;      $returnhash{$_}=int(($sum{$_}/$cnt{$_})*100.0+0.5)/100.0;
          } elsif ($listitems{$_} eq 'cnt') {   } elsif ($listitems{$_} eq 'cnt') {
              $returnhash{$_}=$cnt{$_};      $returnhash{$_}=$cnt{$_};
          } else {   } else {
              $returnhash{$_}=$sum{$_};      $returnhash{$_}=$sum{$_};
          }   }
      }   $returnhash{$_.'_list'}=$concat{$_};
      if ($returnhash{'count'}) {      }
          my $newkey=$$.'_'.time.'_searchcat___'.&escape($url).'___count';  # get count
          $newevaldata{$newkey}=$returnhash{'count'};      if (tie(%evaldata,'GDBM_File',
      }              $prodir.'/nohist_accesscount.db',&GDBM_READER(),0640)) {
      untie(%evaldata);   if (! exists($evaldata{$uri})) {
      untie(%newevaldata);      $returnhash{'count'}='Not Available';
    }   } else {
    return %returnhash;      $returnhash{'count'}=$evaldata{$uri};
    }
    untie %evaldata;
       }
       return %returnhash;
 }  }
       
 # ----------------- Code to enable 'find' subroutine listing of the .meta files  # ----------------- Code to enable 'find' subroutine listing of the .meta files
 require "find.pl";  require "find.pl";
 sub wanted {  sub wanted {
     (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&      (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
     -f _ &&          -f _ &&
     /^.*\.meta$/ && !/^.+\.\d+\.[^\.]+\.meta$/ &&          /^.*\.meta$/ && !/^.+\.\d+\.[^\.]+\.meta$/ &&
     push(@metalist,"$dir/$_");          push(@metalist,"$dir/$_");
 }  }
   
 # ---------------  Read loncapa_apache.conf and loncapa.conf and get variables  # ---------------  Read loncapa_apache.conf and loncapa.conf and get variables
Line 194  exit unless $perlvar{'lonRole'} eq 'libr Line 227  exit unless $perlvar{'lonRole'} eq 'libr
   
 my $wwwid=getpwnam('www');  my $wwwid=getpwnam('www');
 if ($wwwid!=$<) {  if ($wwwid!=$<) {
    $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}";      $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}";
    $subj="LON: $perlvar{'lonHostID'} User ID mismatch";      $subj="LON: $perlvar{'lonHostID'} User ID mismatch";
    system("echo 'User ID mismatch. searchcat.pl must be run as user www.' |\      system("echo 'User ID mismatch. searchcat.pl must be run as user www.' |\
  mailto $emailto -s '$subj' > /dev/null");   mailto $emailto -s '$subj' > /dev/null");
    exit 1;      exit 1;
 }  }
   
   
Line 206  if ($wwwid!=$<) { Line 239  if ($wwwid!=$<) {
   
 open(LOG,'>'.$perlvar{'lonDaemons'}.'/logs/searchcat.log');  open(LOG,'>'.$perlvar{'lonDaemons'}.'/logs/searchcat.log');
 print LOG '==== Searchcat Run '.localtime()."====\n\n";  print LOG '==== Searchcat Run '.localtime()."====\n\n";
   $simplestatus='time='.time.'&';
 my $dbh;  my $dbh;
 # ------------------------------------- Make sure that database can be accessed  # ------------------------------------- Make sure that database can be accessed
 {  {
Line 213  my $dbh; Line 247  my $dbh;
     $dbh = DBI->connect("DBI:mysql:loncapa","www",$perlvar{'lonSqlAccess'},{ RaiseError =>0,PrintError=>0})      $dbh = DBI->connect("DBI:mysql:loncapa","www",$perlvar{'lonSqlAccess'},{ RaiseError =>0,PrintError=>0})
     ) {       ) { 
  print LOG "Cannot connect to database!\n";   print LOG "Cannot connect to database!\n";
    $simplestatus.='mysql=defunct';
    &writesimple();
  exit;   exit;
     }      }
   
     my $make_metadata_table = "CREATE TABLE IF NOT EXISTS metadata (".      my $make_metadata_table = "CREATE TABLE IF NOT EXISTS metadata (".
         "title TEXT, author TEXT, subject TEXT, url TEXT, keywords TEXT, ".          "title TEXT, author TEXT, subject TEXT, url TEXT, keywords TEXT, ".
         "version TEXT, notes TEXT, abstract TEXT, mime TEXT, language TEXT, ".          "version TEXT, notes TEXT, abstract TEXT, mime TEXT, language TEXT, ".
Line 232  my $dbh; Line 269  my $dbh;
   
 # ------------------------------------------------------------- get .meta files  # ------------------------------------------------------------- get .meta files
 opendir(RESOURCES,"$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}");  opendir(RESOURCES,"$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}");
 my @homeusers=grep  my @homeusers = grep {
           {&ishome("$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}/$_")}      &ishome("$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}/$_")
           grep {!/^\.\.?$/} readdir(RESOURCES);      } grep {!/^\.\.?$/} readdir(RESOURCES);
 closedir RESOURCES;  closedir RESOURCES;
   
   #
   # Create the statement handlers we need
   my $delete_sth = $dbh->prepare
       ("DELETE FROM metadata WHERE url LIKE BINARY ?");
   
   my $insert_sth = $dbh->prepare
       ("INSERT INTO metadata VALUES (".
        "?,".   # title
        "?,".   # author
        "?,".   # subject
        "?,".   # m2???
        "?,".   # version
        "?,".   # current
        "?,".   # notes
        "?,".   # abstract
        "?,".   # mime
        "?,".   # language
        "?,".   # creationdate
        "?,".   # revisiondate
        "?,".   # owner
        "?)"    # copyright
        );
   
 foreach my $user (@homeusers) {  foreach my $user (@homeusers) {
     print LOG "\n=== User: ".$user."\n\n";      print LOG "\n=== User: ".$user."\n\n";
 # Remove left-over db-files from potentially crashed searchcat run  
     my $prodir=&propath($perlvar{'lonDefDomain'},$user);      my $prodir=&propath($perlvar{'lonDefDomain'},$user);
     unlink($prodir.'/nohist_new_resevaldata.db');      # Use find.pl
 # Use find.pl  
     undef @metalist;      undef @metalist;
     @metalist=();      @metalist=();
     &find("$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}/$user");      &find("$perlvar{'lonDocRoot'}/res/$perlvar{'lonDefDomain'}/$user");
       # -- process each file to get metadata and put into search catalog SQL
 # -- process each file to get metadata and put into search catalog SQL database      # database.  Also, check to see if already there.
 # Also, check to see if already there.      # I could just delete (without searching first), but this works for now.
 # I could just delete (without searching first), but this works for now.      foreach my $m (@metalist) {
 foreach my $m (@metalist) {          print LOG "- ".$m."\n";
     print LOG "- ".$m."\n";          my $ref=&metadata($m);
     my $ref=&metadata($m);          my $m2='/res/'.&declutter($m);
     my $m2='/res/'.&declutter($m);          $m2=~s/\.meta$//;
     $m2=~s/\.meta$//;          &dynamicmeta($m2);
     &dynamicmeta($m2);    if ($ref->{'obsolete'}) { print LOG "obsolete\n"; next; }
     my $q2="select * from metadata where url like binary '$m2'";   if ($ref->{'copyright'} eq 'private') { print LOG "private\n"; next; }
     my $sth = $dbh->prepare($q2);   &count($m2);
     $sth->execute();          $delete_sth->execute($m2);
     my $r1=$sth->fetchall_arrayref;          $insert_sth->execute($ref->{'title'},
     if (@$r1) {                               $ref->{'author'},
  $sth=$dbh->prepare("delete from metadata where url like binary '$m2'");                               $ref->{'subject'},
         $sth->execute();                               $m2,
                                $ref->{'keywords'},
                                'current',
                                $ref->{'notes'},
                                $ref->{'abstract'},
                                $ref->{'mime'},
                                $ref->{'language'},
                                sqltime($ref->{'creationdate'}),
                                sqltime($ref->{'lastrevisiondate'}),
                                $ref->{'owner'},
                                $ref->{'copyright'});
   #        if ($dbh->err()) {
   #            print STDERR "Error:".$dbh->errstr()."\n";
   #        }
           $ref = undef;
     }      }
     $sth=$dbh->prepare('insert into metadata values ('.      
   '"'.delete($ref->{'title'}).'"'.','.      # --------------------------------------------------- Clean up database
   '"'.delete($ref->{'author'}).'"'.','.      # Need to, perhaps, remove stale SQL database records.
   '"'.delete($ref->{'subject'}).'"'.','.      # ... not yet implemented
   '"'.$m2.'"'.','.          
   '"'.delete($ref->{'keywords'}).'"'.','.  
   '"'.'current'.'"'.','.  
   '"'.delete($ref->{'notes'}).'"'.','.  
   '"'.delete($ref->{'abstract'}).'"'.','.  
   '"'.delete($ref->{'mime'}).'"'.','.  
   '"'.delete($ref->{'language'}).'"'.','.  
   '"'.sqltime(delete($ref->{'creationdate'})).'"'.','.  
   '"'.sqltime(delete($ref->{'lastrevisiondate'})).'"'.','.  
   '"'.delete($ref->{'owner'}).'"'.','.  
   '"'.delete($ref->{'copyright'}).'"'.')');  
     $sth->execute();  
 }  
   
 # ----------------------------------------------------------- Clean up database  
 # Need to, perhaps, remove stale SQL database records.  
 # ... not yet implemented  
   
   
 # -------------------------------------------------- Copy over the new db-files  
     system('mv '.$prodir.'/nohist_new_resevaldata.db '.  
          $prodir.'/nohist_resevaldata.db');  
 }  }
 # --------------------------------------------------- Close database connection  # --------------------------------------------------- Close database connection
 $dbh->disconnect;  $dbh->disconnect;
 print LOG "\n==== Searchcat completed ".localtime()." ====\n";  print LOG "\n==== Searchcat completed ".localtime()." ====\n";
 close(LOG);  close(LOG);
   &writesimple();
   &writecount();
 exit 0;  exit 0;
   
   
   
 # =============================================================================  # =============================================================================
   
 # ---------------------------------------------------------------- Get metadata  # ---------------------------------------------------------------- Get metadata
Line 312  sub metadata { Line 370  sub metadata {
         my $parser=HTML::TokeParser->new(\$metastring);          my $parser=HTML::TokeParser->new(\$metastring);
         my $token;          my $token;
         while ($token=$parser->get_token) {          while ($token=$parser->get_token) {
            if ($token->[0] eq 'S') {              if ($token->[0] eq 'S') {
       my $entry=$token->[1];                  my $entry=$token->[1];
               my $unikey=$entry;                  my $unikey=$entry;
               if (defined($token->[2]->{'part'})) {                   if (defined($token->[2]->{'part'})) { 
                  $unikey.='_'.$token->[2]->{'part'};                       $unikey.='_'.$token->[2]->{'part'}; 
       }                  }
               if (defined($token->[2]->{'name'})) {                   if (defined($token->[2]->{'name'})) { 
                  $unikey.='_'.$token->[2]->{'name'};                       $unikey.='_'.$token->[2]->{'name'}; 
       }                  }
               if ($metacache{$uri.'keys'}) {                  if ($metacache{$uri.'keys'}) {
                  $metacache{$uri.'keys'}.=','.$unikey;                      $metacache{$uri.'keys'}.=','.$unikey;
               } else {                  } else {
                  $metacache{$uri.'keys'}=$unikey;                      $metacache{$uri.'keys'}=$unikey;
       }                  }
               map {                  map {
   $metacache{$uri.''.$unikey.'.'.$_}=$token->[2]->{$_};                      $metacache{$uri.''.$unikey.'.'.$_}=$token->[2]->{$_};
               } @{$token->[3]};                  } @{$token->[3]};
               unless (                  unless (
                  $metacache{$uri.''.$unikey}=$parser->get_text('/'.$entry)                          $metacache{$uri.''.$unikey}=$parser->get_text('/'.$entry)
       ) { $metacache{$uri.''.$unikey}=                          ) { $metacache{$uri.''.$unikey}=
       $metacache{$uri.''.$unikey.'.default'};                                  $metacache{$uri.''.$unikey.'.default'};
       }                          }
           }              }
        }          }
     }      }
     return \%metacache;      return \%metacache;
 }  }
Line 343  sub metadata { Line 401  sub metadata {
 # ------------------------------------------------------------ Serves up a file  # ------------------------------------------------------------ Serves up a file
 # returns either the contents of the file or a -1  # returns either the contents of the file or a -1
 sub getfile {  sub getfile {
   my $file=shift;      my $file=shift;
   if (! -e $file ) { return -1; };      if (! -e $file ) { return -1; };
   my $fh=IO::File->new($file);      my $fh=IO::File->new($file);
   my $a='';      my $a='';
   while (<$fh>) { $a .=$_; }      while (<$fh>) { $a .=$_; }
   return $a      return $a;
 }  }
   
 # ------------------------------------------------------------- Declutters URLs  # ------------------------------------------------------------- Declutters URLs
Line 396  sub sqltime { Line 454  sub sqltime {
   
 sub maketime {  sub maketime {
     my %th=@_;      my %th=@_;
     return POSIX::mktime(      return POSIX::mktime(($th{'seconds'},$th{'minutes'},$th{'hours'},
         ($th{'seconds'},$th{'minutes'},$th{'hours'},                            $th{'day'},$th{'month'}-1,
          $th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,$th{'dlsav'}));                            $th{'year'}-1900,0,0,$th{'dlsav'}));
 }  }
   
   
Line 409  sub maketime { Line 467  sub maketime {
 sub unsqltime {  sub unsqltime {
     my $timestamp=shift;      my $timestamp=shift;
     if ($timestamp=~/^(\d+)\-(\d+)\-(\d+)\s+(\d+)\:(\d+)\:(\d+)$/) {      if ($timestamp=~/^(\d+)\-(\d+)\-(\d+)\s+(\d+)\:(\d+)\:(\d+)$/) {
        $timestamp=&maketime(          $timestamp=&maketime('year'=>$1,'month'=>$2,'day'=>$3,
    'year'=>$1,'month'=>$2,'day'=>$3,                               'hours'=>$4,'minutes'=>$5,'seconds'=>$6);
            'hours'=>$4,'minutes'=>$5,'seconds'=>$6);  
     }      }
     return $timestamp;      return $timestamp;
 }  }

Removed from v.1.32  
changed lines
  Added in v.1.44


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>