print STDERR "Creating missing recursion paths for $job\n";
- $query = "SELECT brestore_pathvisibility.PathId, Path FROM brestore_pathvisibility
- JOIN Path ON( brestore_pathvisibility.PathId = Path.PathId)
- LEFT JOIN brestore_pathhierarchy ON (brestore_pathvisibility.PathId = brestore_pathhierarchy.PathId)
- WHERE brestore_pathvisibility.JobId = $job
- AND brestore_pathhierarchy.PathId IS NULL
- ORDER BY Path";
+ $query = "
+SELECT brestore_pathvisibility.PathId, Path FROM brestore_pathvisibility
+ JOIN Path ON( brestore_pathvisibility.PathId = Path.PathId)
+ LEFT JOIN brestore_pathhierarchy ON (brestore_pathvisibility.PathId = brestore_pathhierarchy.PathId)
+ WHERE brestore_pathvisibility.JobId = $job
+ AND brestore_pathhierarchy.PathId IS NULL
+ ORDER BY Path";
my $sth = $self->dbh_prepare($query);
$sth->execute();
# This query gives all parent pathids for a given jobid that aren't stored.
# It has to be called until no record is updated ...
$query = "
- INSERT INTO brestore_pathvisibility (PathId, JobId) (
- SELECT a.PathId,$job
- FROM
- (SELECT DISTINCT h.PPathId AS PathId
- FROM brestore_pathhierarchy AS h
- JOIN brestore_pathvisibility AS p ON (h.PathId=p.PathId)
- WHERE p.JobId=$job) AS a
- LEFT JOIN
- (SELECT PathId
- FROM brestore_pathvisibility
- WHERE JobId=$job) AS b
- ON (a.PathId = b.PathId)
- WHERE b.PathId IS NULL)";
+INSERT INTO brestore_pathvisibility (PathId, JobId) (
+ SELECT a.PathId,$job
+ FROM (
+ SELECT DISTINCT h.PPathId AS PathId
+ FROM brestore_pathhierarchy AS h
+ JOIN brestore_pathvisibility AS p ON (h.PathId=p.PathId)
+ WHERE p.JobId=$job) AS a LEFT JOIN
+ (SELECT PathId
+ FROM brestore_pathvisibility
+ WHERE JobId=$job) AS b ON (a.PathId = b.PathId)
+ WHERE b.PathId IS NULL)";
my $rows_affected;
while (($rows_affected = $self->dbh_do($query)) and ($rows_affected !~ /^0/))
my $query =
"SELECT File.FilenameId, listfiles.id, listfiles.Name, File.LStat, File.JobId
- FROM
- (SELECT Filename.Name, max(File.FileId) as id
+ FROM File, (
+ SELECT Filename.Name, max(File.FileId) as id
FROM File, Filename
- WHERE File.FilenameId = Filename.FilenameId
- AND Filename.Name != ''
- AND File.PathId IN ($inlistpath)
- AND File.JobId IN ($inclause)
- GROUP BY Filename.Name
- ORDER BY Filename.Name) AS listfiles,
-File
+ WHERE File.FilenameId = Filename.FilenameId
+ AND Filename.Name != ''
+ AND File.PathId IN ($inlistpath)
+ AND File.JobId IN ($inclause)
+ GROUP BY Filename.Name
+ ORDER BY Filename.Name) AS listfiles
WHERE File.FileId = listfiles.id";
$self->debug($query);
# 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 JOIN FileSet USING (FileSetId)
- JOIN Client USING (ClientId) $filter
- WHERE EndTime <= $date
- AND Client.Name = '$client'
- AND Type IN ('B')
- AND JobStatus IN ('T')
- ORDER BY FileSet, JobTDate DESC";
+ my $query = "
+SELECT JobId, FileSet, Level, JobStatus
+ FROM Job
+ JOIN FileSet USING (FileSetId)
+ JOIN Client USING (ClientId) $filter
+ WHERE 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 $args = $bvfs->get_form('pathid', 'filenameid', 'fileid', 'qdate',
'limit', 'offset', 'client');
-print CGI::header('application/x-javascript');
+if (CGI::param('batch')) {
+ $bvfs->update_cache();
+ exit 0;
+}
if ($action eq 'list_client') {
+ print CGI::header('application/x-javascript');
my $filter = $bvfs->get_client_filter();
my $q = "SELECT Name FROM Client $filter";
exit 0;
} elsif ($action eq 'list_job') {
+ print CGI::header('application/x-javascript');
my $filter = $bvfs->get_client_filter();
my $query = "
print "[";
print join(',', map {
- "[$_->[4], '$_->[0]', '$_->[0] $_->[1] $_->[2] ($_->[3])']"
+ "[$_->[4], '$_->[0]', '$_->[0] $_->[1] $_->[2] ($_->[3]) $_->[4]']"
} @$result);
print "]\n";
exit 0;
} elsif ($action eq 'list_storage') { # TODO: use .storage hier
+ print CGI::header('application/x-javascript');
my $q="SELECT Name FROM Storage";
my $lst = $bvfs->dbh_selectall_arrayref($q);
exit 0;
}
-my @jobid = $bvfs->get_jobids(grep { /^\d+$/ } CGI::param('jobid'));
+my @jobid = $bvfs->get_jobids(grep { /^\d+(,\d+)*$/ } CGI::param('jobid'));
if (!scalar(@jobid) and $args->{qdate} and $args->{client}) {
@jobid = $bvfs->set_job_ids_for_date($args->{client}, $args->{qdate});
}
$bvfs->ch_dir($pathid);
+if ($action eq 'restore') {
+
+ # TODO: pouvoir choisir le replace et le jobname
+ my $arg = $bvfs->get_form(qw/client storage regexwhere where/);
+
+ if (!$arg->{client}) {
+ print "ERROR: missing client\n";
+ exit 1;
+ }
+
+ my $fileid = join(',', grep { /^\d+$/ } CGI::param('fileid'));
+ my @dirid = grep { /^\d+$/ } CGI::param('dirid');
+ my $inclause = join(',', @jobid);
+
+ my @union;
+
+ if ($fileid) {
+ push @union,
+ "(SELECT JobId, FileIndex, FilenameId, PathId FROM File WHERE FileId IN ($fileid))";
+ }
+
+ # using this is not good because the sql engine doesn't know
+ # what LIKE will use. It will be better to get Path% in perl
+ # but it doesn't work with accents... :(
+ foreach my $dirid (@dirid) {
+ push @union, "
+ (SELECT File.JobId, File.FileIndex, File.FilenameId, File.PathId
+ FROM Path JOIN File USING (PathId)
+ WHERE Path.Path LIKE
+ (SELECT ". $bvfs->dbh_strcat('Path',"'\%'") ." FROM Path
+ WHERE PathId = $dirid
+ )
+ AND File.JobId IN ($inclause))";
+ }
+
+ return unless scalar(@union);
+
+ my $u = join(" UNION ", @union);
+
+ $bvfs->dbh_do("CREATE TEMPORARY TABLE btemp AS ($u)");
+ # TODO: remove FilenameId et PathId
+ $bvfs->dbh_do("CREATE TABLE b2$$ AS (
+SELECT btemp.JobId, btemp.FileIndex, btemp.FilenameId, btemp.PathId
+ FROM btemp,
+ (SELECT max(JobId) as JobId, PathId, FilenameId
+ FROM btemp
+ GROUP BY PathId, FilenameId
+ ORDER BY JobId DESC) AS a
+ WHERE a.JobId = btemp.JobId
+ AND a.PathId= btemp.PathId
+ AND a.FilenameId = btemp.FilenameId
+)");
+ my $bconsole = $bvfs->get_bconsole();
+ # TODO: pouvoir choisir le replace et le jobname
+ my $jobid = $bconsole->run(client => $arg->{client},
+ storage => $arg->{storage},
+ where => $arg->{where},
+ regexwhere=> $arg->{regexwhere},
+ restore => 1,
+ file => "?b2$$");
+
+ $bvfs->dbh_do("DROP TABLE b2$$");
+ sleep(2);
+ print CGI::redirect("bweb.pl?action=dsp_cur_job;jobid=$jobid") ;
+ exit 0;
+}
+
+print CGI::header('application/x-javascript');
+
if ($action eq 'list_files') {
print "[";
my $files = $bvfs->ls_files();
# File.FilenameId, listfiles.id, listfiles.Name, File.LStat, File.JobId
print join(',',
- map { "[$_->[1], $_->[0], $pathid, \"$_->[2]\", 10, \"2007-01-01 00:00:00\"]" }
+ map { "[$_->[1], $_->[0], $pathid, $_->[4], \"$_->[2]\", 10, \"2007-01-01 00:00:00\"]" }
@$files);
print "]\n";
# return ($dirid,$dir_basename,$lstat,$jobid)
print join(',',
- map { "{ 'id': '$_->[0]', 'text': '$_->[1]', 'cls':'folder'}" }
+ map { "{ 'jobid': '$bvfs->{curjobids}', 'id': '$_->[0]', 'text': '$_->[1]', 'cls':'folder'}" }
@$dirs);
print "]\n";
SELECT DISTINCT VolumeName, InChanger
FROM File,
( -- Get all media from this job
- SELECT MAX(FirstIndex) AS FirstIndex, MIN(LastIndex) AS LastIndex,
+ SELECT MIN(FirstIndex) AS FirstIndex, MAX(LastIndex) AS LastIndex,
VolumeName, Inchanger
FROM JobMedia JOIN Media USING (MediaId)
WHERE JobId IN ($jobid)
) AS allmedia
WHERE File.FileId IN ($fileid)
AND File.FileIndex >= allmedia.FirstIndex
- AND File.FileIndex <= allmedia.LastIndex;
+ AND File.FileIndex <= allmedia.LastIndex
";
my $lst = $bvfs->dbh_selectall_arrayref($q);
print "[";
print join(',', map { "[ '$_->[0]', $_->[1]]" } @$lst);
print "]\n";
-} elsif ($action eq 'restore') {
- my $fileid = join(',', grep { /^\d+$/ } CGI::param('fileid'));
- my @dirid = grep { /^\d+$/ } CGI::param('dirid');
- my $inclause = join(',', @jobid);
-
- my @union;
-
- if ($fileid) {
- push @union, "(SELECT JobId, FileIndex FROM File WHERE FileId IN ($fileid))";
- }
-
- # using this is not good because the sql engine doesn't know
- # what LIKE will use. It will be better to get Path% in perl
- # but it doesn't work with accents... :(
- foreach my $dirid (@dirid) {
- push @union, "
- (SELECT File.JobId, File.FileIndex, File.FilenameId, File.PathId
- FROM Path JOIN File USING (PathId)
- WHERE Path.Path LIKE
- (SELECT ". $bvfs->dbh_strcat('Path',"'\%'") ." FROM Path
- WHERE PathId = $dirid
- )
- AND File.JobId IN ($inclause))";
- }
-
- return unless scalar(@union);
-
- my $u = join(" UNION ", @union);
-
- $bvfs->dbh_do("CREATE TEMP TABLE btemp AS ($u)");
- # TODO: remove FilenameId et PathId
- $bvfs->dbh_do("CREATE TABLE b2$$ AS (
-SELECT btemp.JobId, btemp.FileIndex, btemp.FilenameId, btemp.PathId
- FROM btemp,
- (SELECT max(JobId) as JobId, PathId, FilenameId
- FROM btemp
- GROUP BY PathId, FilenameId
- ORDER BY JobId DESC) AS a
- WHERE a.JobId = btemp.JobId
- AND a.PathId= btemp.PathId
- AND a.FilenameId = btemp.FilenameId
-)");
-
- print "restore file=?b2$$ done\n";
}
__END__
Ext.brestore.jobid=0; // selected jobid
Ext.brestore.jobdate=''; // selected date
Ext.brestore.client=''; // selected client
+Ext.brestore.rclient=''; // selected client for resto
+Ext.brestore.storage=''; // selected storage for resto
Ext.brestore.path=''; // current path (without user location)
Ext.brestore.root_path=''; // user location
Ext.brestore.option_vosb = false;
Ext.brestore.option_vafv = false;
Ext.brestore.dlglaunch;
+Ext.BLANK_IMAGE_URL = '/bweb/ext/resources/images/aero/s.gif'; // 1.1
function get_node_path(node)
{
id:'source'
});
tree.setRootNode(root);
+ Ext.brestore.tree = root;
// render the tree
tree.render();
{name: 'fileid' },
{name: 'filenameid'},
{name: 'pathid' },
+ {name: 'jobid' },
{name: 'name' },
{name: 'size', type: 'int' },
{name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}
},{
dataIndex: 'fileid',
hidden: true
+ },{
+ dataIndex: 'jobid',
+ hidden: true
}
]);
width: 100
},{
dataIndex: 'pathid',
- hidden: true
+ header: 'PathId'
+// hidden: true
},{
dataIndex: 'filenameid',
hidden: true
},{
dataIndex: 'fileid',
- hidden: true
+ header: 'FileId'
+// hidden: true
}
]);
if (data.grid.id == 'div-files') {
for(var i=0;i<data.selections.length;i++) {
r = new file_selection_record({
- jobid: Ext.brestore.jobid,
+ jobid: data.selections[0].json[3],
fileid: data.selections[i].json[0],
filenameid:data.selections[i].json[1],
pathid: data.selections[i].json[2],
- name: Ext.brestore.path + data.selections[i].json[3],
- size: data.selections[i].json[4],
- mtime: data.selections[i].json[5]
+ name: Ext.brestore.path + data.selections[i].json[4],
+ size: data.selections[i].json[5],
+ mtime: data.selections[i].json[6]
});
file_selection_store.add(r)
}
if (data.node) {
var path= get_node_path(data.node);
r = new file_selection_record({
- jobid: Ext.brestore.jobid,
+ jobid: data.node.attributes.jobid,
fileid: 0,
filenameid:0,
pathid: data.node.id,
// create the primary toolbar
var tb2 = new Ext.Toolbar('div-tb-sel');
- tb2.add({
- id:'save',
- text:'Save',
- disabled:true,
-// handler:save,
- cls:'x-btn-text-icon save',
- tooltip:'Saves all components to the server'
- },'-', {
- id:'add',
- text:'Component',
-// handler:addComponent,
- cls:'x-btn-text-icon add-cmp',
- tooltip:'Add a new Component to the dependency builder'
- }, {
- id:'option',
- text:'Option',
- disabled:true,
-// handler:addOption,
- cls:'x-btn-text-icon add-opt',
- tooltip:'Add a new optional dependency to the selected component'
- },'-',{
- id:'remove',
- text:'Remove',
- disabled:true,
-// handler:removeNode,
- cls:'x-btn-text-icon remove',
- tooltip:'Remove the selected item'
- });
var where_field = new Ext.form.TextField({
fieldLabel: 'Location',
// alwaysShowTabs: true
}
});
- var dialog = Ext.brestore.dlglaunch;
- dialog.addKeyListener(27, dialog.hide, dialog);
- dialog.addButton('Submit', dialog.hide, dialog);
- dialog.addButton('Close', dialog.hide, dialog);
var fs = new Ext.form.Form({
labelAlign: 'right',
labelWidth: 80
});
+// var resto_store = new Ext.data.Store({
+// proxy: new Ext.data.HttpProxy({
+// url: '/cgi-bin/bweb/bresto.pl',
+// method: 'GET',
+// params:{action:'list_resto'}
+// }),
+//
+// reader: new Ext.data.ArrayReader({
+// }, Ext.data.Record.create([
+// {name: 'name' }
+// ]))
+// });
+
+ var rclient_combo = new Ext.form.ComboBox({
+ value: Ext.brestore.client,
+ fieldLabel: 'client',
+ hiddenName:'client',
+ store: client_store,
+ displayField:'name',
+ typeAhead: true,
+ mode: 'local',
+ triggerAction: 'all',
+ emptyText:'Select a client...',
+ selectOnFocus:true,
+ width:190
+ });
+ var where_text = new Ext.form.TextField({
+ fieldLabel: 'Where',
+ name: 'where',
+ value: '/tmp/bacula-restore',
+ width:190
+ });
var storage_store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: '/cgi-bin/bweb/bresto.pl',
{name: 'name' }
]))
});
-
- var resto_store = new Ext.data.Store({
- proxy: new Ext.data.HttpProxy({
- url: '/cgi-bin/bweb/bresto.pl',
- method: 'GET',
- params:{action:'list_resto'}
- }),
-
- reader: new Ext.data.ArrayReader({
- }, Ext.data.Record.create([
- {name: 'name' }
- ]))
- });
-
- fs.fieldset(
- {legend:'Restore job'},
- new Ext.form.ComboBox({
- fieldLabel: 'Replace',
- hiddenName:'replace',
- store: new Ext.data.SimpleStore({
- fields: ['replace'],
- data : [['always'],['never'],['if newer']]
- }),
- displayField:'replace',
- typeAhead: true,
- mode: 'local',
- triggerAction: 'all',
- emptyText:'never',
- selectOnFocus:true,
- width:190
- }),
-
- new Ext.form.ComboBox({
- fieldLabel: 'job',
- hiddenName:'job',
- store: resto_store,
- displayField:'name',
- typeAhead: true,
- mode: 'local',
- triggerAction: 'all',
- emptyText:'Select a job...',
- selectOnFocus:true,
- width:190
- })
- ,
- new Ext.form.TextField({
- fieldLabel: 'Where',
- name: 'where',
- width:190
- }),
-
- new Ext.form.ComboBox({
- fieldLabel: 'client',
- hiddenName:'client',
- store: client_store,
- displayField:'name',
- typeAhead: true,
- mode: 'local',
- triggerAction: 'all',
- emptyText:'Select a client...',
- selectOnFocus:true,
- width:190
- }),
- new Ext.form.ComboBox({
+ var storage_combo = new Ext.form.ComboBox({
fieldLabel: 'storage',
hiddenName:'storage',
store: storage_store,
emptyText:'Select a storage...',
selectOnFocus:true,
width:190
- })
+ });
+ fs.fieldset(
+ {legend:'Restore job'},
+// new Ext.form.ComboBox({
+// fieldLabel: 'Replace',
+// hiddenName:'replace',
+// store: new Ext.data.SimpleStore({
+// fields: ['replace'],
+// data : [['always'],['never'],['if newer']]
+// }),
+// displayField:'replace',
+// typeAhead: true,
+// mode: 'local',
+// triggerAction: 'all',
+// emptyText:'never',
+// selectOnFocus:true,
+// width:190
+// }),
+//
+// new Ext.form.ComboBox({
+// fieldLabel: 'job',
+// hiddenName:'job',
+// store: resto_store,
+// displayField:'name',
+// typeAhead: true,
+// mode: 'local',
+// triggerAction: 'all',
+// emptyText:'Select a job...',
+// selectOnFocus:true,
+// width:190
+// }),
+
+ rclient_combo,
+ where_text,
+ storage_combo
);
storage_store.load({params:{action: 'list_storage'}});
- resto_store.load({params:{action: 'list_resto'}});
+// resto_store.load({params:{action: 'list_resto'}});
fs.render('div-resto-form');
// var f = new Ext.form.BasicForm('div-resto-form', {url: '/bweb/test', method: 'GET',
// }
// );
- var layout = dialog.getLayout();
- layout.beginUpdate();
- layout.add('center', new Ext.ContentPanel('div-resto-form', {
+ var launch_restore = function() {
+ var items = file_selection_store.data.items;
+ var tab_fileid=new Array();
+ var tab_dirid=new Array();
+ var tab_jobid=new Array();
+ for(var i=0;i<items.length;i++) {
+ if (items[i].data['fileid']) {
+ tab_fileid.push(items[i].data['fileid']);
+ } else {
+ tab_dirid.push(items[i].data['pathid']);
+ }
+ tab_jobid.push(items[i].data['jobid']);
+ }
+ var res = ';fileid=' + tab_fileid.join(";fileid=");
+ var res2 = ';dirid=' + tab_dirid.join(";dirid=");
+ var res3 = ';jobid=' + tab_jobid.join(";jobid=");
+
+ var res4 = ';client=' + rclient_combo.getValue() + ';storage=' + storage_combo.getValue() + ';where=' + where_text.getValue();
+
+ window.location='/cgi-bin/bweb/bresto.pl?action=restore' + res + res2 + res3 + res4;
+ }
+ var dialog = Ext.brestore.dlglaunch;
+ dialog.addKeyListener(27, dialog.hide, dialog);
+ dialog.addButton('Submit', launch_restore);
+ dialog.addButton('Close', dialog.hide, dialog);
+
+ var layout = dialog.getLayout();
+ layout.beginUpdate();
+ layout.add('center', new Ext.ContentPanel('div-resto-form', {
autoCreate:true, title: 'Third Tab', closable:true, background:true}));
- layout.endUpdate();
- dialog.show();
+ layout.endUpdate();
+ dialog.show();
+
}
}
]);