/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 102 - (show annotations)
Tue Aug 30 22:43:01 2005 UTC (18 years, 8 months ago) by dpavlin
File size: 13012 byte(s)
added share, nicer html

1 #!/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 use DateTime;
9 use vars qw(%In $MyURL);
10 use Time::HiRes qw/time/;
11
12 my $on_page = 100;
13 my $pager_pages = 10;
14
15 my $dsn = $Conf{SearchDSN};
16 my $db_user = $Conf{SearchUser} || '';
17
18 my $index_path = $Conf{HyperEstraierIndex};
19 if ($index_path) {
20 $index_path = $TopDir . '/' . $index_path;
21 $index_path =~ s#//#/#g;
22 }
23
24 my $dbh;
25
26 sub get_dbh {
27 $dbh ||= DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
28 return $dbh;
29 }
30
31 sub getUnits() {
32 my @ret;
33
34 my $dbh = get_dbh();
35 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 $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 }
51
52 sub epoch_to_iso {
53 my $t = shift || return;
54 my $iso = BackupPC::Lib::timeStamp(undef, $t);
55 $iso =~ s/\s/ /g;
56 return $iso;
57 }
58
59 sub dates_from_form($) {
60 my $param = shift || return;
61
62 sub mk_epoch_date($$) {
63 my ($name,$suffix) = @_;
64
65 my $yyyy = $param->{ $name . '_year_' . $suffix} || return undef;
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
71 $yyyy =~ s/\D//g;
72 $mm =~ s/\D//g;
73 $dd =~ s/\D//g;
74
75 my $dt = new DateTime(
76 year => $yyyy,
77 month => $mm,
78 day => $dd
79 );
80 print STDERR "mk_epoch_date($name,$suffix) [$yyyy-$mm-$dd] = " . $dt->ymd . " " . $dt->hms . "\n";
81 return $dt->epoch || 'NULL';
82 }
83
84 my @ret = (
85 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
91 return @ret;
92
93 }
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 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
107 print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" | ",@conditions);
108
109 push( @conditions, ' files.shareid = ' . $param->{'search_share'} ) if ($param->{'search_share'});
110 push (@conditions, " upper(files.path) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});
111
112 return join(" and ", @conditions);
113 }
114
115
116 sub getFiles($) {
117 my ($param) = @_;
118
119 my $offset = $param->{'offset'} || 0;
120 $offset *= $on_page;
121
122 my $dbh = get_dbh();
123
124 my $sql_cols = qq{
125 files.id AS fid,
126 hosts.name AS hname,
127 shares.name AS sname,
128 files.backupnum AS backupnum,
129 files.path AS filepath,
130 files.date AS date,
131 files.type AS type,
132 files.size AS size
133 };
134
135 my $sql_from = qq{
136 FROM files
137 INNER JOIN shares ON files.shareID=shares.ID
138 INNER JOIN hosts ON hosts.ID = shares.hostID
139 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = files.shareID
140 };
141
142 my $sql_where;
143 my $where = getWhere($param);
144 $sql_where = " WHERE ". $where if ($where);
145
146 my $sql_order = qq{
147 ORDER BY files.date
148 LIMIT $on_page
149 OFFSET ?
150 };
151
152 my $sql_count = qq{ select count(files.id) $sql_from $sql_where };
153 my $sql_results = qq{ select $sql_cols $sql_from $sql_where $sql_order };
154
155 my $sth = $dbh->prepare($sql_count);
156 $sth->execute();
157 my ($results) = $sth->fetchrow_array();
158
159 $sth = $dbh->prepare($sql_results);
160 $sth->execute( $offset );
161
162 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 my @ret;
169
170 while (my $row = $sth->fetchrow_hashref()) {
171 push @ret, $row;
172 }
173
174 $sth->finish();
175 return ($results, \@ret);
176 }
177
178 sub getFilesHyperEstraier($) {
179 my ($param) = @_;
180
181 my $offset = $param->{'offset'} || 0;
182 $offset *= $on_page;
183
184 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 (length($q) > 0) {
199 # exact match
200 $cond->add_attr("filepath ISTRINC $q");
201
202 $q =~ s/(.)/$1 /g;
203 # set the search phrase to the search condition object
204 $cond->set_phrase($q);
205 }
206
207 my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
208
209 $cond->add_attr("backup_date NUMGE $backup_from") if ($backup_from);
210 $cond->add_attr("backup_date NUMLE $backup_to") if ($backup_to);
211
212 $cond->add_attr("date NUMGE $files_from") if ($files_from);
213 $cond->add_attr("date NUMLE $files_to") if ($files_to);
214
215 $cond->add_attr("shareid NUMEQ $shareid") if ($shareid);
216
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 for my $i ($offset .. ($offset + $on_page - 1)) {
229 last if ($i >= $hits);
230
231 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 sub getBackupsNotBurned() {
245
246 my $dbh = get_dbh();
247 my $sql = q{
248 SELECT
249 backups.hostID AS hostid,
250 min(hosts.name) AS host,
251 min(shares.name) AS share,
252 backups.num AS backupnum,
253 min(backups.type) AS type,
254 min(backups.date) AS date,
255 min(backups.size) AS size
256 FROM files
257 INNER JOIN shares ON files.shareID=shares.ID
258 INNER JOIN hosts ON hosts.ID = shares.hostID
259 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = shares.ID
260 GROUP BY
261 backups.hostID, backups.num, backups.shareid
262 ORDER BY min(backups.date)
263 };
264 my $sth = $dbh->prepare( $sql );
265 my @ret;
266 $sth->execute();
267
268 while ( my $row = $sth->fetchrow_hashref() ) {
269 $row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
270 $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);
271 push @ret, $row;
272 }
273
274 return @ret;
275 }
276
277 sub displayBackupsGrid()
278 {
279 my $retHTML = "";
280
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 $retHTML .= q{
303 <form name="forma" method="GET" action="$MyURL?action=burn">
304 <input type="hidden" value="burn" name="action">
305 <input type="hidden" value="results" name="search_results">
306 <table style="fview" border="0" cellspacing="0" cellpadding="2">
307 <tr class="tableheader">
308 <td class="tableheader">
309 <input type="checkbox" name="allFiles" onClick="checkAll('allFiles');">
310 </td>
311 <td align="center">Share</td>
312 <td align="center">Backup no</td>
313 <td align="center">Type</td>
314 <td align="center">date</td>
315 <td align="center">age/days</td>
316 <td align="center">size/MB</td>
317 </tr>
318
319 <tr><td colspan=7 style="tableheader">
320 <input type="submit" value="Burn selected backups on medium" name="submitBurner">
321 </td></tr>
322 };
323
324 my @color = (' bgcolor="#e0e0e0"', '');
325
326 my $i = 0;
327 my $host = '';
328
329 foreach my $backup ( getBackupsNotBurned() ) {
330
331 if ($host ne $backup->{'host'}) {
332 $i++;
333 $host = $backup->{'host'};
334 }
335 my $ftype = "";
336
337 $retHTML .= "<tr" . $color[$i %2 ] . ">";
338 $retHTML .= '<td class="fview"><input type="checkbox" name="fcb' .
339 $backup->{'hostid'}.'_'.$backup->{'backupnum'} .
340 '" value="' . $backup->{'hostid'}.'_'.$backup->{'backupnum'} .
341 '"></td>';
342
343 $retHTML .=
344 '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .
345 '<td align="center">' . $backup->{'backupnum'} . '</td>' .
346 '<td align="center">' . $backup->{'type'} . '</td>' .
347 '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
348 '<td align="center">' . $backup->{'age'} . '</td>' .
349 '<td align="right">' . $backup->{'size'} . '</td>' .
350 "</tr>\n";
351
352
353 }
354
355 $retHTML .= "</table>";
356 $retHTML .= "</form>";
357
358 return $retHTML;
359 }
360
361 sub displayGrid($) {
362 my ($param) = @_;
363
364 my $offset = $param->{'offset'};
365 my $hilite = $param->{'search_filename'};
366
367 my $retHTML = "";
368
369 my $start_t = time();
370
371 my ($results, $files);
372 if ($param->{'use_hest'} && length($hilite) > 0) {
373 ($results, $files) = getFilesHyperEstraier($param);
374 } else {
375 ($results, $files) = getFiles($param);
376 }
377
378 my $dur_t = time() - $start_t;
379 my $dur = sprintf("%0.4fs", $dur_t);
380
381 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
382
383 if ($results <= 0) {
384 $retHTML .= qq{
385 <p style="color: red;">No results found...</p>
386 };
387 return $retHTML;
388 } else {
389 # DEBUG
390 #use Data::Dumper;
391 #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
392 }
393
394
395 $retHTML .= qq{
396 <div>
397 Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
398 </div>
399 <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
400 <tr class="fviewheader">
401 <td></td>
402 <td align="center">Share</td>
403 <td align="center">Type and Name</td>
404 <td align="center">#</td>
405 <td align="center">Size</td>
406 <td align="center">Date</td>
407 <td align="center">Media</td>
408 </tr>
409 };
410
411 my $file;
412
413 sub hilite_html($$) {
414 my ($html, $search) = @_;
415 $html =~ s#($search)#<b>$1</b>#gis;
416 return $html;
417 }
418
419 sub restore_link($$$$$$) {
420 my $type = shift;
421 my $action = 'RestoreFile';
422 $action = 'browse' if (lc($type) eq 'dir');
423 return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
424 }
425
426 my $i = $offset * $on_page;
427
428 foreach $file (@{ $files }) {
429 $i++;
430
431 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
432 $retHTML .= qq{<tr class="fviewborder">};
433
434 $retHTML .= qq{<td class="fviewborder">$i</td>};
435
436 $retHTML .=
437 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
438 qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
439 qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
440 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
441 qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
442 qq{<td class="fviewborder">} . '?' . qq{</td>};
443
444 $retHTML .= "</tr>";
445 }
446 $retHTML .= "</table>";
447
448 # all variables which has to be transfered
449 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/) {
450 $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
451 }
452
453 my $del = '';
454 my $max_page = int( $results / $on_page );
455 my $page = 0;
456
457 sub page_link($$$) {
458 my ($param,$page,$display) = @_;
459
460 $param->{'offset'} = $page;
461
462 my $html = '<a href = "' . $MyURL;
463 my $del = '?';
464 foreach my $k (keys %{ $param }) {
465 if ($param->{$k}) {
466 $html .= $del . $k . '=' . ${EscURI( $param->{$k} )};
467 $del = '&';
468 }
469 }
470 $html .= '">' . $display . '</a>';
471 }
472
473 $retHTML .= '<div style="text-align: center;">';
474
475 if ($offset > 0) {
476 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
477 }
478
479 while ($page <= $max_page) {
480 if ($page == $offset) {
481 $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
482 } else {
483 $retHTML .= $del . page_link($param, $page, $page + 1);
484 }
485
486 if ($page < $offset - $pager_pages && $page != 0) {
487 $retHTML .= " ... ";
488 $page = $offset - $pager_pages;
489 $del = '';
490 } elsif ($page > $offset + $pager_pages && $page != $max_page) {
491 $retHTML .= " ... ";
492 $page = $max_page;
493 $del = '';
494 } else {
495 $del = ' | ';
496 $page++;
497 }
498 }
499
500 if ($offset < $max_page) {
501 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
502 }
503
504 $retHTML .= "</div>";
505
506 return $retHTML;
507 }
508
509 1;

  ViewVC Help
Powered by ViewVC 1.1.26