#!/usr/bin/perl -w
-my $bresto_enable = 0;
+my $bresto_enable = 1;
die "bresto is not enabled" if (not $bresto_enable);
=head1 LICENSE
sub get_root
{
- my ($self, $dir) = @_;
+ my ($self) = @_;
return $self->get_pathid('');
}
return \@return_list;
}
+# TODO : we want be able to restore files from a bad ended backup
+# we have JobStatus IN ('T', 'A', 'E') and we must
+
+# Data acces subs from here. Interaction with SGBD and caching
+
+# This sub retrieves the list of jobs corresponding to the jobs selected in the
+# GUI and stores them in @CurrentJobIds.
+# date must be quoted
+sub set_job_ids_for_date
+{
+ my ($self, $client, $date)=@_;
+
+ if (!$client or !$date) {
+ return ();
+ }
+
+ # The algorithm : for a client, we get all the backups for each
+ # fileset, in reverse order Then, for each fileset, we store the 'good'
+ # incrementals and differentials until we have found a full so it goes
+ # like this : store all incrementals until we have found a differential
+ # or a full, then find the full #
+
+ my $query = "SELECT JobId, FileSet, Level, JobStatus
+ FROM Job, Client, FileSet
+ WHERE Job.ClientId = Client.ClientId
+ AND FileSet.FileSetId = Job.FileSetId
+ AND EndTime <= $date
+ AND Client.Name = '$client'
+ AND Type IN ('B')
+ AND JobStatus IN ('T')
+ ORDER BY FileSet, JobTDate DESC";
+
+ my @CurrentJobIds;
+ my $result = $self->dbh_selectall_arrayref($query);
+ my %progress;
+ foreach my $refrow (@$result)
+ {
+ my $jobid = $refrow->[0];
+ my $fileset = $refrow->[1];
+ my $level = $refrow->[2];
+
+ defined $progress{$fileset} or $progress{$fileset}='U'; # U for unknown
+
+ next if $progress{$fileset} eq 'F'; # It's over for this fileset...
+
+ if ($level eq 'I')
+ {
+ next unless ($progress{$fileset} eq 'U' or $progress{$fileset} eq 'I');
+ push @CurrentJobIds,($jobid);
+ }
+ elsif ($level eq 'D')
+ {
+ next if $progress{$fileset} eq 'D'; # We allready have a differential
+ push @CurrentJobIds,($jobid);
+ }
+ elsif ($level eq 'F')
+ {
+ push @CurrentJobIds,($jobid);
+ }
+
+ my $status = $refrow->[3] ;
+ if ($status eq 'T') { # good end of job
+ $progress{$fileset} = $level;
+ }
+ }
+
+ return @CurrentJobIds;
+}
+
# Returns list of versions of a file that could be restored
# returns an array of
my $action = CGI::param('action') || '';
-my $args = $bvfs->get_form('pathid', 'filenameid', 'fileid',
+my $args = $bvfs->get_form('pathid', 'filenameid', 'fileid', 'qdate',
'limit', 'offset', 'client');
my @jobid = grep { /^\d+$/ } CGI::param('jobid');
+if (!scalar(@jobid) and $args->{qdate} and $args->{client}) {
+ @jobid = $bvfs->set_job_ids_for_date($args->{client}, $args->{qdate});
+print join(",", $args->{qdate}, $args->{client}, @jobid), "\n";
+
+}
+
$bvfs->set_curjobids(@jobid);
$bvfs->set_limits($args->{limit}, $args->{offset});
-#$bvfs->{debug}=1;
print CGI::header('application/x-javascript');
print "[";
print join(',', map {
- "[$_->[4], '$_->[0] $_->[1] $_->[2] ($_->[3])']"
+ "[$_->[4], '$_->[0]', '$_->[0] $_->[1] $_->[2] ($_->[3])']"
} @$result);
print "]\n";
}
-my $pathid = CGI::param('node') || 0;
+my $pathid = CGI::param('node') || '';
+my $path = CGI::param('path');
+
if ($pathid =~ /^(\d+)$/) {
$pathid = $1;
+} elsif ($path) {
+ $pathid = $bvfs->get_pathid($path);
} else {
$pathid = $bvfs->get_root();
}
// root.expand();
tree.on('click', function(e) {
- file_store.removeAll();
+ file_store.removeAll();
file_store.load({params:{action: 'list_files',
- jobid:Ext.brestore.jobid,
+ jobid:Ext.brestore.jobid,
node:e.id}
});
- return true;
+ return true;
});
tree.on('beforeload', function(e) {
- file_store.removeAll();
- return true;
+ file_store.removeAll();
+ return true;
});
var file_store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: '/cgi-bin/bweb/bresto.pl',
- method: 'GET',
+ method: 'GET',
params:{action: 'list_files', offset:0, limit:50 }
}),
- reader: new Ext.data.ArrayReader({
+ reader: new Ext.data.ArrayReader({
}, Ext.data.Record.create([
{name: 'fileid' },
{name: 'filenameid'},
},{
header: "Size",
dataIndex: 'size',
- renderer: human_size,
+ renderer: human_size,
width: 50
},{
header: "Date",
dataIndex: 'mtime',
width: 50
},{
- dataIndex: 'pathid',
- hidden: true
+ dataIndex: 'pathid',
+ hidden: true
},{
- dataIndex: 'filenameid',
- hidden: true
+ dataIndex: 'filenameid',
+ hidden: true
},{
- dataIndex: 'fileid',
- hidden: true
- }
+ dataIndex: 'fileid',
+ hidden: true
+ }
]);
// by default columns are sortable
// when we reload the view,
// we clear the file version box
file_store.on('beforeload', function(e) {
- file_versions_store.removeAll();
- return true;
+ file_versions_store.removeAll();
+ return true;
});
files_grid.selModel.on('rowselect', function(e,i,r) {
- Ext.brestore.filename = r.json[3];
- file_versions_store.load({params:{action: 'list_versions',
+ Ext.brestore.filename = r.json[3];
+ file_versions_store.load({params:{action: 'list_versions',
client: Ext.brestore.client,
- pathid: r.json[2],
- filenameid: r.json[1]
+ pathid: r.json[2],
+ filenameid: r.json[1]
}
});
- return true;
+ return true;
});
files_grid.render();
//////////////////////////////////////////////////////////////:
var file_selection_store = new Ext.data.Store({
- proxy: new Ext.data.HttpProxy({
- url: '/cgi-bin/bweb/bresto.pl',
- method: 'GET',
- params:{offset:0, limit:50 }
- }),
+ proxy: new Ext.data.MemoryProxy(),
- reader: new Ext.data.ArrayReader({
+ reader: new Ext.data.ArrayReader({
}, Ext.data.Record.create([
{name: 'jobid' },
{name: 'fileid' },
var file_selection_cm = new Ext.grid.ColumnModel([{
id: 'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
dataIndex: 'name',
- hidden: true
+ hidden: true
},{
header: "JobId",
dataIndex: 'jobid'
},{
header: "Size",
dataIndex: 'size',
- renderer: human_size,
+ renderer: human_size,
width: 50
},{
header: "Date",
dataIndex: 'mtime',
width: 50
},{
- dataIndex: 'pathid',
- hidden: true
+ dataIndex: 'pathid',
+ hidden: true
},{
- dataIndex: 'filenameid',
- hidden: true
+ dataIndex: 'filenameid',
+ hidden: true
},{
- dataIndex: 'fileid',
- hidden: true
- }
+ dataIndex: 'fileid',
+ hidden: true
+ }
]);
cm: file_selection_cm,
ds: file_selection_store,
ddGroup : 'TreeDD',
- enableDragDrop: true,
- enableDrop: true,
+ enableDrag: false,
+ enableDrop: true,
selModel: new Ext.grid.RowSelectionModel(),
loadMask: true,
enableColLock:false
});
+ var file_selection_record = Ext.data.Record.create(
+ {name: 'jobid'},
+ {name: 'fileid'},
+ {name: 'filenameid'},
+ {name: 'pathid'},
+ {name: 'size'},
+ {name: 'mtime'}
+ );
+// data.selections[0].json[]
+// data.node.id
// http://extjs.com/forum/showthread.php?t=12582&highlight=drag+drop
-// var ddrow = new Ext.dd.DropTarget(grid.container, {
-// ddGroup : 'TreeDD',
-// copy:false,
-// notifyDrop : function(dd, e, data){
-// var sm=grid.getSelectionModel();
-// var rows=sm.getSelections();
-// var cindex=dd.getDragData(e).rowIndex;
-// for(i = 0; i < rows.length; i++) {
-// rowData=ds.getById(rows[i].id);
-// if(!this.copy)
-// ds.remove(ds.getById(rows[i].id));
-// ds.insert(cindex,rowData);
-// };
-// }
-// });
+ var ddrow = new Ext.dd.DropTarget(file_selection_grid.container, {
+ ddGroup : 'TreeDD',
+ copy:false,
+ notifyDrop : function(dd, e, data){
+// if (data.selections) {
+// alert("grid");
+// }
+//
+// if (data.node) {
+// alert("tree");
+// }
+//
+ file_selection_store.add(
+ new file_selection_record({
+ jobid:1,
+ fileid:1,
+ filenameid:1,
+ pathid:1,
+ size:1,
+ mtime:'2007-01-01 01:00:00'
+ })
+ );
+
+ return true;
+// var sm=grid.getSelectionModel();
+// var rows=sm.getSelections();
+// var cindex=dd.getDragData(e).rowIndex;
+// for(i = 0; i < rows.length; i++) {
+// rowData=ds.getById(rows[i].id);
+// if(!this.copy)
+// ds.remove(ds.getById(rows[i].id));
+// ds.insert(cindex,rowData);
+// };
+ }
+ });
file_selection_grid.on('enddrag', function(dd,e) {
- alert(e) ; return true;
+ alert(e) ; return true;
});
file_selection_grid.on('notifyDrop', function(dd,e) {
- alert(e) ; return true;
+ alert(e) ; return true;
});
file_selection_grid.render();
var file_versions_store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: '/cgi-bin/bweb/bresto.pl',
- method: 'GET',
+ method: 'GET',
params:{offset:0, limit:50 }
}),
- reader: new Ext.data.ArrayReader({
+ reader: new Ext.data.ArrayReader({
}, Ext.data.Record.create([
{name: 'fileid' },
{name: 'filenameid'},
var file_versions_cm = new Ext.grid.ColumnModel([{
id: 'name', // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })
dataIndex: 'name',
- hidden: true
+ hidden: true
},{
header: "InChanger",
dataIndex: 'inchanger',
- renderer: rd_vol_is_online
+ renderer: rd_vol_is_online
},{
header: "Volume",
dataIndex: 'volume'
},{
header: "Size",
dataIndex: 'size',
- renderer: human_size,
+ renderer: human_size,
width: 50
},{
header: "Date",
dataIndex: 'md5',
width: 50
},{
- dataIndex: 'pathid',
- hidden: true
+ dataIndex: 'pathid',
+ hidden: true
},{
- dataIndex: 'filenameid',
- hidden: true
+ dataIndex: 'filenameid',
+ hidden: true
},{
- dataIndex: 'fileid',
- hidden: true
- }
+ dataIndex: 'fileid',
+ hidden: true
+ }
]);
// by default columns are sortable
});
file_versions_grid.on('rowdblclick', function(e) {
- alert(e) ; file_versions_store.removeAll(); return true;
+ alert(e) ; file_versions_store.removeAll(); return true;
});
file_versions_grid.render();
var client_store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: '/cgi-bin/bweb/bresto.pl',
- method: 'GET',
+ method: 'GET',
params:{action:'list_client'}
}),
- reader: new Ext.data.ArrayReader({
+ reader: new Ext.data.ArrayReader({
}, Ext.data.Record.create([
- {name: 'name' }
+ {name: 'name' }
]))
});
var client_combo = new Ext.form.ComboBox({
- fieldLabel: 'Clients',
+ fieldLabel: 'Clients',
store: client_store,
displayField:'name',
typeAhead: true,
triggerAction: 'all',
emptyText:'Select a client...',
selectOnFocus:true,
- forceSelection: true,
+ forceSelection: true,
width:135
});
client_combo.on('valid', function(e) {
- Ext.brestore.client = e.getValue();
- job_store.load( {params:{action: 'list_job',client:Ext.brestore.client}});
- return true;
+ Ext.brestore.client = e.getValue();
+ job_store.load( {params:{action: 'list_job',
+ client:Ext.brestore.client}});
+ return true;
});
//////////////////////////////////////////////////////////////:
var job_store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: '/cgi-bin/bweb/bresto.pl',
- method: 'GET',
+ method: 'GET',
params:{offset:0, limit:50 }
}),
- reader: new Ext.data.ArrayReader({
+ reader: new Ext.data.ArrayReader({
}, Ext.data.Record.create([
- {name: 'jobid' },
- {name: 'jobname' }
+ {name: 'jobid' },
+ {name: 'date' },
+ {name: 'jobname' }
]))
});
var job_combo = new Ext.form.ComboBox({
- fieldLabel: 'Jobs',
+ fieldLabel: 'Jobs',
store: job_store,
displayField:'jobname',
typeAhead: true,
triggerAction: 'all',
emptyText:'Select a job...',
selectOnFocus:true,
- forceSelection: true,
+ forceSelection: true,
width:300
});
job_combo.on('select', function(e,c) {
- Ext.brestore.jobid = c.json[0];
-
- tree_loader.baseParams = { action:'list_dirs',
- jobid:Ext.brestore.jobid };
+ // TODO: choose between date and jobid here (with a toolbar bp ?)
+ Ext.brestore.jobid = c.json[0];
+ root.setText("Root");
+ tree_loader.baseParams = { action:'list_dirs',
+ jobid:Ext.brestore.jobid };
root.reload();
});
tooltip:'Remove the selected item'
});
- var tb = new Ext.Toolbar('div-toolbar', [
- client_combo,
- job_combo,
- '-',
- {
- id: 'tb_home',
-// icon: '/bweb/up.gif',
- text: 'Change location',
- cls:'x-btn-text-icon',
- handler: function() { alert('do chdir') }
- },
- new Ext.form.TextField({
+ var where_field = new Ext.form.TextField({
fieldLabel: 'Location',
name: 'where',
width:175,
allowBlank:false
- })
+ });
+
+ var tb = new Ext.Toolbar('div-toolbar', [
+ client_combo,
+ job_combo,
+ '-',
+ {
+ id: 'tb_home',
+// icon: '/bweb/up.gif',
+ text: 'Change location',
+ cls:'x-btn-text-icon',
+ handler: function() {
+ var where = where_field.getValue();
+ root.setText(where);
+ tree_loader.baseParams = { action:'list_dirs',
+ jobid:Ext.brestore.jobid,
+ path: where };
+ root.reload();
+ }
+ },
+ where_field
]);
////////////////////////////////////////////////////////////////
split: true, initialSize: 300
},
center: {
- initialSize: 600
+ initialSize: 600
}
-
+
});
layout.beginUpdate();
layout.add('center', new Ext.ContentPanel('div-files', {
autoScroll:true,autoCreate:true,fitToFrame: true
}));
-layout.endUpdate();
+layout.endUpdate();
////////////////////////////////////////////////////////////////