r84350 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r84349‎ | r84350 | r84351 >
Date:21:17, 19 March 2011
Author:ariel
Status:deferred
Tags:
Comment:
replace stats php call with much more accurate max() mysql query, toss some duplicate code
Modified paths:
  • /branches/ariel/xmldumps-backup/worker.py (modified) (history)

Diff [purge]

Index: branches/ariel/xmldumps-backup/worker.py
@@ -169,32 +169,108 @@
170170 return 0
171171 return chunks
172172
 173+class DbServerInfo(object):
 174+ def __init__(self, wiki, dbName):
 175+ self.config = wiki.config
 176+ self.dbName = dbName
 177+ self.selectDatabaseServer()
 178+
 179+ def defaultServer(self):
 180+ # if this fails what do we do about it? Not a bleeping thing. *ugh* FIXME!!
 181+ command = "%s -q %s/maintenance/getSlaveServer.php --wiki=%s --group=dump" % shellEscape((
 182+ self.config.php, self.config.wikiDir, self.dbName))
 183+ return RunSimpleCommand.runAndReturn(command).strip()
 184+
 185+ def selectDatabaseServer(self):
 186+ self.dbServer = self.defaultServer()
 187+
 188+ def runSqlAndGetOutput(self, query):
 189+ """Pass some SQL commands to the server for this DB and save output to a file."""
 190+ command = [ [ "/bin/echo", "%s" % query ],
 191+ [ "%s" % self.config.mysql, "-h",
 192+ "%s" % self.dbServer,
 193+ "-u", "%s" % self.config.dbUser,
 194+ "%s" % self.passwordOption(),
 195+ "%s" % self.dbName,
 196+ "-r" ] ]
 197+ p = CommandPipeline(command, quiet=True)
 198+ p.runPipelineAndGetOutput()
 199+ # fixme best to put the return code someplace along with any errors....
 200+ if (p.output()):
 201+ return(p.output())
 202+ else:
 203+ return None
 204+
 205+ def passwordOption(self):
 206+ """If you pass '-pfoo' mysql uses the password 'foo',
 207+ but if you pass '-p' it prompts. Sigh."""
 208+ if self.config.dbPassword == "":
 209+ return None
 210+ else:
 211+ return "-p" + self.config.dbPassword
 212+
 213+
 214+class RunSimpleCommand(object):
 215+
 216+ def log(self, message, log = None):
 217+ if (log):
 218+ log.addToLogQueue("%s\n" % message)
 219+
 220+ # FIXME rewrite to not use popen2
 221+ def runAndReturn(command, log = None):
 222+ """Run a command and return the output as a string.
 223+ Raises BackupError on non-zero return code."""
 224+ # FIXME convert all these calls so they just use runCommand now
 225+ proc = popen2.Popen4(command, 64)
 226+ output = proc.fromchild.read()
 227+ retval = proc.wait()
 228+ if retval:
 229+ self.log("Non-zero return code from '%s'" % command, log)
 230+ raise BackupError("Non-zero return code from '%s'" % command)
 231+ else:
 232+ return output
 233+
 234+ def runAndReport(self, command, callback):
 235+ """Shell out to a command, and feed output lines to the callback function.
 236+ Returns the exit code from the program once complete.
 237+ stdout and stderr will be combined into a single stream.
 238+ """
 239+ # FIXME convert all these calls so they just use runCommand now
 240+ proc = popen2.Popen4(command, 64)
 241+ #for line in proc.fromchild:
 242+ # callback(self, line)
 243+ line = proc.fromchild.readline()
 244+ while line:
 245+ callback(self, line)
 246+ line = proc.fromchild.readline()
 247+ return proc.wait()
 248+
 249+ runAndReturn = staticmethod(runAndReturn)
 250+ runAndReport = staticmethod(runAndReport)
 251+
173252 class PageAndEditStats(object):
174253 def __init__(self, wiki, dbName):
175254 self.totalPages = None
176255 self.totalEdits = None
177256 self.config = wiki.config
178257 self.dbName = dbName
 258+ self.dbServerInfo = DbServerInfo(wiki, dbName)
179259 (self.totalPages, totalEdits) = self.getStatistics(config,dbName)
180260
181 - def getStatistics(self, config,dbName):
 261+ def getStatistics(self, dbName, ignore):
182262 """Get (cached) statistics for the wiki"""
183263 totalPages = None
184264 totalEdits = None
185 - statsCommand = """%s -q %s/maintenance/showStats.php --wiki=%s """ % shellEscape((
186 - self.config.php, self.config.wikiDir, self.dbName))
187 - # FIXME runAndReturn? defined somewhere else
188 - results = self.runAndReturn(statsCommand)
 265+ query = "select MAX(page_id) from page;"
 266+ results = self.dbServerInfo.runSqlAndGetOutput(query)
189267 lines = results.splitlines()
190 - if (lines):
191 - for line in lines:
192 - (name,value) = line.split(':')
193 - name = name.replace(' ','')
194 - value = value.replace(' ','')
195 - if (name == "Totalpages"):
196 - totalPages = int(value)
197 - elif (name == "Totaledits"):
198 - totalEdits = int(value)
 268+ if (lines and lines[1]):
 269+ totalPages = int(lines[1])
 270+ query = "select MAX(rev_id) from revision;"
 271+ results = self.dbServerInfo.runSqlAndGetOutput(query)
 272+ lines = results.splitlines()
 273+ if (lines and lines[1]):
 274+ totalEdits = int(lines[1])
199275 return(totalPages, totalEdits)
200276
201277 def getTotalPages(self):
@@ -203,19 +279,6 @@
204280 def getTotalEdits(self):
205281 return self.totalEdits
206282
207 - # FIXME should rewrite this I guess and also move it elsewhere, phooey
208 - def runAndReturn(self, command):
209 - """Run a command and return the output as a string.
210 - Raises BackupError on non-zero return code."""
211 - # FIXME convert all these calls so they just use runCommand now
212 - proc = popen2.Popen4(command, 64)
213 - output = proc.fromchild.read()
214 - retval = proc.wait()
215 - if retval:
216 - raise BackupError("Non-zero return code from '%s'" % command)
217 - else:
218 - return output
219 -
220283 class BackupError(Exception):
221284 pass
222285
@@ -618,6 +681,8 @@
619682 self.checkpoint = checkpoint
620683
621684 self.jobRequested = job
 685+ self.dbServerInfo = DbServerInfo(self.wiki, self.dbName)
 686+
622687 self.dumpDir = DumpDir(self.wiki, self.dbName, self.date)
623688
624689 # this must come after the dumpdir setup so we know which directory we are in
@@ -645,14 +710,6 @@
646711 self.log.addToLogQueue("%s\n" % message)
647712 print message
648713
649 - def passwordOption(self):
650 - """If you pass '-pfoo' mysql uses the password 'foo',
651 - but if you pass '-p' it prompts. Sigh."""
652 - if self.config.dbPassword == "":
653 - return None
654 - else:
655 - return "-p" + self.config.dbPassword
656 -
657714 def forceNormalOption(self):
658715 if self.config.forceNormal:
659716 return "--force-normal"
@@ -664,14 +721,14 @@
665722 # FIXME later full path
666723 command = "echo 'print $wgDBprefix; ' | %s -q %s/maintenance/eval.php --wiki=%s" % shellEscape((
667724 self.config.php, self.config.wikiDir, self.dbName))
668 - return self.runAndReturn(command).strip()
 725+ return RunSimpleCommand.runAndReturn(command, self.log).strip()
669726
670727 def saveTable(self, table, outfile):
671728 """Dump a table from the current DB with mysqldump, save to a gzipped sql file."""
672729 commands = [ [ "%s" % self.config.mysqldump, "-h",
673 - "%s" % self.dbServer, "-u",
 730+ "%s" % self.dbServerInfo.dbServer, "-u",
674731 "%s" % self.config.dbUser,
675 - "%s" % self.passwordOption(), "--opt", "--quick",
 732+ "%s" % self.dbServerInfo.passwordOption(), "--opt", "--quick",
676733 "--skip-add-locks", "--skip-lock-tables",
677734 "%s" % self.dbName,
678735 "%s" % self.getDBTablePrefix() + table ],
@@ -683,9 +740,9 @@
684741 """Pass some SQL commands to the server for this DB and save output to a file."""
685742 command = [ [ "/bin/echo", "%s" % query ],
686743 [ "%s" % self.config.mysql, "-h",
687 - "%s" % self.dbServer,
 744+ "%s" % self.dbServerInfo.dbServer,
688745 "-u", "%s" % self.config.dbUser,
689 - "%s" % self.passwordOption(),
 746+ "%s" % self.dbServerInfo.passwordOption(),
690747 "%s" % self.dbName,
691748 "-r" ],
692749 [ "%s" % self.config.gzip ] ]
@@ -697,25 +754,6 @@
698755 series = [ commands ]
699756 return self.runCommand([ series ])
700757
701 - def getStatistics(self, dbName):
702 - """Get (cached) statistics for the wiki"""
703 - totalPages = None
704 - totalEdits = None
705 - statsCommand = """%s -q %s/maintenance/showStats.php --wiki=%s """ % shellEscape((
706 - self.config.php, self.config.wikiDir, self.dbName))
707 - results = self.runAndReturn(statsCommand)
708 - lines = results.splitlines()
709 - if (lines):
710 - for line in lines:
711 - (name,value) = line.split(':')
712 - name = name.replace(' ','')
713 - value = value.replace(' ','')
714 - if (name == "Totalpages"):
715 - totalPages = int(value)
716 - elif (name == "Totaledits"):
717 - totalEdits = int(value)
718 - return(totalPages, totalEdits)
719 -
720758 # command series list: list of (commands plus args) is one pipeline. list of pipelines = 1 series.
721759 # this function wants a list of series.
722760 # be a list (the command name and the various args)
@@ -735,7 +773,6 @@
736774 if commands.exitedSuccessfully():
737775 return 0
738776 else:
739 - #print "***** BINGBING retval is '%s' ********" % retval
740777 problemCommands = commands.commandsWithErrors()
741778 errorString = "Error from command(s): "
742779 for cmd in problemCommands:
@@ -744,34 +781,6 @@
745782 raise BackupError(errorString)
746783 return 1
747784
748 - def runAndReport(self, command, callback):
749 - """Shell out to a command, and feed output lines to the callback function.
750 - Returns the exit code from the program once complete.
751 - stdout and stderr will be combined into a single stream.
752 - """
753 - # FIXME convert all these calls so they just use runCommand now
754 - proc = popen2.Popen4(command, 64)
755 - #for line in proc.fromchild:
756 - # callback(self, line)
757 - line = proc.fromchild.readline()
758 - while line:
759 - callback(self, line)
760 - line = proc.fromchild.readline()
761 - return proc.wait()
762 -
763 - def runAndReturn(self, command):
764 - """Run a command and return the output as a string.
765 - Raises BackupError on non-zero return code."""
766 - # FIXME convert all these calls so they just use runCommand now
767 - proc = popen2.Popen4(command, 64)
768 - output = proc.fromchild.read()
769 - retval = proc.wait()
770 - if retval:
771 - self.logAndPrint("Non-zero return code from '%s'" % command)
772 - raise BackupError("Non-zero return code from '%s'" % command)
773 - else:
774 - return output
775 -
776785 def debug(self, stuff):
777786 self.logAndPrint("%s: %s %s" % (prettyTime(), self.dbName, stuff))
778787 # print "%s: %s %s" % (prettyTime(), self.dbName, stuff)
@@ -783,14 +792,6 @@
784793 self.debug("Creating %s ..." % dir)
785794 os.makedirs(dir)
786795
787 - def selectDatabaseServer(self):
788 - self.dbServer = self.defaultServer()
789 -
790 - def defaultServer(self):
791 - command = "%s -q %s/maintenance/getSlaveServer.php --wiki=%s --group=dump" % shellEscape((
792 - self.config.php, self.config.wikiDir, self.dbName))
793 - return self.runAndReturn(command).strip()
794 -
795796 def runHandleFailure(self):
796797 if self.failCount < 1:
797798 # Email the site administrator just once per database
@@ -850,7 +851,7 @@
851852 self.cleanOldDumps()
852853 self.showRunnerState("Starting backup of %s" % self.dbName)
853854
854 - self.selectDatabaseServer()
 855+ self.DbServerInfo = DbServerInfo(self.wiki,self.dbName)
855856
856857 files = self.listFilesFor(self.dumpItemList.dumpItems)
857858

Status & tagging log