| #!/usr/bin/env python |
| |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| """ |
| qpid-qls-analyze |
| |
| Reads and analyzes a Qpid Linear Store (QLS) store directory. |
| """ |
| |
| import os.path |
| import sys |
| |
| default = os.path.normpath('/usr/share/qpid-tools') |
| home = os.environ.get('QPID_TOOLS_HOME', default) |
| sys.path.append(os.path.join(home, 'python')) |
| |
| import argparse |
| import os |
| import qlslibs.analyze |
| import qlslibs.efp |
| |
| class QlsAnalyzerArgParser(argparse.ArgumentParser): |
| """ |
| Class to handle command-line arguments. |
| """ |
| def __init__(self): |
| argparse.ArgumentParser.__init__(self, description='Qpid Linear Store Analyzer', prog='qpid-qls-analyze') |
| self.add_argument('qls_dir', metavar='DIR', |
| help='Qpid Linear Store (QLS) directory to be analyzed') |
| self.add_argument('--efp', action='store_true', |
| help='Analyze the Emtpy File Pool (EFP) and show stats') |
| self.add_argument('--show-recovered-recs', action='store_true', |
| help='Show only recovered records') |
| self.add_argument('--show-recovery-recs', action='store_true', |
| help='Show material records found during recovery') |
| self.add_argument('--show-all-recs', action='store_true', |
| help='Show all records (including fillers) found during recovery') |
| self.add_argument('--show-xids', action='store_true', |
| help='Show xid as hex number, otherwise show only xid length. Only has effect when records are shown') |
| # TODO: Add ability to show xid as an index rather than a value, helps analysis when xid is a long value with |
| # small differences which cannot easily be seen when looking at an output. Also prints a table of indeces vs xid values. |
| # self.add_argument('--show-xid-index', action='store_true', |
| # help='Show xids by index rather than by their value. Useful for long xids. Prints xid index table') |
| self.add_argument('--show-data', action='store_true', |
| help='Show data, otherwise show only data length. Only has effect when records are shown') |
| self.add_argument('--stats', action='store_true', |
| help='Print journal record stats') |
| self.add_argument('--txtest', action='store_true', |
| help='Show qpid-txtest message number as the message content when viewing records. Only has effect when records are shown') |
| self.add_argument('--txn', action='store_true', |
| help='Reconcile incomplete transactions') |
| self.add_argument('--version', action='version', |
| version='%(prog)s ' + QqpdLinearStoreAnalyzer.QLS_ANALYZE_VERSION) |
| def parse_args(self, args=None, namespace=None): |
| args = argparse.ArgumentParser.parse_args(self, args, namespace) |
| # If required, perform additional validity checks here, raise errors if req'd |
| return args |
| |
| class QqpdLinearStoreAnalyzer(object): |
| """ |
| Top-level store analyzer. Will analyze the directory in args.qls_dir as the top-level Qpid Linear Store (QLS) |
| directory. The following may be analyzed: |
| * The Empty File Pool (if --efp is specified in the arguments) |
| * The Linear Store |
| * The Transaction Prepared List (TPL) |
| """ |
| QLS_ANALYZE_VERSION = '1.0' |
| def __init__(self): |
| self.args = None |
| self._process_args() |
| self.qls_dir = os.path.abspath(self.args.qls_dir) |
| self.efp_manager = qlslibs.efp.EfpManager(self.qls_dir, None) |
| self.jrnl_recovery_mgr = qlslibs.analyze.JournalRecoveryManager(self.qls_dir, self.args) |
| def _process_args(self): |
| """ Create arg parser and process args """ |
| parser = QlsAnalyzerArgParser() |
| self.args = parser.parse_args() |
| if not os.path.exists(self.args.qls_dir): |
| parser.error('Journal path "%s" does not exist' % self.args.qls_dir) |
| def report(self): |
| """ Create a report on the linear store previously analyzed using analyze() """ |
| if self.args.efp: |
| self.efp_manager.report() |
| self.jrnl_recovery_mgr.report() |
| def run(self): |
| """ Run the analyzer, which reads and analyzes the linear store """ |
| if self.args.efp: |
| self.efp_manager.run(None) |
| self.jrnl_recovery_mgr.run() |
| |
| #============================================================================== |
| # main program |
| #============================================================================== |
| |
| if __name__ == "__main__": |
| M = QqpdLinearStoreAnalyzer() |
| M.run() |
| M.report() |