/[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 87 - (hide annotations)
Sun Aug 28 14:05:08 2005 UTC (18 years, 8 months ago) by dpavlin
File size: 13005 byte(s)
bug fixes: date limit now works again, correct number of displayed results,
added SQL script to remove unneeded columns, dates only selection now
works with HyperEstraier (but, it's MUCH SLOWER than from database),
added ordinal number of result

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     if ($q) {
199     $q =~ s/(.)/$1 /g;
200    
201     # set the search phrase to the search condition object
202     $cond->set_phrase($q);
203 dpavlin 87 }
204 dpavlin 86
205 dpavlin 87 my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
206 dpavlin 86
207 dpavlin 87 $cond->add_attr("backup_date NUMGE $backup_from") if ($backup_from);
208     $cond->add_attr("backup_date NUMLE $backup_to") if ($backup_to);
209 dpavlin 86
210 dpavlin 87 $cond->add_attr("date NUMGE $files_from") if ($files_from);
211     $cond->add_attr("date NUMLE $files_to") if ($files_to);
212 dpavlin 86
213 dpavlin 87 $cond->add_attr("shareid NUMEQ $shareid") if ($shareid);
214 dpavlin 86
215     # $cond->set_max( $offset + $on_page );
216     $cond->set_options( $HyperEstraier::Condition::SURE );
217     $cond->set_order( 'date NUMA' );
218    
219     # get the result of search
220     my $result = $db->search($cond, 0);
221    
222     my @res;
223     my $hits = $result->size;
224    
225     # for each document in result
226 dpavlin 87 for my $i ($offset .. ($offset + $on_page - 1)) {
227     last if ($i >= $hits);
228    
229 dpavlin 86 my $id = $result->get($i);
230     my $doc = $db->get_doc($id, 0);
231    
232     my $row;
233     foreach my $c (qw/fid hname sname backupnum fiilename filepath date type size/) {
234     $row->{$c} = $doc->attr($c);
235     }
236     push @res, $row;
237     }
238    
239     return ($hits, \@res);
240     }
241    
242 dpavlin 51 sub getBackupsNotBurned() {
243    
244 dpavlin 84 my $dbh = get_dbh();
245 dpavlin 53 my $sql = q{
246     SELECT
247 dpavlin 66 backups.hostID AS hostid,
248 dpavlin 53 min(hosts.name) AS host,
249 dpavlin 86 backups.num AS backupnum,
250 dpavlin 53 min(backups.type) AS type,
251 dpavlin 66 min(backups.date) AS date,
252     min(backups.size) AS size
253 dpavlin 79 FROM files
254     INNER JOIN shares ON files.shareID=shares.ID
255     INNER JOIN hosts ON hosts.ID = shares.hostID
256 dpavlin 86 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = shares.ID
257 dpavlin 53 GROUP BY
258 dpavlin 66 backups.hostID, backups.num
259 dpavlin 58 ORDER BY min(backups.date)
260 dpavlin 53 };
261     my $sth = $dbh->prepare( $sql );
262     my @ret;
263     $sth->execute();
264 dpavlin 4
265 dpavlin 66 while ( my $row = $sth->fetchrow_hashref() ) {
266     $row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
267     $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);
268     push @ret, $row;
269 dpavlin 4 }
270    
271 dpavlin 53 return @ret;
272     }
273 dpavlin 4
274     sub displayBackupsGrid()
275     {
276     my $retHTML = "";
277     my $addForm = 1;
278    
279 dpavlin 31 if ($addForm) {
280 dpavlin 4
281     $retHTML .= <<EOF3;
282     <script language="javascript" type="text/javascript">
283     <!--
284    
285     function checkAll(location)
286     {
287     for (var i=0;i<document.forma.elements.length;i++)
288     {
289     var e = document.forma.elements[i];
290     if ((e.checked || !e.checked) && e.name != \'all\') {
291     if (eval("document.forma."+location+".checked")) {
292     e.checked = true;
293     } else {
294     e.checked = false;
295     }
296     }
297     }
298     }
299     //-->
300     </script>
301     EOF3
302 dpavlin 31 $retHTML .= q{<form name="forma" method="GET" action="}."$MyURL"."?action=burn\"";
303 dpavlin 4 $retHTML.= q{<input type="hidden" value="burn" name="action">};
304     $retHTML .= q{<input type="hidden" value="results" name="search_results">};
305     }
306 dpavlin 79 $retHTML .= qq{
307 dpavlin 80 <table style="fview" border="1" cellspacing="0" cellpadding="3">
308 dpavlin 79 <tr class="tableheader">
309     };
310 dpavlin 31
311     if ($addForm) {
312 dpavlin 4 $retHTML .= "<td class=\"tableheader\"><input type=\"checkbox\" name=\"allFiles\" onClick=\"checkAll('allFiles');\"></td>";
313     }
314 dpavlin 58 $retHTML .= qq{
315 dpavlin 79 <td align="center">Host</td>
316     <td align="center">Backup no</td>
317     <td align="center">Type</td>
318     <td align="center">date</td>
319     <td align="center">age/days</td>
320     <td align="center">size/MB</td>
321 dpavlin 58 </tr>
322     };
323 dpavlin 4
324 dpavlin 31 my @backups = getBackupsNotBurned();
325     my $backup;
326    
327     if ($addForm) {
328 dpavlin 58 $retHTML .= qq{
329     <tr><td colspan=7 style="tableheader">
330 dpavlin 31 <input type="submit" value="Burn selected backups on medium" name="submitBurner">
331 dpavlin 58 </td></tr>
332     };
333 dpavlin 4 }
334 dpavlin 31
335     foreach $backup(@backups) {
336    
337     my $ftype = "";
338 dpavlin 4
339 dpavlin 31 $retHTML .= "<tr>";
340     if ($addForm) {
341 dpavlin 58 $retHTML .= '<td class="fview"><input type="checkbox" name="fcb' .
342 dpavlin 86 $backup->{'hostid'}.'_'.$backup->{'backupnum'} .
343     '" value="' . $backup->{'hostid'}.'_'.$backup->{'backupnum'} .
344 dpavlin 58 '"></td>';
345 dpavlin 31 }
346 dpavlin 4
347 dpavlin 31 $retHTML .= '<td class="fviewborder">' . $backup->{'host'} . '</td>' .
348 dpavlin 86 '<td class="fviewborder">' . $backup->{'backupnum'} . '</td>' .
349 dpavlin 31 '<td class="fviewborder">' . $backup->{'type'} . '</td>' .
350 dpavlin 58 '<td class="fviewborder">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
351     '<td class="fviewborder">' . $backup->{'age'} . '</td>' .
352 dpavlin 66 '<td class="fviewborder">' . $backup->{'size'} . '</td>' .
353 dpavlin 31 '</tr>';
354 dpavlin 4 }
355 dpavlin 31
356     $retHTML .= "</table>";
357    
358     if ($addForm) {
359     $retHTML .= "</form>";
360     }
361 dpavlin 4
362 dpavlin 31 return $retHTML;
363     }
364 dpavlin 4
365 dpavlin 86 sub displayGrid($) {
366     my ($param) = @_;
367 dpavlin 83
368     my $offset = $param->{'offset'};
369     my $hilite = $param->{'search_filename'};
370    
371 dpavlin 17 my $retHTML = "";
372    
373 dpavlin 55 my $start_t = time();
374    
375 dpavlin 86 my ($results, $files);
376     if ($param->{'use_hest'}) {
377 dpavlin 87 ($results, $files) = getFilesHyperEstraier($param);
378 dpavlin 86 } else {
379 dpavlin 87 ($results, $files) = getFiles($param);
380 dpavlin 86 }
381 dpavlin 31
382 dpavlin 55 my $dur_t = time() - $start_t;
383     my $dur = sprintf("%0.4fs", $dur_t);
384    
385 dpavlin 31 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
386    
387 dpavlin 59 if ($results <= 0) {
388     $retHTML .= qq{
389     <p style="color: red;">No results found...</p>
390     };
391     return $retHTML;
392     } else {
393     # DEBUG
394     #use Data::Dumper;
395     #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
396     }
397    
398    
399 dpavlin 17 $retHTML .= qq{
400 dpavlin 79 <div>
401     Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
402     </div>
403     <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
404     <tr class="fviewheader">
405 dpavlin 87 <td></td>
406 dpavlin 79 <td align="center">Share</td>
407     <td align="center">Type and Name</td>
408     <td align="center">#</td>
409     <td align="center">Size</td>
410     <td align="center">Date</td>
411     <td align="center">Media</td>
412 dpavlin 17 </tr>
413     };
414 dpavlin 31
415 dpavlin 17 my $file;
416 dpavlin 4
417 dpavlin 17 sub hilite_html($$) {
418     my ($html, $search) = @_;
419     $html =~ s#($search)#<b>$1</b>#gis;
420     return $html;
421 dpavlin 4 }
422 dpavlin 9
423 dpavlin 26 sub restore_link($$$$$$) {
424     my $type = shift;
425     my $action = 'RestoreFile';
426     $action = 'browse' if (lc($type) eq 'dir');
427     return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
428     }
429    
430 dpavlin 87 my $i = $offset * $on_page;
431    
432 dpavlin 31 foreach $file (@{ $files }) {
433 dpavlin 87 $i++;
434    
435 dpavlin 24 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
436 dpavlin 79 $retHTML .= qq{<tr class="fviewborder">};
437 dpavlin 9
438 dpavlin 87 $retHTML .= qq{<td>$i</td>};
439    
440 dpavlin 79 $retHTML .=
441 dpavlin 86 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
442     qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
443     qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
444 dpavlin 79 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
445     qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
446 dpavlin 87 qq{<td class="fviewborder">} . '?' . qq{</td>};
447 dpavlin 9
448 dpavlin 17 $retHTML .= "</tr>";
449     }
450     $retHTML .= "</table>";
451    
452 dpavlin 31 # all variables which has to be transfered
453     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/) {
454     $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
455     }
456 dpavlin 17
457 dpavlin 31 my $del = '';
458     my $max_page = int( $results / $on_page );
459     my $page = 0;
460    
461 dpavlin 85 sub page_link($$$) {
462     my ($param,$page,$display) = @_;
463 dpavlin 31
464 dpavlin 85 $param->{'offset'} = $page;
465    
466     my $html = '<a href = "' . $MyURL;
467     my $del = '?';
468     foreach my $k (keys %{ $param }) {
469     if ($param->{$k}) {
470     $html .= $del . $k . '=' . ${EscURI( $param->{$k} )};
471     $del = '&';
472     }
473     }
474     $html .= '">' . $display . '</a>';
475     }
476    
477 dpavlin 31 $retHTML .= '<div style="text-align: center;">';
478    
479     if ($offset > 0) {
480 dpavlin 85 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
481 dpavlin 31 }
482    
483     while ($page <= $max_page) {
484     if ($page == $offset) {
485     $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
486     } else {
487 dpavlin 85 $retHTML .= $del . page_link($param, $page, $page + 1);
488 dpavlin 17 }
489 dpavlin 31
490     if ($page < $offset - $pager_pages && $page != 0) {
491     $retHTML .= " ... ";
492     $page = $offset - $pager_pages;
493     $del = '';
494     } elsif ($page > $offset + $pager_pages && $page != $max_page) {
495     $retHTML .= " ... ";
496     $page = $max_page;
497     $del = '';
498     } else {
499     $del = ' | ';
500     $page++;
501     }
502 dpavlin 17 }
503    
504 dpavlin 31 if ($offset < $max_page) {
505 dpavlin 85 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
506 dpavlin 31 }
507    
508     $retHTML .= "</div>";
509    
510 dpavlin 17 return $retHTML;
511     }
512 dpavlin 4
513     1;

  ViewVC Help
Powered by ViewVC 1.1.26