Ejemplo n.º 1
0
 def __parse_hdr(self, line: str) -> None:
     "Parse line from header"
     for key, valtype, name in items_hdr:
         if line.startswith(key):
             # Check for GSTAT_VERSION
             if self.gstat_version is None:
                 if key == 'System Change Number':
                     self.gstat_version = GSTAT_30
                 elif key == 'Checksum':
                     raise Error(
                         "Output from gstat older than Firebird 3 is not supported"
                     )
             #
             value: str = 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 = [DbAttribute(x) for x in value]
             else:
                 raise Error(f"Unknown value type {valtype}")
             if name is None:
                 name = key.lower().replace(' ', '_')
             setattr(self, name, value)
             return
     raise Error(f'Unknown information (line {self.__line_no})')
Ejemplo n.º 2
0
 def __parse_fseq(self, line: str) -> None:
     "Parse line from file sequence"
     if not line.startswith('File '):
         raise Error(f"Bad file specification (line {self.__line_no})")
     if 'is the only file' in line:
         return
     if ' is the ' in line:
         self.continuation_files.append(line[5:line.index(' is the ')])
     elif ' continues as' in line:
         self.continuation_files.append(line[5:line.index(' continues as')])
     else:
         raise Error(f"Bad file specification (line {self.__line_no})")
Ejemplo n.º 3
0
 def __parse_index(self, line: str) -> None:
     "Parse line from index data"
     if self.__index.name is None:
         # We should parse header
         iname, iid = line[6:].split(' (')
         self.__index.name = iname.strip(' "')
         self.__index.index_id = int(iid.strip('()'))
     else:
         if ',' in line:  # Data values
             for item in line.split(','):
                 item = item.strip()
                 found = False
                 items = items_idx3
                 for key, valtype, name in items:
                     if item.startswith(key):
                         value: str = item[len(key):].strip()
                         if valtype == 'i':  # integer
                             value = int(value)
                         elif valtype == 'f':  # float
                             value = float(value)
                         elif valtype == 'p':  # %
                             value = int(value.strip('%'))
                         else:
                             raise Error(f"Unknown value type {valtype}")
                         if name is None:
                             name = key.lower().strip(':').replace(' ', '_')
                         setattr(self.__index, name, value)
                         found = True
                         break
                 if not found:
                     raise Error(
                         f'Unknown information (line {self.__line_no})')
         else:  # Fill distribution
             if '=' in line:
                 fill_range, fill_value = line.split('=')
                 i = items_fill.index(fill_range.strip())
                 if self.__index.distribution is None:
                     self.__index.distribution = [0, 0, 0, 0, 0]
                 self.__index.distribution[i] = int(fill_value.strip())
             elif line.startswith('Fill distribution:'):
                 pass
             else:
                 raise Error(f'Unknown information (line {self.__line_no})')
Ejemplo n.º 4
0
 def __parse_var(self, line: str) -> None:
     "Parse line from variable header data"
     if line == '*END*':
         return
     for key, valtype, name in items_var:
         if line.startswith(key):
             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')
             else:
                 raise Error(f"Unknown value type {valtype}")
             if name is None:
                 name = key.lower().strip(':').replace(' ', '_')
             setattr(self, name, value)
             return
     raise Error(f'Unknown information (line {self.__line_no})')
Ejemplo n.º 5
0
 def __parse_encryption(self, line: str) -> None:
     "Parse line from encryption data"
     try:
         total, encrypted, unencrypted = line.split(',')
         pad, total = total.rsplit(' ', 1)
         total = int(total)
         pad, encrypted = encrypted.rsplit(' ', 1)
         encrypted = int(encrypted)
         pad, unencrypted = unencrypted.rsplit(' ', 1)
         unencrypted = int(unencrypted)
         data = Encryption(total, encrypted, unencrypted)
     except:
         raise Error(
             f'Malformed encryption information (line {self.__line_no})')
     if 'Data pages:' in line:
         self.encrypted_data_pages = data
     elif 'Index pages:' in line:
         self.encrypted_index_pages = data
     elif 'Blob pages:' in line:
         self.encrypted_blob_pages = data
     else:
         raise Error(
             f'Unknown encryption information (line {self.__line_no})')
Ejemplo n.º 6
0
    def parse_entry(self, log_entry: List[str]) -> LogMessage:
        """Parse single log entry.

        Arguments:
            log_entry: List with log entry lines.
        """
        try:
            items = log_entry[0].split()
            timestamp = datetime.strptime(' '.join(items[len(items) - 5:]),
                                          '%a %b %d %H:%M:%S %Y')
            origin = ' '.join(items[:len(items) - 5])
        except Exception as exc:
            raise Error("Malformed log entry") from exc
        msg = '\n'.join(log_entry[1:]).strip()
        #
        if (found := identify_msg(msg)) is not None:
            log_msg = found[0]
            return LogMessage(origin, timestamp, log_msg.severity,
                              log_msg.msg_id, log_msg.facility,
                              log_msg.get_pattern(found[2]), found[1])
Ejemplo n.º 7
0
    def push(self, line: Union[str, Sentinel]) -> None:
        """Push parser.

        Arguments:
            line: Single gstat output line, or `~firebird.base.types.STOP` sentinel.
        """
        if self.__step == -1:
            self.__clear()
        if line is STOP:
            if self.has_table_stats():
                for table in self.tables:
                    table.distribution = FillDistribution(*table.distribution)
            if self.has_index_stats():
                for index in self.indices:
                    index.distribution = FillDistribution(*index.distribution)
            self.tables.freeze()
            self.indices.freeze()
            self.__step = -1
        else:
            line = line.strip()
            self.__line_no += 1
            if line.startswith('Gstat completion time'):
                self.completed = datetime.datetime.strptime(
                    line[22:], '%a %b %d %H:%M:%S %Y')
            elif self.__step == 0:  # Looking for section or self name
                if line.startswith('Gstat execution time'):
                    self.executed = datetime.datetime.strptime(
                        line[21:], '%a %b %d %H:%M:%S %Y')
                elif line.startswith('Database header page information:'):
                    self.__step = 1
                elif line.startswith('Variable header data:'):
                    self.__step = 2
                elif line.startswith('Database file sequence:'):
                    self.__step = 3
                elif 'encrypted' in line and 'non-crypted' in line:
                    self.__parse_encryption(line)
                elif line.startswith('Analyzing database pages ...'):
                    self.__step = 4
                elif empty_str(line):
                    pass
                elif line.startswith('Database "'):
                    x, s = line.split(' ')
                    self.filename = s.strip('"')
                    self.__step = 0
                else:
                    raise Error(f"Unrecognized data (line {self.__line_no})")
            elif self.__step == 1:  # Header
                if empty_str(line):  # section ends with empty line
                    self.__step = 0
                else:
                    self.__parse_hdr(line)
            elif self.__step == 2:  # Variable data
                if empty_str(line):  # section ends with empty line
                    self.__step = 0
                else:
                    self.__parse_var(line)
            elif self.__step == 3:  # File sequence
                if empty_str(line):  # section ends with empty line
                    self.__step = 0
                else:
                    self.__parse_fseq(line)
            elif self.__step == 4:  # Tables and indices
                if empty_str(line):  # section ends with empty line
                    self.__new_block = True
                else:
                    if self.__new_block:
                        self.__new_block = False
                        if not line.startswith('Index '):
                            # Should be table
                            self.__table = StatTable()
                            self.tables.append(self.__table)
                            self.__in_table = True
                            self.__parse_table(line)
                        else:  # It's index
                            self.__index = StatIndex(self.__table)
                            self.indices.append(self.__index)
                            self.__in_table = False
                            self.__parse_index(line)
                    else:
                        if self.__in_table:
                            self.__parse_table(line)
                        else:
                            self.__parse_index(line)