示例#1
0
 def parse_hdr(line):
     "Parse line from header"
     for key, valtype, name in items_hdr:
         if line.startswith(key):
             # Check for GSTAT_VERSION
             if db.gstat_version is None:
                 if key == 'Checksum':
                     db.gstat_version = GSTAT_25
                     db.tables = ObjectList(_cls=StatTable, key_expr='item.name')
                     db.indices = ObjectList(_cls=StatIndex, key_expr='item.name')
                 elif key == 'System Change Number':
                     db.gstat_version = GSTAT_30
                     db.tables = ObjectList(_cls=StatTable3, key_expr='item.name')
                     db.indices = ObjectList(_cls=StatIndex3, key_expr='item.name')
             #
             value = line[len(key):].strip()
             if valtype == 'i':  # integer
                 value = int(value)
             elif valtype == 's':  # string
                 pass
             elif valtype == 'd':  # date time
                 value = datetime.datetime.strptime(value, '%b %d, %Y %H:%M:%S')
             elif valtype == 'l':  # list
                 if value == '':
                     value = []
                 else:
                     value = [x.strip() for x in value.split(',')]
                     value = tuple([ATTRIBUTES.index(x) for x in value])
             else:
                 raise ParseError("Unknown value type %s" % valtype)
             if name is None:
                 name = key.lower().replace(' ', '_')
             setattr(db, name, value)
             return
     raise ParseError('Unknown information (line %i)' % line_no)
示例#2
0
 def _get_variables(self):
     if self.__variables is None:
         self.__fail_if_closed()
         if self._con.ods >= fdb.ODS_FB_25:
             self._ic.execute("select * from mon$context_variables")
             self.__variables = ObjectList((ContextVariableInfo(self, row) for row in self._ic.itermap()), ContextVariableInfo, 'item.stat_id')
         else:
             self.__variables = ObjectList()
         self.__variables.freeze()
     return self.__variables
示例#3
0
 def _get_callstack(self):
     if self.__callstack is None:
         self.__fail_if_closed()
         if self._con.ods >= fdb.ODS_FB_21:
             self._ic.execute("select * from mon$call_stack")
             self.__callstack = ObjectList((CallStackInfo(self, row) for row in self._ic.itermap()), CallStackInfo, 'item.id')
         else:
             self.__callstack = ObjectList()
         self.__callstack.freeze()
     return self.__callstack
示例#4
0
 def _get_statements(self):
     if self.__statements is None:
         self.__fail_if_closed()
         if self._con.ods >= fdb.ODS_FB_21:
             self._ic.execute("select * from mon$statements")
             self.__statements = ObjectList((StatementInfo(self, row) for row in self._ic.itermap()), StatementInfo, 'item.id')
         else:
             self.__statements = ObjectList()
         self.__statements.freeze()
     return self.__statements
示例#5
0
 def _get_transactions(self):
     if self.__transactions is None:
         self.__fail_if_closed()
         if self._con.ods >= fdb.ODS_FB_21:
             self._ic.execute("select * from mon$transactions")
             self.__transactions = ObjectList((TransactionInfo(self, row) for row in self._ic.itermap()), TransactionInfo, 'item.id')
         else:
             self.__transactions = ObjectList()
         self.__transactions.freeze()
     return self.__transactions
示例#6
0
    def _get_tablestats(self):
        if self.__tablestats is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_30:
                self._ic.execute("""SELECT ts.MON$STAT_ID, ts.MON$STAT_GROUP, ts.MON$TABLE_NAME,
ts.MON$RECORD_STAT_ID, r.MON$RECORD_SEQ_READS, r.MON$RECORD_IDX_READS, r.MON$RECORD_INSERTS,
r.MON$RECORD_UPDATES, r.MON$RECORD_DELETES, r.MON$RECORD_BACKOUTS,
r.MON$RECORD_PURGES, r.MON$RECORD_EXPUNGES, r.MON$RECORD_LOCKS, r.MON$RECORD_WAITS,
r.MON$RECORD_CONFLICTS, r.MON$BACKVERSION_READS, r.MON$FRAGMENT_READS, r.MON$RECORD_RPT_READS
FROM MON$TABLE_STATS ts join MON$RECORD_STATS r
  on ts.MON$RECORD_STAT_ID = r.MON$STAT_ID""")
                self.__tablestats = ObjectList((TableStatsInfo(self, row) for row in self._ic.itermap()), TableStatsInfo, 'item.stat_id')
            else:
                self.__tablestats = ObjectList()
            self.__tablestats.freeze()
        return self.__tablestats
示例#7
0
    def _get_iostats(self):
        if self.__iostats is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_30:
                self._ic.execute("""SELECT r.MON$STAT_ID, r.MON$STAT_GROUP,
r.MON$RECORD_SEQ_READS, r.MON$RECORD_IDX_READS, r.MON$RECORD_INSERTS,
r.MON$RECORD_UPDATES, r.MON$RECORD_DELETES, r.MON$RECORD_BACKOUTS,
r.MON$RECORD_PURGES, r.MON$RECORD_EXPUNGES, r.MON$RECORD_LOCKS, r.MON$RECORD_WAITS,
r.MON$RECORD_CONFLICTS, r.MON$BACKVERSION_READS, r.MON$FRAGMENT_READS, r.MON$RECORD_RPT_READS,
io.MON$PAGE_FETCHES, io.MON$PAGE_MARKS, io.MON$PAGE_READS, io.MON$PAGE_WRITES,
m.MON$MEMORY_ALLOCATED, m.MON$MEMORY_USED, m.MON$MAX_MEMORY_ALLOCATED, m.MON$MAX_MEMORY_USED
FROM MON$RECORD_STATS r join MON$IO_STATS io
  on r.MON$STAT_ID = io.MON$STAT_ID and r.MON$STAT_GROUP = io.MON$STAT_GROUP
  join MON$MEMORY_USAGE m
  on r.MON$STAT_ID = m.MON$STAT_ID and r.MON$STAT_GROUP = m.MON$STAT_GROUP""")
            elif self._con.ods >= fdb.ODS_FB_25:
                self._ic.execute("""SELECT r.MON$STAT_ID, r.MON$STAT_GROUP,
r.MON$RECORD_SEQ_READS, r.MON$RECORD_IDX_READS, r.MON$RECORD_INSERTS,
r.MON$RECORD_UPDATES, r.MON$RECORD_DELETES, r.MON$RECORD_BACKOUTS,
r.MON$RECORD_PURGES, r.MON$RECORD_EXPUNGES, io.MON$PAGE_FETCHES,
io.MON$PAGE_MARKS, io.MON$PAGE_READS, io.MON$PAGE_WRITES, m.MON$MEMORY_ALLOCATED,
m.MON$MEMORY_USED, m.MON$MAX_MEMORY_ALLOCATED, m.MON$MAX_MEMORY_USED
FROM MON$RECORD_STATS r join MON$IO_STATS io
  on r.MON$STAT_ID = io.MON$STAT_ID and r.MON$STAT_GROUP = io.MON$STAT_GROUP
  join MON$MEMORY_USAGE m
  on r.MON$STAT_ID = m.MON$STAT_ID and r.MON$STAT_GROUP = m.MON$STAT_GROUP""")
            elif self._con.ods >= fdb.ODS_FB_21:
                self._ic.execute("""SELECT r.MON$STAT_ID, r.MON$STAT_GROUP,
r.MON$RECORD_SEQ_READS, r.MON$RECORD_IDX_READS, r.MON$RECORD_INSERTS,
r.MON$RECORD_UPDATES, r.MON$RECORD_DELETES, r.MON$RECORD_BACKOUTS,
r.MON$RECORD_PURGES, r.MON$RECORD_EXPUNGES, io.MON$PAGE_FETCHES,
io.MON$PAGE_MARKS, io.MON$PAGE_READS, io.MON$PAGE_WRITES
FROM MON$RECORD_STATS r join MON$IO_STATS io
on r.MON$STAT_ID = io.MON$STAT_ID and r.MON$STAT_GROUP = io.MON$STAT_GROUP""")
            if self._con.ods >= fdb.ODS_FB_21:
                self.__iostats = ObjectList((IOStatsInfo(self, row) for row in self._ic.itermap()), IOStatsInfo, 'item.stat_id')
            else:
                self.__iostats = ObjectList()
            self.__iostats.freeze()
        return self.__iostats
示例#8
0
class Monitor(object):
    """Class for access to Firebird monitoring tables.
    """
    def __init__(self):
        self._con = None
        self._ic = None
        self.__internal = False
        self.clear()
    def __del__(self):
        if not self.closed:
            self._close()
    def __get_closed(self):
        return self._con is None
    def __fail_if_closed(self):
        if self.closed:
            raise fdb.ProgrammingError("Monitor is not binded to connection.")
    def _close(self):
        self._ic.close()
        self._con = None
        self._ic = None
    def _set_as_internal(self):
        """Mark this instance as `internal` (embedded). This blocks calls to
        :meth:`bind` and :meth:`close`."""
        self.__internal = True
        self._con = weakref.proxy(self._con)

        #--- protected

    def _get_database(self):
        if self.__database is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_21:
                self._ic.execute("select * from mon$database")
                self.__database = DatabaseInfo(self, self._ic.fetchonemap())
        return self.__database
    def _get_attachments(self):
        if self.__attachments is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_21:
                self._ic.execute("select * from mon$attachments")
                self.__attachments = ObjectList((AttachmentInfo(self, row) for row in self._ic.itermap()), AttachmentInfo, 'item.id')
            else:
                self.__attachments = ObjectList()
            self.__attachments.freeze()
        return self.__attachments
    def _get_this_attachment(self):
        return self.get_attachment(self._con.db_info(fdb.isc_info_attachment_id))
    def _get_transactions(self):
        if self.__transactions is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_21:
                self._ic.execute("select * from mon$transactions")
                self.__transactions = ObjectList((TransactionInfo(self, row) for row in self._ic.itermap()), TransactionInfo, 'item.id')
            else:
                self.__transactions = ObjectList()
            self.__transactions.freeze()
        return self.__transactions
    def _get_statements(self):
        if self.__statements is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_21:
                self._ic.execute("select * from mon$statements")
                self.__statements = ObjectList((StatementInfo(self, row) for row in self._ic.itermap()), StatementInfo, 'item.id')
            else:
                self.__statements = ObjectList()
            self.__statements.freeze()
        return self.__statements
    def _get_callstack(self):
        if self.__callstack is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_21:
                self._ic.execute("select * from mon$call_stack")
                self.__callstack = ObjectList((CallStackInfo(self, row) for row in self._ic.itermap()), CallStackInfo, 'item.id')
            else:
                self.__callstack = ObjectList()
            self.__callstack.freeze()
        return self.__callstack
    def _get_iostats(self):
        if self.__iostats is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_30:
                self._ic.execute("""SELECT r.MON$STAT_ID, r.MON$STAT_GROUP,
r.MON$RECORD_SEQ_READS, r.MON$RECORD_IDX_READS, r.MON$RECORD_INSERTS,
r.MON$RECORD_UPDATES, r.MON$RECORD_DELETES, r.MON$RECORD_BACKOUTS,
r.MON$RECORD_PURGES, r.MON$RECORD_EXPUNGES, r.MON$RECORD_LOCKS, r.MON$RECORD_WAITS,
r.MON$RECORD_CONFLICTS, r.MON$BACKVERSION_READS, r.MON$FRAGMENT_READS, r.MON$RECORD_RPT_READS,
io.MON$PAGE_FETCHES, io.MON$PAGE_MARKS, io.MON$PAGE_READS, io.MON$PAGE_WRITES,
m.MON$MEMORY_ALLOCATED, m.MON$MEMORY_USED, m.MON$MAX_MEMORY_ALLOCATED, m.MON$MAX_MEMORY_USED
FROM MON$RECORD_STATS r join MON$IO_STATS io
  on r.MON$STAT_ID = io.MON$STAT_ID and r.MON$STAT_GROUP = io.MON$STAT_GROUP
  join MON$MEMORY_USAGE m
  on r.MON$STAT_ID = m.MON$STAT_ID and r.MON$STAT_GROUP = m.MON$STAT_GROUP""")
            elif self._con.ods >= fdb.ODS_FB_25:
                self._ic.execute("""SELECT r.MON$STAT_ID, r.MON$STAT_GROUP,
r.MON$RECORD_SEQ_READS, r.MON$RECORD_IDX_READS, r.MON$RECORD_INSERTS,
r.MON$RECORD_UPDATES, r.MON$RECORD_DELETES, r.MON$RECORD_BACKOUTS,
r.MON$RECORD_PURGES, r.MON$RECORD_EXPUNGES, io.MON$PAGE_FETCHES,
io.MON$PAGE_MARKS, io.MON$PAGE_READS, io.MON$PAGE_WRITES, m.MON$MEMORY_ALLOCATED,
m.MON$MEMORY_USED, m.MON$MAX_MEMORY_ALLOCATED, m.MON$MAX_MEMORY_USED
FROM MON$RECORD_STATS r join MON$IO_STATS io
  on r.MON$STAT_ID = io.MON$STAT_ID and r.MON$STAT_GROUP = io.MON$STAT_GROUP
  join MON$MEMORY_USAGE m
  on r.MON$STAT_ID = m.MON$STAT_ID and r.MON$STAT_GROUP = m.MON$STAT_GROUP""")
            elif self._con.ods >= fdb.ODS_FB_21:
                self._ic.execute("""SELECT r.MON$STAT_ID, r.MON$STAT_GROUP,
r.MON$RECORD_SEQ_READS, r.MON$RECORD_IDX_READS, r.MON$RECORD_INSERTS,
r.MON$RECORD_UPDATES, r.MON$RECORD_DELETES, r.MON$RECORD_BACKOUTS,
r.MON$RECORD_PURGES, r.MON$RECORD_EXPUNGES, io.MON$PAGE_FETCHES,
io.MON$PAGE_MARKS, io.MON$PAGE_READS, io.MON$PAGE_WRITES
FROM MON$RECORD_STATS r join MON$IO_STATS io
on r.MON$STAT_ID = io.MON$STAT_ID and r.MON$STAT_GROUP = io.MON$STAT_GROUP""")
            if self._con.ods >= fdb.ODS_FB_21:
                self.__iostats = ObjectList((IOStatsInfo(self, row) for row in self._ic.itermap()), IOStatsInfo, 'item.stat_id')
            else:
                self.__iostats = ObjectList()
            self.__iostats.freeze()
        return self.__iostats
    def _get_variables(self):
        if self.__variables is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_25:
                self._ic.execute("select * from mon$context_variables")
                self.__variables = ObjectList((ContextVariableInfo(self, row) for row in self._ic.itermap()), ContextVariableInfo, 'item.stat_id')
            else:
                self.__variables = ObjectList()
            self.__variables.freeze()
        return self.__variables
    def _get_tablestats(self):
        if self.__tablestats is None:
            self.__fail_if_closed()
            if self._con.ods >= fdb.ODS_FB_30:
                self._ic.execute("""SELECT ts.MON$STAT_ID, ts.MON$STAT_GROUP, ts.MON$TABLE_NAME,
ts.MON$RECORD_STAT_ID, r.MON$RECORD_SEQ_READS, r.MON$RECORD_IDX_READS, r.MON$RECORD_INSERTS,
r.MON$RECORD_UPDATES, r.MON$RECORD_DELETES, r.MON$RECORD_BACKOUTS,
r.MON$RECORD_PURGES, r.MON$RECORD_EXPUNGES, r.MON$RECORD_LOCKS, r.MON$RECORD_WAITS,
r.MON$RECORD_CONFLICTS, r.MON$BACKVERSION_READS, r.MON$FRAGMENT_READS, r.MON$RECORD_RPT_READS
FROM MON$TABLE_STATS ts join MON$RECORD_STATS r
  on ts.MON$RECORD_STAT_ID = r.MON$STAT_ID""")
                self.__tablestats = ObjectList((TableStatsInfo(self, row) for row in self._ic.itermap()), TableStatsInfo, 'item.stat_id')
            else:
                self.__tablestats = ObjectList()
            self.__tablestats.freeze()
        return self.__tablestats

    #--- Properties

    #: True if link to :class:`~fdb.Connection` is closed.
    closed = property(__get_closed)
    db = LateBindingProperty(_get_database, doc=":class:`DatabaseInfo` object for attached database.")
    attachments = LateBindingProperty(_get_attachments, doc=":class:`~fdb.utils.ObjectList` of all attachments.\nItems are :class:`AttachmentInfo` objects.")
    this_attachment = LateBindingProperty(_get_this_attachment, doc=":class:`AttachmentInfo` object for current connection.")
    transactions = LateBindingProperty(_get_transactions, doc=":class:`~fdb.utils.ObjectList` of all transactions.\nItems are :class:`TransactionInfo` objects.")
    statements = LateBindingProperty(_get_statements, doc=":class:`~fdb.utils.ObjectList` of all statements.\nItems are :class:`StatementInfo` objects.")
    callstack = LateBindingProperty(_get_callstack, doc=":class:`~fdb.utils.ObjectList` with complete call stack.\nItems are :class:`CallStackInfo` objects.")
    iostats = LateBindingProperty(_get_iostats, doc=":class:`~fdb.utils.ObjectList` of all I/O statistics.\nItems are :class:`IOStatsInfo` objects.")
    variables = LateBindingProperty(_get_variables, doc=":class:`~fdb.utils.ObjectList` of all context variables.\nItems are :class:`ContextVariableInfo` objects.")
    # FB 3.0
    tablestats = LateBindingProperty(_get_tablestats, doc=":class:`~fdb.utils.ObjectList` of all table record I/O statistics.\nItems are :class:`TableStatsInfo` objects.")

    #--- Public

    def bind(self, connection):
        """Bind this instance to specified :class:`~fdb.Connection`.

        :param connection: :class:`~fdb.Connection` instance.

        :raises fdb.ProgrammingError: If Monitor object was set as internal (via
            :meth:`_set_as_internal`) or database has ODS lower than 11.1.
        """
        if self.__internal:
            raise fdb.ProgrammingError("Call to 'bind' not allowed for embedded Monitor.")
        if self._con:
            self.close()
        if connection.ods < fdb.ODS_FB_21:
            raise fdb.ProgrammingError("Monitoring tables are available only " \
                                       "for databases with ODS 11.1 and higher.")
        self._con = connection
        self._ic = self._con.trans(fdb.ISOLATION_LEVEL_READ_COMMITED_RO).cursor()
        self.clear()
    def close(self):
        """Sever link to :class:`~fdb.Connection`.

        :raises fdb.ProgrammingError: If Monitor object was set as internal (via
            :meth:`_set_as_internal`).
        """
        if self.__internal:
            raise fdb.ProgrammingError("Call to 'close' not allowed for embedded Monitor.")
        self._close()
        self.clear()
    def clear(self):
        """Drop all cached information objects. Force reload of fresh monitoring
        information on next reference."""
        self.__database = None
        self.__attachments = None
        self.__transactions = None
        self.__statements = None
        self.__callstack = None
        self.__iostats = None
        self.__variables = None
        self.__tablestats = None
        if not self.closed:
            self._ic.transaction.commit()
    def refresh(self):
        "Reloads fresh monitoring information."
        self.__fail_if_closed()
        self._ic.transaction.commit()
        self.clear()
        self._get_database()
    def get_attachment(self, id):
        """Get :class:`AttachmentInfo` by ID.

        :param int id: Attachment ID.

        :returns: :class:`AttachmentInfo` with specified ID or `None`.
        """
        for attachment in self.attachments:
            if attachment.id == id:
                return attachment
        else:
            return None
    def get_transaction(self, id):
        """Get :class:`TransactionInfo` by ID.

        :param int id: Transaction ID.

        :returns: :class:`TransactionInfo` with specified ID or `None`.
        """
        for transaction in self.transactions:
            if transaction.id == id:
                return transaction
        else:
            return None
    def get_statement(self, id):
        """Get :class:`StatementInfo` by ID.

        :param int id: Statement ID.

        :returns: :class:`StatementInfo` with specified ID or `None`.
        """
        for statement in self.statements:
            if statement.id == id:
                return statement
        else:
            return None
    def get_call(self, id):
        """Get :class:`CallStackInfo` by ID.

        :param int id: Callstack ID.

        :returns: :class:`CallStackInfo` with specified ID or `None`.
        """
        for call in self.callstack:
            if call.id == id:
                return call
        else:
            return None