def read_entry(entry_number): app.logger.info("Read entry '%s'", str(entry_number)) cursor = start() try: entry_count = count_entries(cursor) if int(entry_number) > entry_count: return None cursor.execute( 'SELECT entry_timestamp, item_hash, key, item_signature ' 'FROM entry ' 'WHERE entry_number=%(number)s', {"number": entry_number}) row = cursor.fetchone() if row is None: return create_empty_entry(entry_number) return { "entry-number": entry_number, "entry-timestamp": row['entry_timestamp'].strftime('%Y-%m-%d %H:%M:%S.%f'), "item-hash": row['item_hash'], "key": row['key'], "item-signature": row['item_signature'] } finally: commit(cursor)
def leaf_hash(self, entry_number): app.logger.info("Read entry hash for entry number %s", str(entry_number)) self.cursor.execute( 'SELECT entry_hash FROM leaf_hashes ' 'WHERE entry_number=%(number)s', {'number': entry_number}) row = self.cursor.fetchone() if row is None: app.logger.error("No row found for entry %s", str(entry_number)) return calculate_leaf_hash( create_empty_entry(entry_number)).decode() return row['entry_hash']
def read_entries(cursor, offset, limit, max_entry_number): app.logger.info("Read %s entries starting at %s", str(limit), str(offset)) top_of_range = max_entry_number - offset bottom_of_range = top_of_range - limit if bottom_of_range < 0: bottom_of_range = 0 cursor.execute( 'SELECT entry_number, entry_timestamp, item_hash, key, item_signature ' 'FROM entry ' 'WHERE entry_number > %(bottom)s AND entry_number <= %(top)s ' 'ORDER BY entry_number DESC', { 'bottom': bottom_of_range, 'top': top_of_range }) rows = cursor.fetchall() result = [] entry_dict = {} for row in rows: entry = { "entry-number": row['entry_number'], "entry-timestamp": row['entry_timestamp'].strftime('%Y-%m-%d %H:%M:%S.%f'), "item-hash": row['item_hash'], "key": row['key'], "entry-signature": row['item_signature'] } entry_dict[int(row['entry_number'])] = entry for i in range(top_of_range, bottom_of_range, -1): if i in entry_dict: result.append(entry_dict[i]) else: result.append(create_empty_entry(i)) return result
def test_empty_leaf_hash(self): leaf_hash = calculate_leaf_hash(create_empty_entry(698)).decode() self.assertEqual( leaf_hash, 'F0C3DCD45728134CF63D4C59B9BA442D6056E24B46EBF76E9F6648E8E7068E3B')
def test_empty_entry(self): entry = create_empty_entry(127) self.assertEqual(entry['entry-number'], 127) self.assertIsNone(entry['item-hash'])
def republish_entry(entry_number, routing_key): app.logger.info("Republishing entry '%s'", entry_number) cursor = start() try: max_entry = count_entries(cursor) if entry_number > max_entry: app.logger.warning( "Entry number '%s' is greater than maximum entry '%s'", entry_number, max_entry) return False cursor.execute( 'SELECT e.entry_number, e.entry_timestamp, e.item_hash, e.key, i.item, e.item_signature ' 'FROM entry e ' 'JOIN item i on e.item_hash = i.item_hash ' 'WHERE entry_number=%(entry_number)s LIMIT 1', {'entry_number': entry_number}) entry_row = cursor.fetchone() prev_item = None if not entry_row: app.logger.info("No entry found for '%s', using empty entry", entry_number) entry = create_empty_entry(entry_number) else: entry = { "entry-number": entry_number, "entry-timestamp": entry_row['entry_timestamp'].strftime('%Y-%m-%d %H:%M:%S.%f'), "item-hash": entry_row['item_hash'], "key": entry_row['key'], "item-signature": entry_row['item_signature'], "item": entry_row['item'] } cursor.execute( 'SELECT e.entry_number, i.item ' 'FROM entry e ' 'JOIN item i on e.item_hash = i.item_hash ' 'WHERE e.key=%(key)s AND entry_number < %(entry_number)s ' 'ORDER BY entry_number DESC LIMIT 1', { 'key': entry['key'], 'entry_number': entry_number }) prev_entry_row = cursor.fetchone() if prev_entry_row: prev_item = prev_entry_row['item'] action_type = get_action_type(prev_item) message = entry message['action-type'] = action_type if action_type == 'UPDATED': message['item-changes'] = get_item_changes(entry['item'], prev_item) app.logger.info( "Created republish for entry '%s' with changes from previous entry '%s'", entry_number, prev_entry_row['entry_number']) else: app.logger.info("Created republish for entry '%s''", entry_number) app.logger.info( "Sending republish message to exchange '%s' with routing key '%s'", config.EXCHANGE_NAME, routing_key) app.logger.debug("Sending message '%s''", message) publish_message(message, config.RABBIT_URL, config.EXCHANGE_NAME, routing_key, queue_name=None, exchange_type=config.EXCHANGE_TYPE, serializer="json", headers=None) app.audit_logger.info("Entry '%s' republished to routing key '%s'", entry_number, routing_key) return True finally: commit(cursor)