/[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 86 - (hide annotations)
Sun Aug 28 12:35:59 2005 UTC (18 years, 8 months ago) by dpavlin
File size: 12976 byte(s)
first cut at implemeting HyperEstraier search,
shares are now formated like host:share, fix date display,
initial cut at removing unneeded database columns,
rename all fields to comply with database columns

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 19 my $yyyy = $param->{ $name . '_year_' . $suffix} || return;
66     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 51 my $dt = new DateTime(
71     year => $yyyy,
72     month => $mm,
73     day => $dd
74     );
75     return $dt->epoch || 'NULL';
76 dpavlin 19 }
77 dpavlin 4
78 dpavlin 83 return (
79     mk_epoch_date('search_backup', 'from'),
80     mk_epoch_date('search_backup', 'to'),
81     mk_epoch_date('search', 'from'),
82     mk_epoch_date('search', 'to'),
83     );
84     }
85    
86    
87     sub getWhere($) {
88     my $param = shift || return;
89    
90     my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
91    
92     my @conditions;
93 dpavlin 51 push @conditions, qq{ backups.date >= $backup_from } if ($backup_from);
94     push @conditions, qq{ backups.date <= $backup_to } if ($backup_to);
95     push @conditions, qq{ files.date >= $files_from } if ($files_from);
96     push @conditions, qq{ files.date <= $files_to } if ($files_to);
97 dpavlin 19
98 dpavlin 59 print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" | ",@conditions);
99 dpavlin 83
100 dpavlin 60 push( @conditions, ' files.shareid = ' . $param->{'search_share'} ) if ($param->{'search_share'});
101 dpavlin 62 push (@conditions, " upper(files.path) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});
102 dpavlin 19
103 dpavlin 83 return join(" and ", @conditions);
104 dpavlin 4 }
105    
106 dpavlin 19
107 dpavlin 31 sub getFiles($$) {
108 dpavlin 83 my ($param, $offset) = @_;
109 dpavlin 31
110 dpavlin 84 my $dbh = get_dbh();
111 dpavlin 31
112     my $sql_cols = qq{
113     files.id AS fid,
114     hosts.name AS hname,
115     shares.name AS sname,
116 dpavlin 86 -- shares.share AS sharename,
117     files.backupnum AS backupnum,
118     -- files.name AS filename,
119 dpavlin 31 files.path AS filepath,
120 dpavlin 51 files.date AS date,
121 dpavlin 86 files.type AS type,
122 dpavlin 31 files.size AS size,
123 dpavlin 79 -- dvds.name AS dvd
124     null AS dvd
125 dpavlin 31 };
126    
127     my $sql_from = qq{
128 dpavlin 16 FROM files
129     INNER JOIN shares ON files.shareID=shares.ID
130     INNER JOIN hosts ON hosts.ID = shares.hostID
131 dpavlin 86 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = shares.ID
132 dpavlin 55 };
133    
134     my $sql_dvd_from = qq{
135 dpavlin 79 -- LEFT JOIN dvds ON dvds.ID = files.dvdid
136 dpavlin 31 };
137 dpavlin 4
138 dpavlin 31 my $sql_where;
139 dpavlin 83 my $where = getWhere($param);
140 dpavlin 31 $sql_where = " WHERE ". $where if ($where);
141 dpavlin 4
142 dpavlin 31 my $sql_order = qq{
143 dpavlin 64 ORDER BY files.date
144 dpavlin 59 LIMIT $on_page
145     OFFSET ?
146 dpavlin 9 };
147 dpavlin 31
148 dpavlin 59 my $sql_count = qq{ select count(files.id) $sql_from $sql_where };
149     my $sql_results = qq{ select $sql_cols $sql_from $sql_dvd_from $sql_where $sql_order };
150    
151 dpavlin 31 $offset ||= 0;
152 dpavlin 59 $offset = ($offset * $on_page);
153 dpavlin 31
154 dpavlin 59 my $sth = $dbh->prepare($sql_count);
155 dpavlin 31 $sth->execute();
156     my ($results) = $sth->fetchrow_array();
157    
158 dpavlin 59 $sth = $dbh->prepare($sql_results);
159 dpavlin 31 $sth->execute( $offset );
160    
161 dpavlin 59 if ($sth->rows != $results) {
162     my $bug = "$0 BUG: [[ $sql_count ]] = $results while [[ $sql_results ]] = " . $sth->rows;
163     $bug =~ s/\s+/ /gs;
164     print STDERR "$bug\n";
165     }
166    
167 dpavlin 31 my @ret;
168 dpavlin 4
169 dpavlin 31 while (my $row = $sth->fetchrow_hashref()) {
170 dpavlin 86 push @ret, $row;
171 dpavlin 4 }
172 dpavlin 59
173 dpavlin 31 $sth->finish();
174     return ($results, \@ret);
175     }
176 dpavlin 4
177 dpavlin 86 sub getFilesHyperEstraier($$) {
178     my ($param, $offset) = @_;
179    
180     die "no index_path?" unless ($index_path);
181    
182     use HyperEstraier;
183    
184     # open the database
185     my $db = HyperEstraier::Database->new();
186     $db->open($index_path, $HyperEstraier::ESTDBREADER);
187    
188     # create a search condition object
189     my $cond = HyperEstraier::Condition->new();
190    
191     my $q = $param->{'search_filename'};
192     my $shareid = $param->{'search_share'};
193    
194     if ($q) {
195     $q =~ s/(.)/$1 /g;
196    
197     # set the search phrase to the search condition object
198     $cond->set_phrase($q);
199    
200     my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
201    
202     $cond->add_attr("backup_date NUMGE $backup_from") if ($backup_from);
203     $cond->add_attr("backup_date NUMLE $backup_to") if ($backup_to);
204    
205     $cond->add_attr("date NUMGE $files_from") if ($files_from);
206     $cond->add_attr("date NUMLE $files_to") if ($files_to);
207    
208     $cond->add_attr("shareid NUMEQ $shareid") if ($shareid);
209     }
210    
211     $offset ||= 0;
212     $offset = ($offset * $on_page);
213    
214     # $cond->set_max( $offset + $on_page );
215     $cond->set_options( $HyperEstraier::Condition::SURE );
216     $cond->set_order( 'date NUMA' );
217    
218     # get the result of search
219     my $result = $db->search($cond, 0);
220     $result->get(0);
221    
222     my @res;
223     my $hits = $result->size;
224    
225     # for each document in result
226     for my $i ($offset .. $result->size-1) {
227     my $id = $result->get($i);
228     my $doc = $db->get_doc($id, 0);
229    
230     my $row;
231     foreach my $c (qw/fid hname sname backupnum fiilename filepath date type size/) {
232     $row->{$c} = $doc->attr($c);
233     }
234     push @res, $row;
235     }
236    
237     return ($hits, \@res);
238     }
239    
240 dpavlin 51 sub getBackupsNotBurned() {
241    
242 dpavlin 84 my $dbh = get_dbh();
243 dpavlin 53 my $sql = q{
244     SELECT
245 dpavlin 66 backups.hostID AS hostid,
246 dpavlin 53 min(hosts.name) AS host,
247 dpavlin 86 backups.num AS backupnum,
248 dpavlin 53 min(backups.type) AS type,
249 dpavlin 66 min(backups.date) AS date,
250     min(backups.size) AS size
251 dpavlin 79 FROM files
252     INNER JOIN shares ON files.shareID=shares.ID
253     INNER JOIN hosts ON hosts.ID = shares.hostID
254 dpavlin 86 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = shares.ID
255 dpavlin 53 WHERE
256     files.dvdid IS NULL
257     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     ($results, $files) = getFilesHyperEstraier($param, $offset);
378     } else {
379     ($results, $files) = getFiles($param, $offset);
380     }
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     <td align="center">Share</td>
406     <td align="center">Type and Name</td>
407     <td align="center">#</td>
408     <td align="center">Size</td>
409     <td align="center">Date</td>
410     <td align="center">Media</td>
411 dpavlin 17 </tr>
412     };
413 dpavlin 31
414 dpavlin 17 my $file;
415 dpavlin 4
416 dpavlin 17 sub hilite_html($$) {
417     my ($html, $search) = @_;
418     $html =~ s#($search)#<b>$1</b>#gis;
419     return $html;
420 dpavlin 4 }
421 dpavlin 9
422 dpavlin 26 sub restore_link($$$$$$) {
423     my $type = shift;
424     my $action = 'RestoreFile';
425     $action = 'browse' if (lc($type) eq 'dir');
426     return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
427     }
428    
429 dpavlin 31 foreach $file (@{ $files }) {
430 dpavlin 24 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
431 dpavlin 79 $retHTML .= qq{<tr class="fviewborder">};
432 dpavlin 9
433 dpavlin 79 $retHTML .=
434 dpavlin 86 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
435     qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
436     qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
437 dpavlin 79 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
438     qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
439     qq{<td class="fviewborder">} . $file->{'dvd'} . qq{</td>};
440 dpavlin 9
441 dpavlin 17 $retHTML .= "</tr>";
442     }
443     $retHTML .= "</table>";
444    
445 dpavlin 31 # all variables which has to be transfered
446     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/) {
447     $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
448     }
449 dpavlin 17
450 dpavlin 31 my $del = '';
451     my $max_page = int( $results / $on_page );
452     my $page = 0;
453    
454 dpavlin 85 sub page_link($$$) {
455     my ($param,$page,$display) = @_;
456 dpavlin 31
457 dpavlin 85 $param->{'offset'} = $page;
458    
459     my $html = '<a href = "' . $MyURL;
460     my $del = '?';
461     foreach my $k (keys %{ $param }) {
462     if ($param->{$k}) {
463     $html .= $del . $k . '=' . ${EscURI( $param->{$k} )};
464     $del = '&';
465     }
466     }
467     $html .= '">' . $display . '</a>';
468     }
469    
470 dpavlin 31 $retHTML .= '<div style="text-align: center;">';
471    
472     if ($offset > 0) {
473 dpavlin 85 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
474 dpavlin 31 }
475    
476     while ($page <= $max_page) {
477     if ($page == $offset) {
478     $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
479     } else {
480 dpavlin 85 $retHTML .= $del . page_link($param, $page, $page + 1);
481 dpavlin 17 }
482 dpavlin 31
483     if ($page < $offset - $pager_pages && $page != 0) {
484     $retHTML .= " ... ";
485     $page = $offset - $pager_pages;
486     $del = '';
487     } elsif ($page > $offset + $pager_pages && $page != $max_page) {
488     $retHTML .= " ... ";
489     $page = $max_page;
490     $del = '';
491     } else {
492     $del = ' | ';
493     $page++;
494     }
495 dpavlin 17 }
496    
497 dpavlin 31 if ($offset < $max_page) {
498 dpavlin 85 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
499 dpavlin 31 }
500    
501     $retHTML .= "</div>";
502    
503 dpavlin 17 return $retHTML;
504     }
505 dpavlin 4
506     1;

  ViewVC Help
Powered by ViewVC 1.1.26