ArielGlenn has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/385368 )
Change subject: clean up partially written files from previous 7z runs of same
wiki and date
......................................................................
clean up partially written files from previous 7z runs of same wiki and date
We write to files with .inprog extension now, these must be cleaned
up if the job is retried after failure, so that good content isn't
appended to these bad partial files.
Change-Id: I6e858fe11a34c115441a92cea18988514bc8942e
---
M xmldumps-backup/dumps/fileutils.py
M xmldumps-backup/dumps/jobs.py
M xmldumps-backup/dumps/recompressjobs.py
3 files changed, 59 insertions(+), 16 deletions(-)
Approvals:
ArielGlenn: Looks good to me, approved
jenkins-bot: Verified
diff --git a/xmldumps-backup/dumps/fileutils.py
b/xmldumps-backup/dumps/fileutils.py
index a53e76a..a264ece 100644
--- a/xmldumps-backup/dumps/fileutils.py
+++ b/xmldumps-backup/dumps/fileutils.py
@@ -150,6 +150,7 @@
is_checkpoint_file filename of form
dbname-date-dumpname-pxxxxpxxxx.xml.bz2
is_file_part filename of form dbname-date-dumpnamex.xml.gz/bz2/7z
is_temp_file filename of form dbname-date-dumpname.xml.gz/bz2/7z-tmp
+ is_inprog filename of form dbname-date-dumpname.<stuff>.inprog
first_page_id for checkpoint files, taken from value in filename
last_page_id for checkpoint files, value taken from filename
filename full filename
@@ -219,6 +220,7 @@
self.is_temp_file = False
self.temp = None
+ self.is_inprog = False
# example filenames:
# elwikidb-20110729-all-titles-in-ns0.gz
@@ -231,8 +233,15 @@
self.is_temp_file = True
self.temp = "-tmp"
- if '.' in self.filename:
- (file_base, self.file_ext) = self.filename.rsplit('.', 1)
+ if self.filename.endswith(".inprog"):
+ self.is_inprog = True
+
+ if self.is_inprog:
+ splitme = self.filename[:-7] # get rid of .inprog at end
+ else:
+ splitme = self.filename
+ if '.' in splitme:
+ (file_base, self.file_ext) = splitme.rsplit('.', 1)
if self.temp:
self.file_ext = self.file_ext[:-4]
else:
@@ -263,6 +272,8 @@
self.checkpoint_pattern = r"-p(?P<first>[0-9]+)p(?P<last>[0-9]+)\." +
self.file_ext
if self.temp is not None:
self.checkpoint_pattern += self.temp + "$"
+ elif self.is_inprog:
+ self.checkpoint_pattern += ".inprog$"
else:
self.checkpoint_pattern += "$"
@@ -725,7 +736,7 @@
def _get_files_filtered(self, date=None, dump_name=None, file_type=None,
file_ext=None, parts=None, temp=None,
checkpoint=None,
- skip_suffixes=None, required_suffixes=None):
+ skip_suffixes=None, required_suffixes=None,
inprog=False):
'''
list all files that exist, filtering by the given args.
if we get None for an arg then we accept all values
@@ -747,7 +758,6 @@
dfnames = self.get_files_in_dir(date)
dfnames_matched = []
for dfname in dfnames:
-
if skip_suffixes:
for suffix in skip_suffixes:
if dfname.filename.endswith(suffix):
@@ -776,6 +786,8 @@
continue
if (temp is False and dfname.is_temp_file) or (temp and not
dfname.is_temp_file):
continue
+ if (inprog is False and dfname.is_inprog) or (inprog is True and
not dfname.is_inprog):
+ continue
if ((checkpoint is False and dfname.is_checkpoint_file) or
(checkpoint and not dfname.is_checkpoint_file)):
continue
@@ -796,7 +808,7 @@
return mylist
def get_checkpt_files(self, date=None, dump_name=None,
- file_type=None, file_ext=None, parts=False,
temp=False):
+ file_type=None, file_ext=None, parts=False,
temp=False, inprog=False):
'''
list all checkpoint files that exist, filtering by the given args.
if we get None for an arg then we accept all values for that arg in
the filename
@@ -809,7 +821,7 @@
return self._get_files_filtered(date, dump_name, file_type,
file_ext, parts, temp, checkpoint=True,
required_suffixes=None,
- skip_suffixes=self.BAD)
+ skip_suffixes=self.BAD, inprog=inprog)
def get_truncated_empty_checkpt_files(self, date=None, dump_name=None,
file_type=None, file_ext=None,
@@ -829,7 +841,8 @@
skip_suffixes=None)
def get_reg_files(self, date=None, dump_name=None,
- file_type=None, file_ext=None, parts=False, temp=False,
suffix=None):
+ file_type=None, file_ext=None, parts=False, temp=False,
+ suffix=None, inprog=False):
'''
list all non-checkpoint files that exist, filtering by the given args.
if we get None for an arg then we accept all values for that arg in
the filename
@@ -851,4 +864,4 @@
return self._get_files_filtered(date, dump_name, file_type,
file_ext, parts, temp,
checkpoint=False,
required_suffixes=required_suffixes,
- skip_suffixes=skip_suffixes)
+ skip_suffixes=skip_suffixes,
inprog=inprog)
diff --git a/xmldumps-backup/dumps/jobs.py b/xmldumps-backup/dumps/jobs.py
index a3e4a29..8ebbbf1 100644
--- a/xmldumps-backup/dumps/jobs.py
+++ b/xmldumps-backup/dumps/jobs.py
@@ -96,9 +96,11 @@
command_info['output_dir'] = output_dir
else:
if runner.wiki.is_private():
- command_info['output_dir'] =
os.path.join(runner.wiki.private_dir(), runner.wiki.date)
+ command_info['output_dir'] =
os.path.join(runner.wiki.private_dir(),
+ runner.wiki.date)
else:
- command_info['output_dir'] =
os.path.join(runner.wiki.public_dir(), runner.wiki.date)
+ command_info['output_dir'] =
os.path.join(runner.wiki.public_dir(),
+ runner.wiki.date)
self.commands_submitted.append(command_info)
def check_truncation(self):
@@ -409,7 +411,7 @@
None, dname, self.file_type, self.file_ext, parts, temp=False))
return dfnames
- def list_checkpt_files_for_filepart(self, dump_dir, parts,
dump_names=None):
+ def list_checkpt_files_for_filepart(self, dump_dir, parts,
dump_names=None, inprog=False):
'''
list checkpoint files that have been produced for specified file
part(s)
returns:
@@ -420,10 +422,10 @@
dump_names = [self.dumpname]
for dname in dump_names:
dfnames.extend(dump_dir.get_checkpt_files(
- None, dname, self.file_type, self.file_ext, parts, temp=False))
+ None, dname, self.file_type, self.file_ext, parts, temp=False,
inprog=inprog))
return dfnames
- def list_reg_files_for_filepart(self, dump_dir, parts, dump_names=None):
+ def list_reg_files_for_filepart(self, dump_dir, parts, dump_names=None,
inprog=False):
'''
list noncheckpoint files that have been produced for specified file
part(s)
returns:
@@ -434,7 +436,7 @@
dump_names = [self.dumpname]
for dname in dump_names:
dfnames.extend(dump_dir.get_reg_files(
- None, dname, self.file_type, self.file_ext, parts, temp=False))
+ None, dname, self.file_type, self.file_ext, parts, temp=False,
inprog=inprog))
return dfnames
def list_truncated_empty_reg_files_for_filepart(self, dump_dir, parts,
dump_names=None):
diff --git a/xmldumps-backup/dumps/recompressjobs.py
b/xmldumps-backup/dumps/recompressjobs.py
index 68ed2b1..9d0a698 100644
--- a/xmldumps-backup/dumps/recompressjobs.py
+++ b/xmldumps-backup/dumps/recompressjobs.py
@@ -4,6 +4,7 @@
'''
from os.path import exists
+import os
from dumps.exceptions import BackupError
from dumps.fileutils import DumpFilename
from dumps.jobs import Dump
@@ -380,9 +381,36 @@
if errors:
raise BackupError("error recompressing bz2 file(s) %s")
+ def toss_inprog_files(self, dump_dir, runner):
+ """
+ delete partially written 7z files from previous failed attempts, if
+ any; 7z will otherwise blithely append onto them
+ """
+ if self.checkpoint_file is not None:
+ # we only rerun this one, so just remove this one
+ if exists(dump_dir.filename_public_path(self.checkpoint_file)):
+ if runner.dryrun:
+ print "would remove",
dump_dir.filename_public_path(self.checkpoint_file)
+ else:
+
os.remove(dump_dir.filename_public_path(self.checkpoint_file))
+ elif exists(dump_dir.filename_private_path(self.checkpoint_file)):
+ if runner.dryrun:
+ print "would remove",
dump_dir.filename_private_path(self.checkpoint_file)
+ else:
+
os.remove(dump_dir.filename_private_path(self.checkpoint_file))
+
+ dfnames = self.list_outfiles_for_cleanup(dump_dir)
+ if runner.dryrun:
+ print "would remove ", [dfname.filename for dfname in dfnames]
+ else:
+ for dfname in dfnames:
+ self.remove_output_file(dump_dir, dfname)
+
def run(self, runner):
commands = []
# Remove prior 7zip attempts; 7zip will try to append to an existing
archive
+ self.toss_inprog_files(runner.dump_dir, runner)
+
self.cleanup_old_files(runner.dump_dir, runner)
if self.checkpoint_file is not None:
output_dfname = DumpFilename(self.wiki, None,
self.checkpoint_file.dumpname,
@@ -489,12 +517,12 @@
dfnames = []
if self.item_for_recompression._checkpoints_enabled:
dfnames.extend(self.list_checkpt_files_for_filepart(
- dump_dir, self.get_fileparts_list(), dump_names))
+ dump_dir, self.get_fileparts_list(), dump_names, inprog=True))
dfnames.extend(self.list_temp_files_for_filepart(
dump_dir, self.get_fileparts_list(), dump_names))
else:
dfnames.extend(self.list_reg_files_for_filepart(
- dump_dir, self.get_fileparts_list(), dump_names))
+ dump_dir, self.get_fileparts_list(), dump_names, inprog=True))
return dfnames
def list_outfiles_for_input(self, dump_dir):
--
To view, visit https://gerrit.wikimedia.org/r/385368
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I6e858fe11a34c115441a92cea18988514bc8942e
Gerrit-PatchSet: 1
Gerrit-Project: operations/dumps
Gerrit-Branch: master
Gerrit-Owner: ArielGlenn <[email protected]>
Gerrit-Reviewer: ArielGlenn <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits