Пример #1
0
  def _Dynamic_Get(self, get_request, get_response):
    txid = None
    if get_request.has_transaction():
      txid = get_request.transaction().handle()
      txdata = self.__transactions[txid]
      assert (txdata.thread_id ==
          thread.get_ident()), "Transactions are single-threaded."

      keys = [(k, k.Encode()) for k in get_request.key_list()]

      new_request = datastore_pb.GetRequest()
      for key, enckey in keys:
        if enckey not in txdata.entities:
          new_request.add_key().CopyFrom(key)
    else:
      new_request = get_request

    if new_request.key_size() > 0:
      super(RemoteDatastoreStub, self).MakeSyncCall(
          'datastore_v3', 'Get', new_request, get_response)

    if txid is not None:
      newkeys = new_request.key_list()
      entities = get_response.entity_list()
      for key, entity in zip(newkeys, entities):
        entity_hash = None
        if entity.has_entity():
          entity_hash = sha.new(entity.entity().Encode()).digest()
        txdata.preconditions[key.Encode()] = (key, entity_hash)

      new_response = datastore_pb.GetResponse()
      it = iter(get_response.entity_list())
      for key, enckey in keys:
        if enckey in txdata.entities:
          cached_entity = txdata.entities[enckey][1]
          if cached_entity:
            new_response.add_entity().mutable_entity().CopyFrom(cached_entity)
          else:
            new_response.add_entity()
        else:
          new_entity = it.next()
          if new_entity.has_entity():
            assert new_entity.entity().key() == key
            new_response.add_entity().CopyFrom(new_entity)
          else:
            new_response.add_entity()
      get_response.CopyFrom(new_response)
Пример #2
0
    def _Dynamic_TransactionQuery(self, request, response):
        if not request.has_ancestor():
            raise apiproxy_errors.ApplicationError(
                datastore_pb.Error.BAD_REQUEST,
                'No ancestor in transactional query.')

        app_id = datastore_types.ResolveAppId(None)
        if (datastore_rpc._GetDatastoreType(app_id) !=
                datastore_rpc.BaseConnection.HIGH_REPLICATION_DATASTORE):
            raise apiproxy_errors.ApplicationError(
                datastore_pb.Error.BAD_REQUEST,
                'remote_api supports transactional queries only in the '
                'high-replication datastore.')

        entity_group_key = entity_pb.Reference()
        entity_group_key.CopyFrom(request.ancestor())
        group_path = entity_group_key.mutable_path()
        root = entity_pb.Path_Element()
        root.MergeFrom(group_path.element(0))
        group_path.clear_element()
        group_path.add_element().CopyFrom(root)
        eg_element = group_path.add_element()
        eg_element.set_type(metadata.EntityGroup.KIND_NAME)
        eg_element.set_id(metadata.EntityGroup.ID)

        begin_request = datastore_pb.BeginTransactionRequest()
        begin_request.set_app(app_id)
        tx = datastore_pb.Transaction()
        self.__call('datastore_v3', 'BeginTransaction', begin_request, tx)

        request.mutable_transaction().CopyFrom(tx)
        self.__call('datastore_v3', 'RunQuery', request,
                    response.mutable_result())

        get_request = datastore_pb.GetRequest()
        get_request.mutable_transaction().CopyFrom(tx)
        get_request.add_key().CopyFrom(entity_group_key)
        get_response = datastore_pb.GetResponse()
        self.__call('datastore_v3', 'Get', get_request, get_response)
        entity_group = get_response.entity(0)

        response.mutable_entity_group_key().CopyFrom(entity_group_key)
        if entity_group.has_entity():
            response.mutable_entity_group().CopyFrom(entity_group.entity())

        self.__call('datastore_v3', 'Commit', tx,
                    datastore_pb.CommitResponse())
Пример #3
0
    def get(self, key, txid=None):
        request = datastore_pb.GetRequest()
        req_key = request.add_key()
        req_key.MergeFrom(key._ToPb())

        if txid is not None:
            req_tx = request.mutable_transaction()
            req_tx.set_app(self.project_id)
            req_tx.set_handle(txid)

        encoded_response = yield self._make_request('Get', request.Encode())
        get_response = datastore_pb.GetResponse(encoded_response)
        response_entity = get_response.entity(0).entity()
        if not response_entity.has_key():
            return

        raise gen.Return(Entity.FromPb(response_entity))
    def test_kindless_query(self):
        query = datastore_pb.Query()
        ancestor = query.mutable_ancestor()
        entity_proto1 = self.get_new_entity_proto("test",
                                                  "test_kind",
                                                  "nancy",
                                                  "prop1name",
                                                  "prop1val",
                                                  ns="blah")
        entity_key = entity_proto1.key()
        get_req = datastore_pb.GetRequest()
        key = get_req.add_key()
        key.MergeFrom(entity_key)

        tombstone1 = {
            'key': {
                APP_ENTITY_SCHEMA[0]: TOMBSTONE,
                APP_ENTITY_SCHEMA[1]: 1
            }
        }
        db_batch = flexmock()
        db_batch.should_receive("batch_get_entity").and_return({
            "test\x00blah\x00test_kind:nancy\x01": {
                APP_ENTITY_SCHEMA[0]: entity_proto1.Encode(),
                APP_ENTITY_SCHEMA[1]: 1
            }
        })

        db_batch.should_receive("batch_put_entity").and_return(None)
        entity_proto1 = {
            'test\x00blah\x00test_kind:nancy\x01': {
                APP_ENTITY_SCHEMA[0]: entity_proto1.Encode(),
                APP_ENTITY_SCHEMA[1]: 1
            }
        }
        db_batch.should_receive("range_query").and_return(
            [entity_proto1, tombstone1]).and_return([])
        zookeeper = flexmock()
        zookeeper.should_receive("get_valid_transaction_id").and_return(1)
        zookeeper.should_receive("is_in_transaction").and_return(False)
        zookeeper.should_receive("acquire_lock").and_return(True)
        dd = DatastoreDistributed(db_batch, zookeeper)
        filter_info = {'__key__': [[0, 0]]}
        dd.kindless_query(query, filter_info, None)
Пример #5
0
def _get_entity_by_key(ds_access, entity_key):
  """ Fetches an entity.

  Args:
    ds_access: A DatastoreDistributed client.
    entity_key: A datastore.Key object.
  Returns:
    A datastore.Entity object.
  Raises:
    ApplicationError if unable to fetch entity.
  """
  reference = entity_key._ToPb()
  request = datastore_pb.GetRequest()
  key = request.add_key()
  key.CopyFrom(reference)

  response = datastore_pb.GetResponse()
  ds_access._Dynamic_Get(request, response)
  entity = datastore.Entity.FromPb(response.entity(0).entity())
  return entity
Пример #6
0
  def test_dynamic_get(self):
    entity_proto1 = self.get_new_entity_proto(
      "test", "test_kind", "nancy", "prop1name", "prop2val", ns="blah")

    zk_client = flexmock()
    zk_client.should_receive('add_listener')

    async_result = gen.Future()
    async_result.set_result({
      "test\x00blah\x00test_kind:nancy\x01": {
        APP_ENTITY_SCHEMA[0]: entity_proto1.Encode(),
        APP_ENTITY_SCHEMA[1]: 1
      }
    })

    zookeeper = flexmock(handle=zk_client)
    zookeeper.should_receive("get_valid_transaction_id").and_return(1)
    zookeeper.should_receive("acquire_lock").and_return(True)
    db_batch = flexmock()
    db_batch.should_receive('valid_data_version_sync').and_return(True)
    db_batch.should_receive("batch_get_entity").and_return(async_result)
    db_batch.should_receive('record_reads').and_return(ASYNC_NONE)

    transaction_manager = flexmock()
    dd = DatastoreDistributed(db_batch, transaction_manager, zookeeper)

    entity_key = entity_proto1.key()
    get_req = datastore_pb.GetRequest()
    key = get_req.add_key()
    key.MergeFrom(entity_key)
    get_resp = datastore_pb.GetResponse()

    yield dd.dynamic_get("test", get_req, get_resp)
    self.assertEquals(get_resp.entity_size(), 1)

    # Now test while in a transaction
    get_resp = datastore_pb.GetResponse()
    get_req.mutable_transaction().set_handle(1)
    yield dd.dynamic_get("test", get_req, get_resp)
    self.assertEquals(get_resp.entity_size(), 1)
Пример #7
0
    def __insert_v3_entity(self, v3_entity, v3_txn):
        """Inserts a v3 entity.

    Args:
      v3_entity: an entity_pb.EntityProto
      v3_txn: a datastore_pb.Transaction or None

    Returns:
      a tuple (the number of index writes that occurred,
               the entity key)

    Raises:
      ApplicationError: if the entity already exists
    """
        if not v3_txn:

            v3_txn = datastore_pb.Transaction()
            v3_begin_txn_req = datastore_pb.BeginTransactionRequest()
            v3_begin_txn_req.set_app(v3_entity.key().app())
            self.__make_v3_call('BeginTransaction', v3_begin_txn_req, v3_txn)
            _, key = self.__insert_v3_entity(v3_entity, v3_txn)
            v3_resp = datastore_pb.CommitResponse()
            self.__make_v3_call('Commit', v3_txn, v3_resp)
            return (v3_resp.cost().index_writes(), key)

        if datastore_pbs.is_complete_v3_key(v3_entity.key()):
            v3_get_req = datastore_pb.GetRequest()
            v3_get_req.mutable_transaction().CopyFrom(v3_txn)
            v3_get_req.key_list().append(v3_entity.key())
            v3_get_resp = datastore_pb.GetResponse()
            self.__make_v3_call('Get', v3_get_req, v3_get_resp)
            if v3_get_resp.entity(0).has_entity():
                raise apiproxy_errors.ApplicationError(
                    datastore_pb.Error.BAD_REQUEST, 'Entity already exists.')
        v3_put_req = datastore_pb.PutRequest()
        v3_put_req.mutable_transaction().CopyFrom(v3_txn)
        v3_put_req.entity_list().append(v3_entity)
        v3_put_resp = datastore_pb.PutResponse()
        self.__make_v3_call('Put', v3_put_req, v3_put_resp)
        return (v3_put_resp.cost().index_writes(), v3_put_resp.key(0))
    def __update_v3_entity(self, v3_entity, v3_txn):
        """Updates a v3 entity.

    Args:
      v3_entity: a datastore_v4_pb.Entity
      v3_txn: a datastore_pb.Transaction or None

    Returns:
      the number of index writes that occurred

    Raises:
      ApplicationError: if the entity does not exist
    """
        if not v3_txn:

            v3_txn = datastore_pb.Transaction()
            v3_begin_txn_req = datastore_pb.BeginTransactionRequest()
            v3_begin_txn_req.set_app(v3_entity.key().app())
            self.__make_v3_call('BeginTransaction', v3_begin_txn_req, v3_txn)
            self.__update_v3_entity(v3_entity, v3_txn)
            v3_resp = datastore_pb.CommitResponse()
            self.__make_v3_call('Commit', v3_txn, v3_resp)
            return v3_resp.cost().index_writes()

        v3_get_req = datastore_pb.GetRequest()
        v3_get_req.mutable_transaction().CopyFrom(v3_txn)
        v3_get_req.key_list().append(v3_entity.key())
        v3_get_resp = datastore_pb.GetResponse()
        self.__make_v3_call('Get', v3_get_req, v3_get_resp)
        if not v3_get_resp.entity(0).has_entity():
            raise apiproxy_errors.ApplicationError(
                datastore_v4_pb.Error.BAD_REQUEST, 'Entity does not exist.')
        v3_put_req = datastore_pb.PutRequest()
        v3_put_req.mutable_transaction().CopyFrom(v3_txn)
        v3_put_req.entity_list().append(v3_entity)
        v3_put_resp = datastore_pb.PutResponse()
        self.__make_v3_call('Put', v3_put_req, v3_put_resp)
        return v3_put_resp.cost().index_writes()
Пример #9
0
  def get_request(self, app_id, http_request_data):
    """ High level function for doing gets.

    Args:
      app_id: Name of the application.
      http_request_data: Stores the protocol buffer request from the AppServer.
    Returns:
      An encoded get response.
    """ 
    global datastore_access
    getreq_pb = datastore_pb.GetRequest(http_request_data)
    getresp_pb = datastore_pb.GetResponse()
    try:
      datastore_access.dynamic_get(app_id, getreq_pb, getresp_pb)
    except zktransaction.ZKBadRequest as zkie:
      logger.exception('Illegal argument during {}'.format(getreq_pb))
      return (getresp_pb.Encode(),
              datastore_pb.Error.BAD_REQUEST, 
              "Illegal arguments for transaction. {0}".format(str(zkie)))
    except zktransaction.ZKInternalException:
      logger.exception('ZKInternalException during {}'.format(getreq_pb))
      return (getresp_pb.Encode(),
              datastore_pb.Error.INTERNAL_ERROR, 
              "Internal error with ZooKeeper connection.")
    except zktransaction.ZKTransactionException:
      logger.exception('Concurrent transaction during {}'.
        format(getreq_pb))
      return (getresp_pb.Encode(),
              datastore_pb.Error.CONCURRENT_TRANSACTION, 
              "Concurrent transaction exception on get.")
    except dbconstants.AppScaleDBConnectionError:
      logger.exception('DB connection error during {}'.format(getreq_pb))
      return (getresp_pb.Encode(),
              datastore_pb.Error.INTERNAL_ERROR,
              "Datastore connection error on get.")

    return (getresp_pb.Encode(), 0, "")
Пример #10
0
    def test_dynamic_get(self):
        entity_proto1 = self.get_new_entity_proto("test",
                                                  "test_kind",
                                                  "nancy",
                                                  "prop1name",
                                                  "prop2val",
                                                  ns="blah")
        zookeeper = flexmock()
        zookeeper.should_receive("get_valid_transaction_id").and_return(1)
        zookeeper.should_receive("register_updated_key").and_return(1)
        zookeeper.should_receive("acquire_lock").and_return(True)
        db_batch = flexmock()
        db_batch.should_receive("batch_put_entity").and_return(None)
        db_batch.should_receive("batch_get_entity").and_return({
            "test/blah/test_kind:nancy!": {
                APP_ENTITY_SCHEMA[0]: entity_proto1.Encode(),
                APP_ENTITY_SCHEMA[1]: 1
            }
        })

        dd = DatastoreDistributed(db_batch, zookeeper)

        entity_key = entity_proto1.key()
        get_req = datastore_pb.GetRequest()
        key = get_req.add_key()
        key.MergeFrom(entity_key)
        get_resp = datastore_pb.GetResponse()

        dd.dynamic_get("test", get_req, get_resp)
        self.assertEquals(get_resp.entity_size(), 1)

        # Now test while in a transaction
        get_resp = datastore_pb.GetResponse()
        get_req.mutable_transaction().set_handle(1)
        dd.dynamic_get("test", get_req, get_resp)
        self.assertEquals(get_resp.entity_size(), 1)
Пример #11
0
    def get(self, url_key=None):
        """
        function get, mapped to url: /get/$url_key/
        params:
            @url_key: string to be converted to datastore key
        """
        if url_key is None:
            return "{}"
        else:
            key = datastore_types.Key.from_path(DBNAME, url_key)
            #try:
            req = datastore_pb.GetRequest()
            req.key_list().append(key._ToPb())
            rpc = datastore.DatastoreRPC('datastore_v3')
            resp = HttpDbResponse()
            rpc.make_call('Get', req, resp)

            import simplejson

            rpc.wait()
            rpc.check_success()
            e = resp.entity_list()

            return [simplejson.dumps(x.__json__()) for x in e]
  def __get_v1_entity_version(self, v1_key, v1_txn):
    """Returns the version of an entity, or _NO_VERSION if it does not exist.

    Args:
      v1_key: the key of the entity to lookup.
      v1_txn: the transaction to use when retrieving the entity.

    Returns:
      the version number of the entity if it was found, or _NO_VERSION
      otherwise.
    """
    v3_key = entity_pb.Reference()
    self.__entity_converter.v1_to_v3_reference(v1_key, v3_key)
    v3_txn = datastore_pb.Transaction()
    self.__service_converter.v1_to_v3_txn(v1_txn, v3_txn)

    v3_get_req = datastore_pb.GetRequest()
    v3_get_req.mutable_transaction().CopyFrom(v3_txn)
    v3_get_req.key_list().append(v3_key)
    v3_get_resp = datastore_pb.GetResponse()
    self.__make_v3_call('Get', v3_get_req, v3_get_resp)
    if v3_get_resp.entity(0).has_entity():
      return v3_get_resp.entity(0).version()
    return _NO_VERSION