/[BackupPC]/trunk/lib/BackupPC/SearchLib.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/lib/BackupPC/SearchLib.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91 - (hide annotations)
Sun Aug 28 17:53:46 2005 UTC (18 years, 8 months ago) by dpavlin
File size: 13118 byte(s)
bug fix: require search string to be in filepath to produce same
results from HyperEstraier as from RDBMS.

1 dpavlin 4 #!/usr/bin/perl
2     package BackupPC::SearchLib;
3    
4     use strict;
5     use BackupPC::CGI::Lib qw(:all);
6     use BackupPC::Attrib qw(:all);
7     use DBI;
8 dpavlin 51 use DateTime;
9 dpavlin 31 use vars qw(%In $MyURL);
10 dpavlin 55 use Time::HiRes qw/time/;
11 dpavlin 4
12 dpavlin 31 my $on_page = 100;
13     my $pager_pages = 10;
14    
15 dpavlin 51 my $dsn = $Conf{SearchDSN};
16     my $db_user = $Conf{SearchUser} || '';
17    
18 dpavlin 86 my $index_path = $Conf{HyperEstraierIndex};
19     if ($index_path) {
20     $index_path = $TopDir . '/' . $index_path;
21     $index_path =~ s#//#/#g;
22     }
23    
24 dpavlin 84 my $dbh;
25    
26     sub get_dbh {
27     $dbh ||= DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
28     return $dbh;
29     }
30    
31 dpavlin 4 sub getUnits() {
32 dpavlin 59 my @ret;
33    
34 dpavlin 84 my $dbh = get_dbh();
35 dpavlin 86 my $sth = $dbh->prepare(qq{
36     SELECT
37     shares.id as id,
38     hosts.name || ':' || shares.name as share
39     FROM shares
40     JOIN hosts on hostid = hosts.id
41     ORDER BY share
42     } );
43 dpavlin 59 $sth->execute();
44     push @ret, { 'id' => '', 'share' => '-'}; # dummy any
45    
46     while ( my $row = $sth->fetchrow_hashref() ) {
47     push @ret, $row;
48     }
49     return @ret;
50 dpavlin 4 }
51    
52 dpavlin 51 sub epoch_to_iso {
53     my $t = shift || return;
54 dpavlin 86 my $iso = BackupPC::Lib::timeStamp(undef, $t);
55 dpavlin 79 $iso =~ s/\s/ /g;
56     return $iso;
57 dpavlin 51 }
58    
59 dpavlin 83 sub dates_from_form($) {
60     my $param = shift || return;
61 dpavlin 4
62 dpavlin 51 sub mk_epoch_date($$) {
63 dpavlin 19 my ($name,$suffix) = @_;
64 dpavlin 4
65 dpavlin 87 my $yyyy = $param->{ $name . '_year_' . $suffix} || return undef;
66 dpavlin 19 my $mm .= $param->{ $name . '_month_' . $suffix} ||
67     ( $suffix eq 'from' ? 1 : 12);
68     my $dd .= $param->{ $name . '_day_' . $suffix} ||
69     ( $suffix eq 'from' ? 1 : 31);
70 dpavlin 87
71     $yyyy =~ s/\D//g;
72     $mm =~ s/\D//g;
73     $dd =~ s/\D//g;
74    
75 dpavlin 51 my $dt = new DateTime(
76     year => $yyyy,
77     month => $mm,
78     day => $dd
79     );
80 dpavlin 87 print STDERR "mk_epoch_date($name,$suffix) [$yyyy-$mm-$dd] = " . $dt->ymd . " " . $dt->hms . "\n";
81 dpavlin 51 return $dt->epoch || 'NULL';
82 dpavlin 19 }
83 dpavlin 4
84 dpavlin 87 my @ret = (
85 dpavlin 83 mk_epoch_date('search_backup', 'from'),
86     mk_epoch_date('search_backup', 'to'),
87     mk_epoch_date('search', 'from'),
88     mk_epoch_date('search', 'to'),
89     );
90 dpavlin 87
91     return @ret;
92    
93 dpavlin 83 }
94    
95    
96     sub getWhere($) {
97     my $param = shift || return;
98    
99     my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
100    
101     my @conditions;
102 dpavlin 51 push @conditions, qq{ backups.date >= $backup_from } if ($backup_from);
103     push @conditions, qq{ backups.date <= $backup_to } if ($backup_to);
104     push @conditions, qq{ files.date >= $files_from } if ($files_from);
105     push @conditions, qq{ files.date <= $files_to } if ($files_to);
106 dpavlin 19
107 dpavlin 59 print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" | ",@conditions);
108 dpavlin 83
109 dpavlin 60 push( @conditions, ' files.shareid = ' . $param->{'search_share'} ) if ($param->{'search_share'});
110 dpavlin 62 push (@conditions, " upper(files.path) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});
111 dpavlin 19
112 dpavlin 83 return join(" and ", @conditions);
113 dpavlin 4 }
114    
115 dpavlin 19
116 dpavlin 87 sub getFiles($) {
117     my ($param) = @_;
118 dpavlin 31
119 dpavlin 87 my $offset = $param->{'offset'} || 0;
120     $offset *= $on_page;
121    
122 dpavlin 84 my $dbh = get_dbh();
123 dpavlin 31
124     my $sql_cols = qq{
125     files.id AS fid,
126     hosts.name AS hname,
127     shares.name AS sname,
128 dpavlin 86 files.backupnum AS backupnum,
129 dpavlin 31 files.path AS filepath,
130 dpavlin 51 files.date AS date,
131 dpavlin 86 files.type AS type,
132 dpavlin 87 files.size AS size
133 dpavlin 31 };
134    
135     my $sql_from = qq{
136 dpavlin 16 FROM files
137     INNER JOIN shares ON files.shareID=shares.ID
138     INNER JOIN hosts ON hosts.ID = shares.hostID
139 dpavlin 87 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = files.shareID
140 dpavlin 55 };
141    
142 dpavlin 31 my $sql_where;
143 dpavlin 83 my $where = getWhere($param);
144 dpavlin 31 $sql_where = " WHERE ". $where if ($where);
145 dpavlin 4
146 dpavlin 31 my $sql_order = qq{
147 dpavlin 64 ORDER BY files.date
148 dpavlin 59 LIMIT $on_page
149     OFFSET ?
150 dpavlin 9 };
151 dpavlin 31
152 dpavlin 59 my $sql_count = qq{ select count(files.id) $sql_from $sql_where };
153 dpavlin 87 my $sql_results = qq{ select $sql_cols $sql_from $sql_where $sql_order };
154 dpavlin 59
155     my $sth = $dbh->prepare($sql_count);
156 dpavlin 31 $sth->execute();
157     my ($results) = $sth->fetchrow_array();
158    
159 dpavlin 59 $sth = $dbh->prepare($sql_results);
160 dpavlin 31 $sth->execute( $offset );
161    
162 dpavlin 59 if ($sth->rows != $results) {
163     my $bug = "$0 BUG: [[ $sql_count ]] = $results while [[ $sql_results ]] = " . $sth->rows;
164     $bug =~ s/\s+/ /gs;
165     print STDERR "$bug\n";
166     }
167    
168 dpavlin 31 my @ret;
169 dpavlin 4
170 dpavlin 31 while (my $row = $sth->fetchrow_hashref()) {
171 dpavlin 86 push @ret, $row;
172 dpavlin 4 }
173 dpavlin 59
174 dpavlin 31 $sth->finish();
175     return ($results, \@ret);
176     }
177 dpavlin 4
178 dpavlin 87 sub getFilesHyperEstraier($) {
179     my ($param) = @_;
180 dpavlin 86
181 dpavlin 87 my $offset = $param->{'offset'} || 0;
182     $offset *= $on_page;
183    
184 dpavlin 86 die "no index_path?" unless ($index_path);
185    
186     use HyperEstraier;
187    
188     # open the database
189     my $db = HyperEstraier::Database->new();
190     $db->open($index_path, $HyperEstraier::ESTDBREADER);
191    
192     # create a search condition object
193     my $cond = HyperEstraier::Condition->new();
194    
195     my $q = $param->{'search_filename'};
196     my $shareid = $param->{'search_share'};
197    
198 dpavlin 88 if (length($q) > 0) {
199 dpavlin 91 # exact match
200     $cond->add_attr("filepath ISTRINC $q");
201    
202 dpavlin 86 $q =~ s/(.)/$1 /g;
203     # set the search phrase to the search condition object
204     $cond->set_phrase($q);
205 dpavlin 87 }
206 dpavlin 86
207 dpavlin 87 my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
208 dpavlin 86
209 dpavlin 87 $cond->add_attr("backup_date NUMGE $backup_from") if ($backup_from);
210     $cond->add_attr("backup_date NUMLE $backup_to") if ($backup_to);
211 dpavlin 86
212 dpavlin 87 $cond->add_attr("date NUMGE $files_from") if ($files_from);
213     $cond->add_attr("date NUMLE $files_to") if ($files_to);
214 dpavlin 86
215 dpavlin 87 $cond->add_attr("shareid NUMEQ $shareid") if ($shareid);
216 dpavlin 86
217     # $cond->set_max( $offset + $on_page );
218     $cond->set_options( $HyperEstraier::Condition::SURE );
219     $cond->set_order( 'date NUMA' );
220    
221     # get the result of search
222     my $result = $db->search($cond, 0);
223    
224     my @res;
225     my $hits = $result->size;
226    
227     # for each document in result
228 dpavlin 87 for my $i ($offset .. ($offset + $on_page - 1)) {
229     last if ($i >= $hits);
230    
231 dpavlin 86 my $id = $result->get($i);
232     my $doc = $db->get_doc($id, 0);
233    
234     my $row;
235     foreach my $c (qw/fid hname sname backupnum fiilename filepath date type size/) {
236     $row->{$c} = $doc->attr($c);
237     }
238     push @res, $row;
239     }
240    
241     return ($hits, \@res);
242     }
243    
244 dpavlin 51 sub getBackupsNotBurned() {
245    
246 dpavlin 84 my $dbh = get_dbh();
247 dpavlin 53 my $sql = q{
248     SELECT
249 dpavlin 66 backups.hostID AS hostid,
250 dpavlin 53 min(hosts.name) AS host,
251 dpavlin 86 backups.num AS backupnum,
252 dpavlin 53 min(backups.type) AS type,
253 dpavlin 66 min(backups.date) AS date,
254     min(backups.size) AS size
255 dpavlin 79 FROM files
256     INNER JOIN shares ON files.shareID=shares.ID
257     INNER JOIN hosts ON hosts.ID = shares.hostID
258 dpavlin 86 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = shares.ID
259 dpavlin 53 GROUP BY
260 dpavlin 66 backups.hostID, backups.num
261 dpavlin 58 ORDER BY min(backups.date)
262 dpavlin 53 };
263     my $sth = $dbh->prepare( $sql );
264     my @ret;
265     $sth->execute();
266 dpavlin 4
267 dpavlin 66 while ( my $row = $sth->fetchrow_hashref() ) {
268     $row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
269     $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);
270     push @ret, $row;
271 dpavlin 4 }
272    
273 dpavlin 53 return @ret;
274     }
275 dpavlin 4
276     sub displayBackupsGrid()
277     {
278     my $retHTML = "";
279     my $addForm = 1;
280    
281 dpavlin 31 if ($addForm) {
282 dpavlin 4
283     $retHTML .= <<EOF3;
284     <script language="javascript" type="text/javascript">
285     <!--
286    
287     function checkAll(location)
288     {
289     for (var i=0;i<document.forma.elements.length;i++)
290     {
291     var e = document.forma.elements[i];
292     if ((e.checked || !e.checked) && e.name != \'all\') {
293     if (eval("document.forma."+location+".checked")) {
294     e.checked = true;
295     } else {
296     e.checked = false;
297     }
298     }
299     }
300     }
301     //-->
302     </script>
303     EOF3
304 dpavlin 31 $retHTML .= q{<form name="forma" method="GET" action="}."$MyURL"."?action=burn\"";
305 dpavlin 4 $retHTML.= q{<input type="hidden" value="burn" name="action">};
306     $retHTML .= q{<input type="hidden" value="results" name="search_results">};
307     }
308 dpavlin 79 $retHTML .= qq{
309 dpavlin 80 <table style="fview" border="1" cellspacing="0" cellpadding="3">
310 dpavlin 79 <tr class="tableheader">
311     };
312 dpavlin 31
313     if ($addForm) {
314 dpavlin 4 $retHTML .= "<td class=\"tableheader\"><input type=\"checkbox\" name=\"allFiles\" onClick=\"checkAll('allFiles');\"></td>";
315     }
316 dpavlin 58 $retHTML .= qq{
317 dpavlin 79 <td align="center">Host</td>
318     <td align="center">Backup no</td>
319     <td align="center">Type</td>
320     <td align="center">date</td>
321     <td align="center">age/days</td>
322     <td align="center">size/MB</td>
323 dpavlin 58 </tr>
324     };
325 dpavlin 4
326 dpavlin 31 my @backups = getBackupsNotBurned();
327     my $backup;
328    
329     if ($addForm) {
330 dpavlin 58 $retHTML .= qq{
331     <tr><td colspan=7 style="tableheader">
332 dpavlin 31 <input type="submit" value="Burn selected backups on medium" name="submitBurner">
333 dpavlin 58 </td></tr>
334     };
335 dpavlin 4 }
336 dpavlin 31
337     foreach $backup(@backups) {
338    
339     my $ftype = "";
340 dpavlin 4
341 dpavlin 31 $retHTML .= "<tr>";
342     if ($addForm) {
343 dpavlin 58 $retHTML .= '<td class="fview"><input type="checkbox" name="fcb' .
344 dpavlin 86 $backup->{'hostid'}.'_'.$backup->{'backupnum'} .
345     '" value="' . $backup->{'hostid'}.'_'.$backup->{'backupnum'} .
346 dpavlin 58 '"></td>';
347 dpavlin 31 }
348 dpavlin 4
349 dpavlin 31 $retHTML .= '<td class="fviewborder">' . $backup->{'host'} . '</td>' .
350 dpavlin 86 '<td class="fviewborder">' . $backup->{'backupnum'} . '</td>' .
351 dpavlin 31 '<td class="fviewborder">' . $backup->{'type'} . '</td>' .
352 dpavlin 58 '<td class="fviewborder">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
353     '<td class="fviewborder">' . $backup->{'age'} . '</td>' .
354 dpavlin 66 '<td class="fviewborder">' . $backup->{'size'} . '</td>' .
355 dpavlin 31 '</tr>';
356 dpavlin 4 }
357 dpavlin 31
358     $retHTML .= "</table>";
359    
360     if ($addForm) {
361     $retHTML .= "</form>";
362     }
363 dpavlin 4
364 dpavlin 31 return $retHTML;
365     }
366 dpavlin 4
367 dpavlin 86 sub displayGrid($) {
368     my ($param) = @_;
369 dpavlin 83
370     my $offset = $param->{'offset'};
371     my $hilite = $param->{'search_filename'};
372    
373 dpavlin 17 my $retHTML = "";
374    
375 dpavlin 55 my $start_t = time();
376    
377 dpavlin 86 my ($results, $files);
378 dpavlin 88 if ($param->{'use_hest'} && length($hilite) > 0) {
379 dpavlin 87 ($results, $files) = getFilesHyperEstraier($param);
380 dpavlin 86 } else {
381 dpavlin 87 ($results, $files) = getFiles($param);
382 dpavlin 86 }
383 dpavlin 31
384 dpavlin 55 my $dur_t = time() - $start_t;
385     my $dur = sprintf("%0.4fs", $dur_t);
386    
387 dpavlin 31 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
388    
389 dpavlin 59 if ($results <= 0) {
390     $retHTML .= qq{
391     <p style="color: red;">No results found...</p>
392     };
393     return $retHTML;
394     } else {
395     # DEBUG
396     #use Data::Dumper;
397     #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
398     }
399    
400    
401 dpavlin 17 $retHTML .= qq{
402 dpavlin 79 <div>
403     Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
404     </div>
405     <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
406     <tr class="fviewheader">
407 dpavlin 87 <td></td>
408 dpavlin 79 <td align="center">Share</td>
409     <td align="center">Type and Name</td>
410     <td align="center">#</td>
411     <td align="center">Size</td>
412     <td align="center">Date</td>
413     <td align="center">Media</td>
414 dpavlin 17 </tr>
415     };
416 dpavlin 31
417 dpavlin 17 my $file;
418 dpavlin 4
419 dpavlin 17 sub hilite_html($$) {
420     my ($html, $search) = @_;
421     $html =~ s#($search)#<b>$1</b>#gis;
422     return $html;
423 dpavlin 4 }
424 dpavlin 9
425 dpavlin 26 sub restore_link($$$$$$) {
426     my $type = shift;
427     my $action = 'RestoreFile';
428     $action = 'browse' if (lc($type) eq 'dir');
429     return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
430     }
431    
432 dpavlin 87 my $i = $offset * $on_page;
433    
434 dpavlin 31 foreach $file (@{ $files }) {
435 dpavlin 87 $i++;
436    
437 dpavlin 24 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
438 dpavlin 79 $retHTML .= qq{<tr class="fviewborder">};
439 dpavlin 9
440 dpavlin 88 $retHTML .= qq{<td class="fviewborder">$i</td>};
441 dpavlin 87
442 dpavlin 79 $retHTML .=
443 dpavlin 86 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
444     qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
445     qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
446 dpavlin 79 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
447     qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
448 dpavlin 87 qq{<td class="fviewborder">} . '?' . qq{</td>};
449 dpavlin 9
450 dpavlin 17 $retHTML .= "</tr>";
451     }
452     $retHTML .= "</table>";
453    
454 dpavlin 31 # all variables which has to be transfered
455     foreach my $n (qw/search_day_from search_month_from search_year_from search_day_to search_month_to search_year_to search_backup_day_from search_backup_month_from search_backup_year_from search_backup_day_to search_backup_month_to search_backup_year_to search_filename offset/) {
456     $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
457     }
458 dpavlin 17
459 dpavlin 31 my $del = '';
460     my $max_page = int( $results / $on_page );
461     my $page = 0;
462    
463 dpavlin 85 sub page_link($$$) {
464     my ($param,$page,$display) = @_;
465 dpavlin 31
466 dpavlin 85 $param->{'offset'} = $page;
467    
468     my $html = '<a href = "' . $MyURL;
469     my $del = '?';
470     foreach my $k (keys %{ $param }) {
471     if ($param->{$k}) {
472     $html .= $del . $k . '=' . ${EscURI( $param->{$k} )};
473     $del = '&';
474     }
475     }
476     $html .= '">' . $display . '</a>';
477     }
478    
479 dpavlin 31 $retHTML .= '<div style="text-align: center;">';
480    
481     if ($offset > 0) {
482 dpavlin 85 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
483 dpavlin 31 }
484    
485     while ($page <= $max_page) {
486     if ($page == $offset) {
487     $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
488     } else {
489 dpavlin 85 $retHTML .= $del . page_link($param, $page, $page + 1);
490 dpavlin 17 }
491 dpavlin 31
492     if ($page < $offset - $pager_pages && $page != 0) {
493     $retHTML .= " ... ";
494     $page = $offset - $pager_pages;
495     $del = '';
496     } elsif ($page > $offset + $pager_pages && $page != $max_page) {
497     $retHTML .= " ... ";
498     $page = $max_page;
499     $del = '';
500     } else {
501     $del = ' | ';
502     $page++;
503     }
504 dpavlin 17 }
505    
506 dpavlin 31 if ($offset < $max_page) {
507 dpavlin 85 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
508 dpavlin 31 }
509    
510     $retHTML .= "</div>";
511    
512 dpavlin 17 return $retHTML;
513     }
514 dpavlin 4
515     1;

  ViewVC Help
Powered by ViewVC 1.1.26