示例#1
0
  /**
   * Selects multiple keys at once. This method always
   * works asynchronously.
   *
   * @param[in] keys vector of keys to select
   * @return true if all keys are found
   */
  bool mget(std::vector<std::string> &keys)
  {
    std::vector<const char *> real_keys;
    std::vector<size_t> key_len;
    /*
     * Construct an array which will contain the length
     * of each of the strings in the input vector. Also, to
     * interface with the memcached C API, we need to convert
     * the vector of std::string's to a vector of char *.
     */
    real_keys.reserve(keys.size());
    key_len.reserve(keys.size());

    std::vector<std::string>::iterator it= keys.begin();

    while (it != keys.end())
    {
      real_keys.push_back(const_cast<char *>((*it).c_str()));
      key_len.push_back((*it).length());
      ++it;
    }

    /*
     * If the std::vector of keys is empty then we cannot 
     * call memcached_mget as we will get undefined behavior.
     */
    if (! real_keys.empty())
    {
      memcached_return rc= memcached_mget(&memc, &real_keys[0], &key_len[0], 
                                          real_keys.size());
      return (rc == MEMCACHED_SUCCESS);
    }

    return false;
  }
示例#2
0
static int cdb_readv(knot_db_t *db, knot_db_val_t *key, knot_db_val_t *val, int maxcount)
{
	if (!db || !key || !val) {
		return kr_error(EINVAL);
	}

	struct memcached_cli *cli = db;

	/* Convert to libmemcached query format */
	assert(maxcount < 1000); /* Sane upper bound */
	const char *keys [maxcount];
	size_t lengths [maxcount];
	for (int i = 0; i < maxcount; ++i) {
		keys[i] = key[i].data;
		lengths[i] = key[i].len;
	}

	/* Execute multiple get and retrieve results */
	memcached_return_t status = memcached_mget(cli->handle, keys, lengths, maxcount);
	memcached_result_free(&cli->res);
	memcached_result_create(cli->handle, &cli->res);
	for (int i = 0; i < maxcount; ++i) {
		memcached_result_st *res = memcached_fetch_result(cli->handle, &cli->res, &status);
		if (!res) { /* Less results than expected */
			return kr_error(ENOENT);
		}
		val[i].len = memcached_result_length(res);
		val[i].data = (void *)memcached_result_value(res);
	}
	return 0;
}
示例#3
0
/**
 * @function memcached.mget
 * 
 * ### Synopsis:
 * 
 * var o = memcache.get(handle, array_of_keys);
 * 
 * Get multiple values, identified by an array of keys, from memcached.
 * 
 * The returned object is a hash of returned values, indexed by the key.  
 * 
 * For each of these keys, the value is an object in the form described at the top of this page.
 * 
 * @param {object} handle - handle to memcached connection.
 * @param {array} keys - array of keys of data to get from memcached
 * @return {object} o - has of objects of the form described at top of the page, or false if an error occurred.
 */
JSVAL _memcached_mget (JSARGS args) {
    HandleScope scope;
    M* handle = HANDLE(args[0]);
    Handle<Array> aKeys = Handle<Array>::Cast(args[1]);
    int numKeys = aKeys->Length();
    char *keys[numKeys];
    size_t key_lengths[numKeys];
    for (int i = 0; i < numKeys; i++) {
        String::Utf8Value k(aKeys->Get(i));
        keys[i] = *k;
        key_lengths[i] = strlen(keys[i]);
    }
    R rc = memcached_mget(handle, keys, key_lengths, numKeys);
    if (rc != MEMCACHED_SUCCESS) {
        return String::New(memcached_strerror(handle, rc));
    }
    char return_key[MEMCACHED_MAX_KEY];
    size_t return_key_length;
    char *return_value;
    size_t return_value_length;
    uint32_t flags;
    JSOBJ result = Object::New();
    while ((return_value = memcached_fetch(handle, return_key, &return_key_length, &return_value_length, &flags, &rc))) {
        JSOBJ o = Object::New();
        o->Set(String::New("value"), String::New(return_value));
        o->Set(String::New("flags"), Integer::New(flags));
        o->Set(String::New("rc"), Integer::New(rc));
        free(return_value);
        result->Set(String::New(return_key), o);
    }
    return scope.Close(result);
}
示例#4
0
文件: ssMemcached.cpp 项目: gityf/db
int ssMemcached::multiget(char *sKeySet[], size_t *nKeySetLen,
    int nKeySetNum, char *pReturnData[],
    char *pKeySet[], const int nValueLen) {
    char return_key[MEMCACHED_MAX_KEY];
    size_t return_key_length;
    char *return_value;
    size_t return_value_length;
    uint32_t flags;
    int index = 0;
    memset(return_key, 0, sizeof(return_key));
    retCode_ = memcached_mget(memc_, sKeySet, nKeySetLen, nKeySetNum);
    if (retCode_ == MEMCACHED_SUCCESS) {
        int i = 0;
        return_value = memcached_fetch(memc_, return_key,
            &return_key_length, &return_value_length, &flags, &retCode_);
        while (return_value != NULL) {
            if (retCode_ == MEMCACHED_SUCCESS) {
                for (i = 0; i < nKeySetNum; i++) {
                    index = index % nKeySetNum;
                    if (strcmp(sKeySet[index], return_key) == 0) {
                        break;
                    }
                    else {
                        index = (index + 1) % nKeySetNum;
                    }
                }
                if (i < nKeySetNum) {
                    if (return_value_length >= nValueLen) {
                        strncpy(pReturnData[index], return_value, nValueLen - 1);
                    }
                    else {
                        strncpy(pReturnData[index], return_value, return_value_length);
                    }
                    if (return_key_length >= CACHEKEYLEN) {
                        strncpy(pKeySet[index], return_key, CACHEKEYLEN - 1);
                    }
                    else {
                        strncpy(pKeySet[index], return_key, return_key_length);
                    }
                    memset(return_key, 0, sizeof(return_key));
                    index++;
                    free(return_value);
                }
                else {
                    return 0;
                }
            }
            else {
                return 0;
            }
        }
    }
    else {
        return 0;
    }
    return 1;
}
示例#5
0
文件: IoMemcached.c 项目: ADTSH/io
/*doc Memcached getMulti(keys)
Asks memcached to retrieve data corresponding to the list of keys.
Returns a Map with the results.
If some of the keys appearing in a retrieval request are not sent back
by the server in the item list this means that the server does not
hold items with such keys
*/
IoObject *IoMemcached_getMulti(IoMemcached *self, IoObject *locals, IoMessage *m)
{
	IoList *keys_list = IoMessage_locals_listArgAt_(m, locals, 0);
	size_t keys_list_size = IoList_rawSize(keys_list);

	IoObject *results_map = IoMap_new(IOSTATE);

	if(keys_list_size == 0)
		return results_map;

	int i;
	for(i = 0; i < keys_list_size; i++) {
		IoSeq *key = IoList_rawAt_(keys_list, i);
		IOASSERT(ISSEQ(key), "key must be a Sequence");
		IOASSERT(IOSEQ_LENGTH(key) > 0, "key cannot be an empty Sequence");
		IOASSERT(IOSEQ_LENGTH(key) < MEMCACHED_MAX_KEY, "key is too long");
	}

	const char **ckeys = (const char **) malloc(sizeof(const char *) * keys_list_size);
	size_t *ckey_lengths = (size_t *) malloc(sizeof(size_t) * keys_list_size);

	for(i = 0; i < keys_list_size; i++) {
		ckeys[i] = CSTRING(IoList_rawAt_(keys_list, i));
		ckey_lengths[i] = strlen(ckeys[i]);
	}

	memcached_return_t rc = memcached_mget(DATA(self)->mc, ckeys, ckey_lengths, keys_list_size);

	free(ckeys);
	free(ckey_lengths);

	char returned_key[MEMCACHED_MAX_KEY], *returned_value;
	size_t returned_key_length, returned_value_length;
	uint32_t flags;

	returned_value = memcached_fetch(DATA(self)->mc,
		returned_key, &returned_key_length,
		&returned_value_length, &flags, &rc
	);

	while(returned_value != NULL) {
		IoMap_rawAtPut(results_map,
			IoSeq_newSymbolWithData_length_(IOSTATE, returned_key, returned_key_length),
			IoMemcached_deserialize(self, returned_value, returned_value_length, flags)
		);

		free(returned_value);

		returned_value = memcached_fetch(DATA(self)->mc,
			returned_key, &returned_key_length,
			&returned_value_length, &flags, &rc
		);
	}

	return results_map;
}
示例#6
0
void
test_memcached_cas(void)
{
  memcached_return rc;

  const char *key = "caskey";
  size_t key_len = strlen(key);
  const char* keys[2] = { (char *)key, NULL };
  size_t key_lens[2] = { key_len, 0 };

  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
  grn_test_memcached_assert(
    memcached_set(memc, key, key_len, "cas test", 8, 0, 0xdeadbeefU),
    cut_message("memcached set failed."));

  {
    uint64_t cas;
    memcached_result_st *results;
    memcached_result_st results_obj;

    results = memcached_result_create(memc, &results_obj);
    grn_test_memcached_assert(
      memcached_mget(memc, keys, key_lens, 1),
      cut_message("memcached mget failed."));
    results = memcached_fetch_result(memc, &results_obj, &rc);
    cut_assert_not_null(results,
                        cut_message("memcached fetch result failed."));

    cas = memcached_result_cas(results);
    cut_assert_operator(cas, !=, 0,
                        cut_message("memcached cas value is non-zero."));

    grn_test_memcached_assert(
      memcached_cas(memc, key, key_len, "cas changed", 12, 0, 0, cas),
      cut_message("memcached cas failed."));

    grn_test_memcached_assert_equal_rc(
      MEMCACHED_NOTSTORED,
      memcached_cas(memc, key, key_len, "cas changed", 12, 0, 0, cas),
      cut_message("memcached cas value is same."));

    memcached_result_free(&results_obj);
  }
}
示例#7
0
static bool kv_mget(kv_data* c, libkv_mget_data* mx,
		char** keys, size_t* keylens, size_t num)
{
	kv_mget_data* m = malloc(sizeof(kv_mget_data));
	if(m == NULL) {
		return NULL;
	}
	if(memcached_mget(c->st, keys, keylens, num)
			!= MEMCACHED_SUCCESS) {
		free(m);
		return false;
	}
	m->c = c;
	m->lastbuf = NULL;
	mx->kv_mget_next  = (void*)&kv_mget_next;
	mx->kv_mget_free  = (void*)&kv_mget_free;
	mx->data = (void*)m;
	return true;
}
示例#8
0
void
test_memcached_cas(void)
{
  memcached_return rc;

  const char *key = "caskey";
  size_t key_len = strlen(key);
  char* keys[2] = { (char *)key, NULL };
  size_t key_lens[2] = { key_len, 0 };

  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
  rc = memcached_set(memc, key, key_len, "cas test", 8, 0, 0xdeadbeefU);
  cut_set_message("memcached set failed.");
  cut_assert_equal_int(MEMCACHED_SUCCESS, rc);

  {
    uint64_t cas;
    memcached_result_st *results;
    memcached_result_st results_obj;

    results = memcached_result_create(memc, &results_obj);
    rc = memcached_mget(memc, keys, key_lens, 1);
    cut_set_message("memcached mget failed.");
    cut_assert_equal_int(MEMCACHED_SUCCESS, rc);
    results = memcached_fetch_result(memc, &results_obj, &rc);

    cas = memcached_result_cas(results);
    cut_set_message("memcached cas value is non-zero.");
    cut_assert_operator_int(cas, !=, 0);

    rc = memcached_cas(memc, key, key_len, "cas changed", 12, 0, 0, cas);
    cut_set_message("memcached cas failed.");
    cut_assert_equal_int(MEMCACHED_SUCCESS, rc);

    rc = memcached_cas(memc, key, key_len, "cas changed", 12, 0, 0, cas);
    cut_set_message("memcached cas value is same.");
    /* TODO: fix rc after libmemcached fix */
    cut_assert_equal_int(MEMCACHED_PROTOCOL_ERROR, rc);
    /* cut_assert_equal_int(MEMCACHED_DATA_EXISTS, rc); */

    memcached_result_free(&results_obj);
  }
}
示例#9
0
  /// Retrieve the AoR data for a given SIP URI, creating it if there isn't
  /// any already, and returning NULL if we can't get a connection.
  AoR* MemcachedStore::get_aor_data(const std::string& aor_id)
                                    ///< the SIP URI
  {
    memcached_return_t rc;
    MemcachedAoR* aor_data = NULL;

    // Try to get a connection
    struct timespec wait_time;
    wait_time.tv_sec = 0;
    wait_time.tv_nsec = 100 * 1000 * 1000;
    memcached_st* st = memcached_pool_fetch(_pool, &wait_time, &rc);

    if (st != NULL)
    {
      // Got one: use it.
      const char* key_ptr = aor_id.data();
      const size_t key_len = aor_id.length();
      rc = memcached_mget(st, &key_ptr, &key_len, 1);
      if (memcached_success(rc))
      {
        memcached_result_st result;
        memcached_result_create(st, &result);
        memcached_fetch_result(st, &result, &rc);

        if (memcached_success(rc))
        {
          aor_data = deserialize_aor(std::string(memcached_result_value(&result), memcached_result_length(&result)));
          aor_data->set_cas(memcached_result_cas(&result));
          int now = time(NULL);
          expire_bindings(aor_data, now);
        }
        else
        {
          // AoR does not exist, so create it.
          aor_data = new MemcachedAoR();
        }
      }
      memcached_pool_release(_pool, st);
    }

    return (AoR*)aor_data;
  }
示例#10
0
int
sstack_memcache_read_multiple(memcached_st * memc,
						const char **keys,
						size_t *keylen,
						int num_keys,
						log_ctx_t *ctx)
{
	memcached_return_t rc = MEMCACHED_FAILURE;

	if (NULL == memc || NULL == *keys || num_keys <= 0) {
		sfs_log(ctx, SFS_ERR, "%s: Invalid parameters specified \n",
						__FUNCTION__);

		return -1;
	}
	rc = memcached_mget(memc, keys, keylen, num_keys);
	if (rc == MEMCACHED_SUCCESS)
		return 0;
	else
		return -rc;
}
示例#11
0
    virtual void read(payload_t *keys, int count, payload_t *values = NULL) {
        char *_value;
        size_t _value_length;
        uint32_t _flags;
        memcached_return_t _error;

        // Convert keys to arrays suitable for memcached
        char* __keys[count];
        size_t __sizes[count];
        for(int i = 0; i < count; i++) {
            __keys[i] = keys[i].first;
            __sizes[i] = keys[i].second;
        }

        // Do the multiget
        _error = memcached_mget(&memcached, __keys, __sizes, count);
        if(_error != MEMCACHED_SUCCESS) {
            fprintf(stderr, "Error performing multiread operation (%d)\n", _error);
            exit(-1);
        }

        // Fetch the results
        int i = 0;
        do {
            _value = memcached_fetch(&memcached, __keys[i], &__sizes[i],
                                     &_value_length, &_flags, &_error);
            if(_error != MEMCACHED_SUCCESS && _error != MEMCACHED_END) {
                fprintf(stderr, "Error performing read operation (%d)\n", _error);
                exit(-1);
            }
            if (values != NULL) {
                if (_value_length != values[i].second || memcmp(_value, values[i].first, _value_length) != 0) {
                    fprintf(stderr, "Incorrect value in database\n");
                    exit(-1);
                }
            }
            free(_value);
            i++;
        } while(_value != NULL);
    }
示例#12
0
memcached_return_t BaseMemcachedStore::get_from_replica(memcached_st* replica,
                                                        const char* key_ptr,
                                                        const size_t key_len,
                                                        std::string& data,
                                                        uint64_t& cas)
{
  memcached_return_t rc = MEMCACHED_ERROR;
  cas = 0;

  // We must use memcached_mget because memcached_get does not retrieve CAS
  // values.
  rc = memcached_mget(replica, &key_ptr, &key_len, 1);

  if (memcached_success(rc))
  {
    // memcached_mget command was successful, so retrieve the result.
    TRC_DEBUG("Fetch result");
    memcached_result_st result;
    memcached_result_create(replica, &result);
    memcached_fetch_result(replica, &result, &rc);

    if (memcached_success(rc))
    {
      // Found a record, so exit the read loop.
      TRC_DEBUG("Found record on replica");

      // Copy the record into a string. std::string::assign copies its
      // arguments when used with a char*, so we can free the result
      // afterwards.
      data.assign(memcached_result_value(&result),
                  memcached_result_length(&result));
      cas = memcached_result_cas(&result);
    }

    memcached_result_free(&result);
  }

  return rc;
}
示例#13
0
static Variant HHVM_METHOD(Memcache, get, const Variant& key,
                                          VRefParam flags /*= null*/) {
  auto data = Native::data<MemcacheData>(this_);
  if (key.is(KindOfArray)) {
    std::vector<const char *> real_keys;
    std::vector<size_t> key_len;
    Array keyArr = key.toArray();

    real_keys.reserve(keyArr.size());
    key_len.reserve(keyArr.size());

    for (ArrayIter iter(keyArr); iter; ++iter) {
      auto key = iter.second().toString();
      String serializedKey = memcache_prepare_key(key);
      char *k = new char[serializedKey.length()+1];
      std::strcpy(k, serializedKey.c_str());
      real_keys.push_back(k);
      key_len.push_back(serializedKey.length());
    }

    if (!real_keys.empty()) {
      const char *payload = NULL;
      size_t payload_len = 0;
      uint32_t flags = 0;
      const char *res_key = NULL;
      size_t res_key_len = 0;

      memcached_result_st result;

      memcached_return_t ret = memcached_mget(&data->m_memcache, &real_keys[0],
                                              &key_len[0], real_keys.size());
      memcached_result_create(&data->m_memcache, &result);
      Array return_val;

      while ((memcached_fetch_result(&data->m_memcache, &result, &ret))
             != nullptr) {
        if (ret != MEMCACHED_SUCCESS) {
          // should probably notify about errors
          continue;
        }

        payload     = memcached_result_value(&result);
        payload_len = memcached_result_length(&result);
        flags       = memcached_result_flags(&result);
        res_key     = memcached_result_key_value(&result);
        res_key_len = memcached_result_key_length(&result);

        return_val.set(String(res_key, res_key_len, CopyString),
                       memcache_fetch_from_storage(payload,
                                                   payload_len, flags));
      }
      memcached_result_free(&result);
      for ( size_t i = 0 ; i < real_keys.size() ; i++ ) {
        delete [] real_keys[i];
      }

      return return_val;
    }
  } else {
    char *payload = NULL;
    size_t payload_len = 0;
    uint32_t flags = 0;

    memcached_return_t ret;
    String serializedKey = memcache_prepare_key(key.toString());

    if (serializedKey.length() == 0) {
      return false;
    }

    payload = memcached_get(&data->m_memcache, serializedKey.c_str(),
                            serializedKey.length(), &payload_len, &flags, &ret);

    /* This is for historical reasons from libmemcached*/
    if (ret == MEMCACHED_END) {
      ret = MEMCACHED_NOTFOUND;
    }

    if (ret == MEMCACHED_NOTFOUND) {
      return false;
    }

    Variant retval = memcache_fetch_from_storage(payload, payload_len, flags);
    free(payload);

    return retval;
  }
  return false;
}
示例#14
0
static VALUE mc_get(int argc, VALUE *argv, VALUE self) {
  memcached_st *mc;
  VALUE cas, keys, results, key, result;
  VALUE scalar_key = Qnil;
  memcached_return status;

  Data_Get_Struct(self, memcached_st, mc);
  rb_scan_args(argc, argv, "11", &keys, &cas);
  memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, RTEST(cas) ? 1 : 0);

  if (RTEST(cas) && TYPE(keys) != T_ARRAY) {
    scalar_key = keys;
    keys = rb_ary_new4(1, &keys);
  }

  if (TYPE(keys) != T_ARRAY) {
    char*    str;
    size_t   len;
    uint32_t flags;

    key = use_binary(mc) ? keys : escape_key(keys, NULL);
    str = memcached_get(mc, RSTRING_PTR(key), RSTRING_LEN(key), &len, &flags, &status);
    if (str == NULL) return Qnil;

    if (status == MEMCACHED_SUCCESS) {
      result = rb_hash_new();
      rb_hash_aset(result, sym_value, rb_str_new(str, len));
      rb_hash_aset(result, sym_flags, INT2NUM(flags));
      free(str);
      return result;
    } else {
      printf("Memcache read error: %s %u\n", memcached_strerror(mc, status), status);
      return Qnil;
    }
  } else {
    memcached_result_st* mc_result;
    size_t       num_keys, i;
    const char** key_strings;
    size_t*      key_lengths;
    bool         escaped;

    results = rb_hash_new();
    num_keys = RARRAY_LEN(keys);
    if (num_keys == 0) return results;

    key_strings = (const char**) malloc(num_keys * sizeof(char *));
    key_lengths = (size_t *) malloc(num_keys * sizeof(size_t));
    for (i = 0; i < RARRAY_LEN(keys); i++) {
      key = RARRAY_PTR(keys)[i];
      if (!use_binary(mc)) key = escape_key(key, &escaped);

      key_lengths[i] = RSTRING_LEN(key);
      key_strings[i] = RSTRING_PTR(key);
    }

    memcached_mget(mc, key_strings, key_lengths, num_keys);

    while ((mc_result = memcached_fetch_result(mc, NULL, &status))) {
      if (escaped) {
        key = unescape_key(memcached_result_key_value(mc_result), memcached_result_key_length(mc_result));
      } else {
        key = rb_str_new(memcached_result_key_value(mc_result), memcached_result_key_length(mc_result));
      }

      if (status == MEMCACHED_SUCCESS) {
        result = rb_hash_new();
        rb_hash_aset(result, sym_value, rb_str_new(memcached_result_value(mc_result),
                                                   memcached_result_length(mc_result)));
        rb_hash_aset(result, sym_flags, INT2NUM(memcached_result_flags(mc_result)));
        if (RTEST(cas)) rb_hash_aset(result, sym_cas, ULL2NUM(memcached_result_cas(mc_result)));
        memcached_result_free(mc_result);
        rb_hash_aset(results, key, result);
      } else {
        printf("Memcache read error: %s %u\n", memcached_strerror(mc, status), status);
      }
    }
    free(key_strings);
    free(key_lengths);
    if (!NIL_P(scalar_key)) return rb_hash_aref(results, scalar_key);
    return results;
  }
}
示例#15
0
int main(int argc, char *argv[])
{
    if (argc < 3) {
        std::cerr << "Usage: qurluniqmgr set|get servers" << std::endl;
        exit(1);
    }

    std::string cmd = argv[1];
    std::string server = argv[2];

    memcached_st *queue;
    queue  = memcached_create(NULL);
    memcached_server_st *servers;
    servers= memcached_servers_parse(server.c_str());
    if (servers != NULL) {
       memcached_server_push(queue, servers);
       memcached_server_list_free(servers);
    } else {
        std::cerr << "Error server config error" << std::endl;
        std::cerr << "Usage: qurluniqmgr set|get servers" << std::endl;
        exit(1);
    }

    if (cmd == "set") {
        std::string line;
        int count = 0;
        while (std::getline(std::cin, line)) {
            ++count;
            if (count % 100000 == 0) {
                std::cerr << "get total " << count << std::endl;
            }

            if (line.size() == 0) {
                continue;
            }

            memcached_return_t rc = memcached_set(queue, line.c_str(), line.size(), "1", 1, 0, 0);
            if (rc != MEMCACHED_SUCCESS) {
                std::cerr << "set " << line <<  " error " << std::endl;
            }
        }
    } else if (cmd == "set0") {
        std::string line;
        int count = 0;
        while (std::getline(std::cin, line)) {
            ++count;
            if (count % 100000 == 0) {
                std::cerr << "get total " << count << std::endl;
            }

            if (line.size() == 0) {
                continue;
            }

            memcached_return_t rc = memcached_set(queue, line.c_str(), line.size(), "0", 1, 0, 0);
            if (rc != MEMCACHED_SUCCESS) {
                std::cerr << "set " << line <<  " error " << std::endl;
            }
        }
    } else if (cmd == "get") {
        const char* keys[BATCH_SIZE];
        size_t key_lens[BATCH_SIZE];

        char ret_key[256];
        size_t ret_key_len;
        size_t ret_val_len;
        uint32_t flags;
        char * ret_val = NULL;
        memcached_return rc;

        std::vector<std::string> batch_vec;
        std::string line;
        int count = 0;
        while (std::getline(std::cin, line)) {
            ++count;
            if (count % 100000 == 0) {
                std::cerr << "get total " << count << std::endl;
            }

            if (line.size() == 0) {
                continue;
            }
            batch_vec.push_back(line);
            if (batch_vec.size() == BATCH_SIZE) {
                for (size_t i = 0; i < batch_vec.size(); i++) {
                    keys[i] = batch_vec[i].c_str();
                    key_lens[i] = batch_vec[i].size();
                }

                rc = memcached_mget(queue, keys, key_lens, batch_vec.size());

                if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_DATA_EXISTS || rc == MEMCACHED_STORED) {
                    while ((ret_val = memcached_fetch(queue, ret_key, &ret_key_len, &ret_val_len, &flags, &rc))) {
                        free(ret_val);
                    }
                } else {
                    std::cerr << "ERROR when store " << std::endl;
                }

                batch_vec.clear();
            }
        }

        if (batch_vec.size() > 0) {
            for (size_t i = 0; i < batch_vec.size(); i++) {
                keys[i] = batch_vec[i].c_str();
                key_lens[i] = batch_vec[i].size();
            }

            rc = memcached_mget(queue, keys, key_lens, batch_vec.size());
            if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_DATA_EXISTS || rc == MEMCACHED_STORED) {
                while ((ret_val = memcached_fetch(queue, ret_key, &ret_key_len, &ret_val_len, &flags, &rc))) {
                    free(ret_val);
                }
            } else {
                std::cerr << "ERROR when store " << std::endl;
            }

            batch_vec.clear();
        }
    } else {
        std::cerr << "No cmd " << cmd << " supported"<< std::endl;
        std::cerr << "Usage: qurluniqmgr set|get servers" << std::endl;
        exit(1);
    }

    return 0;
}
示例#16
0
Variant c_Memcache::t_get(CVarRef key, VRefParam flags /*= null*/) {
  if (key.is(KindOfArray)) {
    std::vector<const char *> real_keys;
    std::vector<size_t> key_len;
    Array keyArr = key.toArray();

    real_keys.reserve(keyArr.size());
    key_len.reserve(keyArr.size());

    for (ArrayIter iter(keyArr); iter; ++iter) {
      real_keys.push_back(const_cast<char *>(iter.second().toString().c_str()));
      key_len.push_back(iter.second().toString().length());
    }

    if (!real_keys.empty()) {
      const char *payload = NULL;
      size_t payload_len = 0;
      uint32_t flags = 0;
      const char *res_key = NULL;
      size_t res_key_len = 0;

      memcached_result_st result;

      memcached_return_t ret = memcached_mget(&m_memcache, &real_keys[0],
                                              &key_len[0], real_keys.size());
      memcached_result_create(&m_memcache, &result);
      Array return_val;

      while ((memcached_fetch_result(&m_memcache, &result, &ret)) != NULL) {
        if (ret != MEMCACHED_SUCCESS) {
          // should probably notify about errors
          continue;
        }

        payload     = memcached_result_value(&result);
        payload_len = memcached_result_length(&result);
        flags       = memcached_result_flags(&result);
        res_key     = memcached_result_key_value(&result);
        res_key_len = memcached_result_key_length(&result);

        return_val.set(String(res_key, res_key_len, CopyString),
                       memcache_fetch_from_storage(payload,
                                                   payload_len, flags));
      }
      memcached_result_free(&result);

      return return_val;
    }
  } else {
    char *payload = NULL;
    size_t payload_len = 0;
    uint32_t flags = 0;

    memcached_return_t ret;
    String skey = key.toString();

    if (skey.length() == 0) {
      return false;
    }

    payload = memcached_get(&m_memcache, skey.c_str(), skey.length(),
                            &payload_len, &flags, &ret);

    /* This is for historical reasons from libmemcached*/
    if (ret == MEMCACHED_END) {
      ret = MEMCACHED_NOTFOUND;
    }

    if (ret == MEMCACHED_NOTFOUND) {
      return false;
    }

    Variant retval = memcache_fetch_from_storage(payload, payload_len, flags);
    free(payload);

    return retval;
  }
  return false;
}
示例#17
0
/// Retrieve the data for a given namespace and key.
Store::Status MemcachedStore::get_data(const std::string& table,
                                       const std::string& key,
                                       std::string& data,
                                       uint64_t& cas,
                                       SAS::TrailId trail)
{
  Store::Status status = Store::Status::OK;


  // Construct the fully qualified key.
  std::string fqkey = table + "\\\\" + key;
  const char* key_ptr = fqkey.data();
  const size_t key_len = fqkey.length();

  const std::vector<memcached_st*>& replicas = get_replicas(fqkey, Op::READ);

  if (trail != 0)
  {
    SAS::Event start(trail, SASEvent::MEMCACHED_GET_START, 0);
    start.add_var_param(fqkey);
    SAS::report_event(start);
  }

  LOG_DEBUG("%d read replicas for key %s", replicas.size(), fqkey.c_str());

  // Read from all replicas until we get a positive result.
  memcached_return_t rc = MEMCACHED_ERROR;
  bool active_not_found = false;
  size_t failed_replicas = 0;
  size_t ii;
  // If we only have one replica, we should try it twice -
  // libmemcached won't notice a dropped TCP connection until it tries
  // to make a request on it, and will fail the request then
  // reconnect, so the second attempt could still work.
  size_t attempts = (replicas.size() == 1) ? 2 : replicas.size();

  for (ii = 0; ii < attempts; ++ii)
  {
    size_t replica_idx;
    if ((replicas.size() == 1) && (ii == 1))
    {
      if (rc != MEMCACHED_CONNECTION_FAILURE)
      {
        // This is a legitimate error, not a server failure, so we
        // shouldn't retry.
        break;
      }
      replica_idx = 0;
      LOG_WARNING("Failed to read from sole memcached replica: retrying once");
    }
    else
    {
      replica_idx = ii;
    }
    // We must use memcached_mget because memcached_get does not retrieve CAS
    // values.
    LOG_DEBUG("Attempt to read from replica %d (connection %p)", replica_idx, replicas[replica_idx]);
    rc = memcached_mget(replicas[replica_idx], &key_ptr, &key_len, 1);

    if (memcached_success(rc))
    {
      // memcached_mget command was successful, so retrieve the result.
      LOG_DEBUG("Fetch result");
      memcached_result_st result;
      memcached_result_create(replicas[replica_idx], &result);
      memcached_fetch_result(replicas[replica_idx], &result, &rc);

      if (memcached_success(rc))
      {
        // Found a record, so exit the read loop.
        LOG_DEBUG("Found record on replica %d", replica_idx);
        data.assign(memcached_result_value(&result), memcached_result_length(&result));
        cas = (active_not_found) ? 0 : memcached_result_cas(&result);

        // std::string::assign copies its arguments when used with a
        // char*, so this is safe.
        memcached_result_free(&result);
        break;
      }
      else
      {
        // Free the result and continue the read loop.
        memcached_result_free(&result);
      }
    }


    if (rc == MEMCACHED_NOTFOUND)
    {
      // Failed to find a record on an active replica.  Flag this so if we do
      // find data on a later replica we can reset the cas value returned to
      // zero to ensure a subsequent write will succeed.
      LOG_DEBUG("Read for %s on replica %d returned NOTFOUND", fqkey.c_str(), replica_idx);
      active_not_found = true;
    }
    else
    {
      // Error from this node, so consider it inactive.
      LOG_DEBUG("Read for %s on replica %d returned error %d (%s)",
                fqkey.c_str(), replica_idx, rc, memcached_strerror(replicas[replica_idx], rc));
      ++failed_replicas;
    }
  }

  if (memcached_success(rc))
  {
    if (trail != 0)
    {
      SAS::Event got_data(trail, SASEvent::MEMCACHED_GET_SUCCESS, 0);
      got_data.add_var_param(fqkey);
      got_data.add_var_param(data);
      got_data.add_static_param(cas);
      SAS::report_event(got_data);
    }
    // Return the data and CAS value.  The CAS value is either set to the CAS
    // value from the result, or zero if an earlier active replica returned
    // NOT_FOUND.  This ensures that a subsequent set operation will succeed
    // on the earlier active replica.
    LOG_DEBUG("Read %d bytes from table %s key %s, CAS = %ld",
              data.length(), table.c_str(), key.c_str(), cas);

  }
  else if (failed_replicas < replicas.size())
  {
    // At least one replica returned NOT_FOUND.
    if (trail != 0)
    {
      SAS::Event not_found(trail, SASEvent::MEMCACHED_GET_NOT_FOUND, 0);
      not_found.add_var_param(fqkey);
      SAS::report_event(not_found);
    }

    LOG_DEBUG("At least one replica returned not found, so return NOT_FOUND");
    status = Store::Status::NOT_FOUND;
  }
  else
  {
    // All replicas returned an error, so log the error and return the
    // failure.
    if (trail != 0)
    {
      SAS::Event err(trail, SASEvent::MEMCACHED_GET_ERROR, 0);
      err.add_var_param(fqkey);
      SAS::report_event(err);
    }

    LOG_ERROR("Failed to read data for %s from %d replicas",
              fqkey.c_str(), replicas.size());
    status = Store::Status::ERROR;
  }

  return status;
}