Ejemplo n.º 1
0
  def process_tombstone(self, key, entity, version):
    """ Processes any entities which have been soft deleted.
        Does an actual delete to reclaim disk space.

    Args:
      key: The key to the entity table.
      entity: The entity in string serialized form.
      version: The version of the entity in the datastore.
    Returns:
      True if a hard delete occurred, False otherwise.
    """
    success = False
    app_prefix = entity_utils.get_prefix_from_entity_key(key)
    root_key = entity_utils.get_root_key_from_entity_key(key)

    try:
      if self.zoo_keeper.is_blacklisted(app_prefix, version):
        logging.error("Found a blacklisted item for version {0} on key {1}".\
          format(version, key))
        return True
        #TODO actually fix the badlisted entity
        return self.fix_badlisted_entity(key, version)
    except zk.ZKTransactionException, zk_exception:
      logging.error("Caught exception {0}.\nBacking off!".format(zk_exception))
      time.sleep(self.DB_ERROR_PERIOD)
      return False
Ejemplo n.º 2
0
    def process_tombstone(self, key, entity, version):
        """ Processes any entities which have been soft deleted.
        Does an actual delete to reclaim disk space.

    Args:
      key: The key to the entity table.
      entity: The entity in string serialized form.
      version: The version of the entity in the datastore.
    Returns:
      True if a hard delete occurred, False otherwise.
    """
        success = False
        app_prefix = entity_utils.get_prefix_from_entity_key(key)
        root_key = entity_utils.get_root_key_from_entity_key(key)

        try:
            if self.zoo_keeper.is_blacklisted(app_prefix, version):
                logging.error("Found a blacklisted item for version {0} on key {1}".\
                  format(version, key))
                return True
                #TODO actually fix the badlisted entity
                return self.fix_badlisted_entity(key, version)
        except zk.ZKTransactionException, zk_exception:
            logging.error(
                "Caught exception {0}.\nBacking off!".format(zk_exception))
            time.sleep(self.DB_ERROR_PERIOD)
            return False
Ejemplo n.º 3
0
  def process_entity(self, entity):
    """ Verifies entity, fetches from journal if necessary and calls
    dump_entity.

    Args:
      entity: The entity to be backed up.
    Returns:
      True on success, False otherwise.
    """
    key = entity.keys()[0]
    kind = entity_utils.get_kind_from_entity_key(key)
    # Skip protected and private entities.
    if re.match(self.PROTECTED_KINDS, kind) or\
        re.match(self.PRIVATE_KINDS, kind):
      # Do not skip blob entities.
      if not re.match(self.BLOB_CHUNK_REGEX, kind) and\
          not re.match(self.BLOB_INFO_REGEX, kind):
        logging.debug("Skipping key: {0}".format(key))
        return False

    one_entity = entity[key][dbconstants.APP_ENTITY_SCHEMA[0]]
    if one_entity == datastore_server.TOMBSTONE:
      return False
    app_prefix = entity_utils.get_prefix_from_entity_key(key)
    root_key = entity_utils.get_root_key_from_entity_key(key)

    success = True
    while True:
      # Acquire lock.
      txn_id = self.zoo_keeper.get_transaction_id(app_prefix)
      try:
        if self.zoo_keeper.acquire_lock(app_prefix, txn_id, root_key):
          version = entity[key][dbconstants.APP_ENTITY_SCHEMA[1]]
          if not self.verify_entity(key, version):
            # Fetch from the journal.
            entity = entity_utils.fetch_journal_entry(self.db_access, key)
            if not entity:
              logging.error("Bad journal entry for key: {0} and result: {1}".
                format(key, entity))
              success = False
            else:
              one_entity = entity[key][dbconstants.APP_ENTITY_SCHEMA[0]]

          if self.dump_entity(one_entity):
            logging.debug("Backed up key: {0}".format(key))
            success = True
          else:
            success = False
        else:
          logging.warn("Entity with key: {0} not found".format(key))
          success = False
      except zk.ZKTransactionException, zk_exception:
        logging.error("Zookeeper exception {0} while requesting entity lock".
          format(zk_exception))
        success = False
      except zk.ZKInternalException, zk_exception:
        logging.error("Zookeeper exception {0} while requesting entity lock".
          format(zk_exception))
        success = False
Ejemplo n.º 4
0
  def fix_badlisted_entity(self, key, version):
    """ Places the correct entity given the current one is from a blacklisted
    transaction.

    Args:
      key: The key to the entity table.
      version: The bad version of the entity.
    Returns:
      True on success, False otherwise.
    """
    app_prefix = entity_utils.get_prefix_from_entity_key(key)
    root_key = entity_utils.get_root_key_from_entity_key(key)
    # TODO watch out for the race condition of doing a GET then a PUT.

    try:
      txn_id = self.zoo_keeper.get_transaction_id(app_prefix)
      if self.zoo_keeper.acquire_lock(app_prefix, txn_id, root_key):
        valid_id = self.zoo_keeper.get_valid_transaction_id(app_prefix,
          version, key)
        # Insert the entity along with regular indexes and composites.
        ds_distributed = self.register_db_accessor(app_prefix)
        bad_key = datastore_server.DatastoreDistributed.get_journal_key(key,
          version)
        good_key = datastore_server.DatastoreDistributed.get_journal_key(key,
          valid_id)

        # Fetch the journal and replace the bad entity.
        good_entry = entity_utils.fetch_journal_entry(self.db_access, good_key)
        bad_entry = entity_utils.fetch_journal_entry(self.db_access, bad_key)

        # Get the kind to lookup composite indexes.
        kind = None
        if good_entry:
          kind = datastore_server.DatastoreDistributed.get_entity_kind(
            good_entry.key())
        elif bad_entry:
          kind = datastore_server.DatastoreDistributed.get_entity_kind(
            bad_entry.key())

        # Fetch latest composites for this entity
        composites = self.get_composite_indexes(app_prefix, kind)

        # Remove previous regular indexes and composites if it's not a
        # TOMBSTONE.
        if bad_entry:
          self.delete_indexes(bad_entry)
          self.delete_composite_indexes(bad_entry, composites)

        # Overwrite the entity table with the correct version.
        # Insert into entity table, regular indexes, and composites.
        if good_entry:
          # TODO
          #self.db_access.batch_put_entities(...)
          #self.insert_indexes(good_entry)
          #self.insert_composite_indexes(good_entry, composites)
          pass
        else:
          # TODO
          #self.db_access.batch_delete_entities(...)
          pass
        del ds_distributed
      else:
        success = False
    except zk.ZKTransactionException, zk_exception:
      logging.error("Caught exception {0}".format(zk_exception))
      success = False
Ejemplo n.º 5
0
    def fix_badlisted_entity(self, key, version):
        """ Places the correct entity given the current one is from a blacklisted
    transaction.

    Args:
      key: The key to the entity table.
      version: The bad version of the entity.
    Returns:
      True on success, False otherwise.
    """
        app_prefix = entity_utils.get_prefix_from_entity_key(key)
        root_key = entity_utils.get_root_key_from_entity_key(key)
        # TODO watch out for the race condition of doing a GET then a PUT.

        try:
            txn_id = self.zoo_keeper.get_transaction_id(app_prefix)
            if self.zoo_keeper.acquire_lock(app_prefix, txn_id, root_key):
                valid_id = self.zoo_keeper.get_valid_transaction_id(
                    app_prefix, version, key)
                # Insert the entity along with regular indexes and composites.
                ds_distributed = self.register_db_accessor(app_prefix)
                bad_key = datastore_server.DatastoreDistributed.get_journal_key(
                    key, version)
                good_key = datastore_server.DatastoreDistributed.get_journal_key(
                    key, valid_id)

                # Fetch the journal and replace the bad entity.
                good_entry = entity_utils.fetch_journal_entry(
                    self.db_access, good_key)
                bad_entry = entity_utils.fetch_journal_entry(
                    self.db_access, bad_key)

                # Get the kind to lookup composite indexes.
                kind = None
                if good_entry:
                    kind = datastore_server.DatastoreDistributed.get_entity_kind(
                        good_entry.key())
                elif bad_entry:
                    kind = datastore_server.DatastoreDistributed.get_entity_kind(
                        bad_entry.key())

                # Fetch latest composites for this entity
                composites = self.get_composite_indexes(app_prefix, kind)

                # Remove previous regular indexes and composites if it's not a
                # TOMBSTONE.
                if bad_entry:
                    self.delete_indexes(bad_entry)
                    self.delete_composite_indexes(bad_entry, composites)

                # Overwrite the entity table with the correct version.
                # Insert into entity table, regular indexes, and composites.
                if good_entry:
                    # TODO
                    #self.db_access.batch_put_entities(...)
                    #self.insert_indexes(good_entry)
                    #self.insert_composite_indexes(good_entry, composites)
                    pass
                else:
                    # TODO
                    #self.db_access.batch_delete_entities(...)
                    pass
                del ds_distributed
            else:
                success = False
        except zk.ZKTransactionException, zk_exception:
            logging.error("Caught exception {0}".format(zk_exception))
            success = False
Ejemplo n.º 6
0
    def test_get_root_key_from_entity_key(self):
        self.assertEquals("hi/bye\x01", entity_utils.get_root_key_from_entity_key("hi/bye\x01otherstuff\x01moar"))

        self.assertEquals("hi/\x01", entity_utils.get_root_key_from_entity_key("hi/\x01otherstuff\x01moar"))