/* Set the value, then quit to make sure it is flushed. Come back in and test that add fails. */ static test_return_t add_test(memcached_st *memc) { memcached_return_t rc; const char *key= "foo"; const char *value= "when we sanitize"; unsigned long long setting_value; setting_value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK); rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED); memcached_quit(memc); rc= memcached_add(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint32_t)0); /* Too many broken OS'es have broken loopback in async, so we can't be sure of the result */ if (setting_value) { test_true(rc == MEMCACHED_NOTSTORED || rc == MEMCACHED_STORED); } else { test_true(rc == MEMCACHED_NOTSTORED); } return 0; }
/*doc Memcached add(key, value[, expiration]) Asks memcached to store the value identified by the key, but only if the server *doesn't* already hold data for this key. Returns true on success, false in case of a collision. Otherwise raises an exception. */ IoObject *IoMemcached_add(IoMemcached *self, IoObject *locals, IoMessage *m) { IoSeq *key = IoMessage_locals_seqArgAt_(m, locals, 0); IoObject *value = IoMessage_locals_quickValueArgAt_(m, locals, 1); time_t expiration = IoMessage_argCount(m) == 3 ? IoMessage_locals_intArgAt_(m, locals, 2) : 0; uint32_t flags; size_t size; char *cvalue = IoMemcached_serialize(self, locals, value, &size, &flags); memcached_return_t rc; rc = memcached_add(DATA(self)->mc, CSTRING(key), IOSEQ_LENGTH(key), cvalue, size, expiration, flags ); free(cvalue); if(rc != MEMCACHED_SUCCESS && rc != MEMCACHED_NOTSTORED) IoState_error_(IOSTATE, m, memcached_strerror(DATA(self)->mc, rc)); // MEMCACHED_NOTSTORED is a legitmate error in the case of a collision. if(rc == MEMCACHED_NOTSTORED) return IOSTATE->ioFalse; return IOSTATE->ioTrue; // MEMCACHED_SUCCESS }
static bool HHVM_METHOD(Memcache, add, const String& key, const Variant& var, int flag /*= 0*/, int expire /*= 0*/) { if (key.empty()) { raise_warning("Key cannot be empty"); return false; } auto data = Native::data<MemcacheData>(this_); if (!hasAvailableServers(data)) { return false; } std::vector<char> serialized = memcache_prepare_for_storage(data, var, flag); String serializedKey = memcache_prepare_key(key); memcached_return_t ret = memcached_add(&data->m_memcache, serializedKey.c_str(), serializedKey.length(), serialized.data(), serialized.size(), expire, flag); return (ret == MEMCACHED_SUCCESS); }
void test_memcached_replace(void) { uint32_t flags; memcached_return rc; grn_test_memcached_assert_equal_rc( MEMCACHED_NOTSTORED, memcached_replace(memc, "key", 3, "value", 5, 0, 0xdeadbeefU), cut_message("memcached replace succeeded.")); sleep(1); grn_test_memcached_assert( memcached_add(memc, "key", 3, "value", 5, 0, 0xdeadbeefU), cut_message("memcached add failed.")); grn_test_memcached_assert( memcached_replace(memc, "key", 3, "new-value", 9, 0, 0xdeadbeefU), cut_message("memcached replace failed.")); val1 = memcached_get(memc, "key", 3, &val1_len, &flags, &rc); grn_test_memcached_assert(rc, cut_message("memcached get failed.")); cut_assert_equal_string("new-value", val1); cut_assert_equal_uint(0xdeadbeefU, flags); }
void test_memcached_replace(void) { uint32_t flags; memcached_return rc; rc = memcached_replace(memc, "key", 3, "value", 5, 0, 0xdeadbeefU); cut_set_message("memcached replace succeeded."); /* TODO: fix rc after libmemcached fix */ cut_assert_equal_int(MEMCACHED_PROTOCOL_ERROR, rc); sleep(1); rc = memcached_add(memc, "key", 3, "value", 5, 0, 0xdeadbeefU); cut_set_message("memcached add failed."); cut_assert_equal_int(MEMCACHED_SUCCESS, rc); rc = memcached_replace(memc, "key", 3, "new-value", 9, 0, 0xdeadbeefU); cut_set_message("memcached replace failed."); cut_assert_equal_int(MEMCACHED_SUCCESS, rc); val1 = memcached_get(memc, "key", 3, &val1_len, &flags, &rc); cut_set_message("memcached get failed."); cut_assert_equal_int(MEMCACHED_SUCCESS, rc); cut_assert_equal_string("new-value", val1); cut_assert_equal_uint(0xdeadbeefU, flags); }
static mrb_value mrb_memcached_add(mrb_state *mrb, mrb_value self) { mrb_value key, val; mrb_int expr = 0; mrb_memcached_data *data = DATA_PTR(self); memcached_return mrt; mrb_get_args(mrb, "oo|i", &key, &val, &expr); switch (mrb_type(key)) { case MRB_TT_STRING: break; case MRB_TT_SYMBOL: key = mrb_obj_as_string(mrb, key); break; default: mrb_raise(mrb, E_RUNTIME_ERROR, "memcached key type is string or symbol"); } val = mrb_obj_as_string(mrb, val); mrt = memcached_add(data->mst, RSTRING_PTR(key), RSTRING_LEN(key), RSTRING_PTR(val), RSTRING_LEN(val), (time_t)expr, (uint32_t)0); if (mrt != MEMCACHED_SUCCESS && mrt != MEMCACHED_STORED && mrt != MEMCACHED_NOTSTORED) { // add failed return mrb_nil_value(); } return mrb_fixnum_value(mrt); }
static int php_memc_sess_lock(memcached_st *memc, const char *key) { char *lock_key = NULL; int lock_key_len = 0; unsigned long attempts; long write_retry_attempts = 0; long lock_maxwait = MEMC_G(sess_lock_max_wait); long lock_wait = MEMC_G(sess_lock_wait); long lock_expire = MEMC_G(sess_lock_expire); time_t expiration; memcached_return status; /* set max timeout for session_start = max_execution_time. (c) Andrei Darashenka, Richter & Poweleit GmbH */ if (lock_maxwait <= 0) { lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0); if (lock_maxwait <= 0) { lock_maxwait = MEMC_SESS_LOCK_EXPIRATION; } } if (lock_wait == 0) { lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT; } if (lock_expire <= 0) { lock_expire = lock_maxwait; } expiration = lock_expire + 1; attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait); /* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */ if (MEMC_G(sess_remove_failed_enabled)) { write_retry_attempts = MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1); } lock_key_len = spprintf(&lock_key, 0, "lock.%s", key); do { status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0); if (status == MEMCACHED_SUCCESS) { MEMC_G(sess_locked) = 1; MEMC_G(sess_lock_key) = lock_key; MEMC_G(sess_lock_key_len) = lock_key_len; return 0; } else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) { if (write_retry_attempts > 0) { write_retry_attempts--; continue; } php_error_docref(NULL, E_WARNING, "Write of lock failed"); break; } if (lock_wait > 0) { usleep(lock_wait); } } while(--attempts > 0); efree(lock_key); return -1; }
/** * Add an object with the specified key and value to the server. This * function returns false if the object already exists on the server. * * @param[in] key key of object to add * @param[in] value of object to add * @return true on success; false otherwise */ bool add(const std::string &key, const std::vector<char> &value) { if (key.empty() || value.empty()) { return false; } memcached_return rc= memcached_add(&memc, key.c_str(), key.length(), &value[0], value.size(), 0, 0); return (rc == MEMCACHED_SUCCESS); }
void rate_limiter::update(const std::string &ip, int bytes) { if (ptr) { time_t now = time(NULL); std::string key; state *sp; size_t length; uint32_t flags; memcached_return error; key = "cgimap:" + ip; retry: if (ptr && (sp = (state *)memcached_get(ptr, key.data(), key.size(), &length, &flags, &error)) != NULL) { assert(length == sizeof(state)); int64_t elapsed = now - sp->last_update; sp->last_update = now; if (elapsed * bytes_per_sec < sp->bytes_served) { sp->bytes_served = sp->bytes_served - elapsed * bytes_per_sec + bytes; } else { sp->bytes_served = bytes; } // should use CAS but it's a right pain so we'll wing it for now... memcached_replace(ptr, key.data(), key.size(), (char *)sp, sizeof(state), 0, 0); free(sp); } else { state s; s.last_update = now; s.bytes_served = bytes; if (memcached_add(ptr, key.data(), key.size(), (char *)&s, sizeof(state), 0, 0) == MEMCACHED_NOTSTORED) { goto retry; } } } return; }
int ssMemcached::add(char *sKey, size_t nKeyLen, char *pValue, int pValueLen, int nTime) { uint32_t flag = 0; retCode_ = memcached_add(memc_, sKey, nKeyLen, pValue, pValueLen, nTime, flag); if (retCode_ == MEMCACHED_SUCCESS) { //fprintf(stderr,"Key stored successfully\n"); } else { fprintf(stderr, "Couldn't store key: %s\n", memcached_strerror(memc_, retCode_)); return 0; } return 1; }
static int exec_add(memcached_st *mcd, const char *key, const char *value, time_t expire, uint32_t flags) { memcached_return_t error = memcached_add(mcd, key, strlen(key), value, strlen(value), expire, flags); if (error == MEMCACHED_SUCCESS) printf("add: key=%s value=%s expire=%lu flags=%u\n", key, value, expire, flags); else printf("add: key=%s error=%s\n", key, memcached_strerror(mcd, error)); return 0; }
void store_memcached(memcached_st *cache, const char *path, struct nipc_packet *packet) { char *key = key_for_memcached(path, packet->type); memcached_return_t memcached_response = memcached_add(cache, key, strlen(key), packet->data, packet->data_length, (time_t) 0, (uint32_t) 0); if (memcached_response == MEMCACHED_SUCCESS) { log_info(memcached_logger, "Se guardaron %d bytes para la clave %s", packet->data_length, key); } else { log_error(memcached_logger, "Error guardando datos en la clave %s: %s", key, memcached_strerror(cache, memcached_response)); } free(key); }
/** * @function memcached.add * * ### Synopsis * * var rc = memcached.add(handle, key, value); * var rc = memcached.add(handle, key, value, expiration); * var rc = memcached.add(handle, key, value, expiration, flags); * * Store information in memcached indexed by key. * * If an object identified by key already exists on the server, an error occurs. * * @param {object} handle - handle to memcached connection. * @param {string} key - key of data to set in memcached. * @param {string} value - value of data to set in memcached. * @param {int} expiration - length of time value is valid (after this it will be removed from memcached automatically). * @param {int} flags - user defined integer value stored along with the value. * @return {int} rc - result code; 0 if no error, otherwise the error code. */ JSVAL _memcached_add (JSARGS args) { HandleScope scope; M *handle = HANDLE(args[0]); String::Utf8Value key(args[1]); String::Utf8Value value(args[2]); time_t expiration = 0; if (args.Length() > 3) { expiration = args[3]->IntegerValue(); } uint32_t flags = 0; if (args.Length() > 4) { flags = args[4]->IntegerValue(); } return scope.Close(Integer::New(memcached_add(handle, *key, strlen(*key), *value, strlen(*value), expiration, flags))); }
static void rush_add(int nr, char *buf, char seed, uint32_t key_len, uint32_t value_len, memcached_st *memc) { int i; memcached_return_t rc; char *key, *value; for(i=0; i<nr; i++) { generate_key_value(i,buf,seed,&key,key_len,&value,value_len); rc=memcached_add(memc,key,key_len,value,value_len,(time_t)0,(uint32_t)0); if(memcached_failed(rc)) { printf("memcached_add() failed: %s\n",memcached_strerror(memc,rc)); } PRINTF("i=%d, key_len=%ld, value_len=%ld\n",i,key_len,value_len); } }
bool c_Memcache::t_add(CStrRef key, CVarRef var, int flag /*= 0*/, int expire /*= 0*/) { if (key.empty()) { raise_warning("Key cannot be empty"); return false; } String serialized = memcache_prepare_for_storage(var, flag); memcached_return_t ret = memcached_add(&m_memcache, key.c_str(), key.length(), serialized.c_str(), serialized.length(), expire, flag); return (ret == MEMCACHED_SUCCESS); }
void Cache::add( const MC2String& key, const void* data, size_t dataLength, time_t expiration /*= 0*/, uint32_t flags /*= 0*/ ) { SysUtility::IgnorePipe ignorePipe; memcached_return rc = memcached_add( m_pimpl->memc.get(), key.c_str(), strlen( key.c_str() ), (const char*)data, dataLength, expiration, flags ); throwOnFail( rc, m_pimpl->memc.get(), "Couldn't add a value" ); }
/// Update the data for a particular address of record. Writes the data /// atomically. If the underlying data has changed since it was last /// read, the update is rejected and this returns false; if the update /// succeeds, this returns true. /// /// If a connection cannot be obtained, returns a random boolean based on /// data found on the call stack at the point of entry. bool MemcachedStore::set_aor_data(const std::string& aor_id, ///< the SIP URI AoR* data) ///< the data to store { memcached_return_t rc; MemcachedAoR* aor_data = (MemcachedAoR*)data; // 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. // // Expire any old bindings before writing to the server. In theory, // if there are no bindings left we could delete the entry, but this // may cause concurrency problems because memcached does not support // cas on delete operations. In this case we do a memcached_cas with // an effectively immediate expiry time. int now = time(NULL); int max_expires = expire_bindings(aor_data, now); std::string value = serialize_aor(aor_data); if (aor_data->get_cas() == 0) { // New record, so attempt to add. This will fail if someone else // gets there first. rc = memcached_add(st, aor_id.data(), aor_id.length(), value.data(), value.length(), max_expires, 0); } else { // This is an update to an existing record, so use memcached_cas // to make sure it is atomic. rc = memcached_cas(st, aor_id.data(), aor_id.length(), value.data(), value.length(), max_expires, 0, aor_data->get_cas()); } memcached_pool_release(_pool, st); } return memcached_success(rc); }
static zend_bool s_lock_session(memcached_st *memc, zend_string *sid) { memcached_return rc; char *lock_key; size_t lock_key_len; time_t expiration; zend_long wait_time, retries; php_memcached_user_data *user_data = memcached_get_user_data(memc); lock_key_len = spprintf(&lock_key, 0, "lock.%s", sid->val); expiration = s_lock_expiration(); wait_time = MEMC_SESS_INI(lock_wait_min); retries = MEMC_SESS_INI(lock_retries); do { rc = memcached_add(memc, lock_key, lock_key_len, "1", sizeof ("1") - 1, expiration, 0); switch (rc) { case MEMCACHED_SUCCESS: user_data->lock_key = zend_string_init(lock_key, lock_key_len, user_data->is_persistent); user_data->is_locked = 1; break; case MEMCACHED_NOTSTORED: case MEMCACHED_DATA_EXISTS: if (retries > 0) { usleep(wait_time * 1000); wait_time = MIN(MEMC_SESS_INI(lock_wait_max), wait_time * 2); } break; default: php_error_docref(NULL, E_WARNING, "Failed to write session lock: %s", memcached_strerror (memc, rc)); break; } } while (!user_data->is_locked && retries-- > 0); efree(lock_key); return user_data->is_locked; }
Memcache_Res CMemcache:: Memcac_Prepend(string strKey, const char* pValue, size_t val_size, time_t expiration) { Memcache_Res mRes = MEMCACHED_SUCCESS; if(strKey.empty() || NULL == pValue) return static_cast<Memcache_Res>(MEMCACHED_INVALID_ARGUMENTS); // lock and prepend pthread_mutex_lock(&m_hmc_mutex); if(NULL == m_hMc) return MEMCACHED_SERVER_ERROR; mRes = memcached_prepend(m_hMc, strKey.c_str(), strKey.length(), pValue, val_size, expiration, 0); if(MEMCACHED_NOTSTORED == mRes) mRes = memcached_add(m_hMc, strKey.c_str(), strKey.length(), pValue, val_size, expiration, 0); pthread_mutex_unlock(&m_hmc_mutex); return mRes; }
VALUE mc_add(int argc, VALUE *argv, VALUE self) { memcached_st *mc; VALUE key, value, expiry, flags; static memcached_return_t result; Data_Get_Struct(self, memcached_st, mc); rb_scan_args(argc, argv, "22", &key, &value, &expiry, &flags); key = StringValue(key); if (!use_binary(mc)) key = escape_key(key, NULL); value = StringValue(value); result = memcached_add(mc, RSTRING_PTR(key), RSTRING_LEN(key), RSTRING_PTR(value), RSTRING_LEN(value), RTEST(expiry) ? NUM2UINT(expiry) : 0, RTEST(flags) ? NUM2UINT(flags) : 0); if (result == MEMCACHED_SUCCESS) { return value; } else if(result == MEMCACHED_NOTSTORED) { return Qnil; } else { return throw_error(&result); } }
static int exec_simple_bench(memcached_st *mcd, double scale) { char kbuf[256]; char vbuf[1024 * 1024]; int klen, vlen; int i, n, count; int num_gets = 0; int num_adds = 0; long total = 0; long interval; struct timeval tv1, tv2; if (scale < 100.0) scale = 100.0; n = (int)(scale * 64); count = (int)(scale * 512); srand(count); gettimeofday(&tv1, NULL); memcached_flush(mcd, 0); while (count-- > 0) { memcached_return_t error; uint32_t flags; char *value; size_t value_length; i = rand() % n; klen = sprintf(kbuf, "mcdbench_key%06u", i); value = memcached_get(mcd, kbuf, klen, &value_length, &flags, &error); if (value == NULL) { if (error != MEMCACHED_NOTFOUND) { printf("key=%s error=%s\n", kbuf, memcached_strerror(mcd, error)); continue; } make_pseudo_value(i, vbuf, &vlen); error = memcached_add(mcd, kbuf, klen, vbuf, vlen, 0, 0); if (error != MEMCACHED_SUCCESS) { printf("key=%s error=%s\n", kbuf, memcached_strerror(mcd, error)); continue; } num_adds++; total += vlen; } else { num_gets++; total += value_length; free(value); } } gettimeofday(&tv2, NULL); interval = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec); printf("time: %.2f adds: %u gets: %u transfer: %lubytes\n", ((double)interval) / 1000000.0, num_adds, num_gets, total); return 0; }
int pr_memcache_kadd(pr_memcache_t *mcache, module *m, const char *key, size_t keysz, void *value, size_t valuesz, time_t expires, uint32_t flags) { memcached_return res; /* XXX Should we allow null values to be added, thus allowing use of keys * as sentinels? */ if (mcache == NULL || m == NULL || key == NULL || value == NULL) { errno = EINVAL; return -1; } mcache_set_module_namespace(mcache, m); res = memcached_add(mcache->mc, key, keysz, value, valuesz, expires, flags); mcache_set_module_namespace(mcache, NULL); switch (res) { case MEMCACHED_SUCCESS: return 0; case MEMCACHED_ERRNO: if (errno != EINPROGRESS) { int xerrno = errno; pr_trace_msg(trace_channel, 3, "error adding key (%lu bytes), value (%lu bytes): system error: %s", (unsigned long) keysz, (unsigned long) valuesz, strerror(xerrno)); errno = xerrno; } else { /* We know that we're not using nonblocking IO; this value usually * means that libmemcached could not connect to the configured * memcached servers. So set the value to something more * indicative, and fall through. */ res = MEMCACHED_CONNECTION_FAILURE; } break; case MEMCACHED_SERVER_MARKED_DEAD: case MEMCACHED_CONNECTION_FAILURE: { memcached_server_instance_st server; server = memcached_server_get_last_disconnect(mcache->mc); if (server != NULL) { pr_trace_msg(trace_channel, 3, "unable to connect to %s:%d", memcached_server_name(server), memcached_server_port(server)); } break; } default: pr_trace_msg(trace_channel, 2, "error adding key (%lu bytes), value (%lu bytes): %s", (unsigned long) keysz, (unsigned long) valuesz, memcached_strerror(mcache->mc, res)); errno = EPERM; break; } return -1; }
/// Update the data for the specified namespace and key. Writes the data /// atomically, so if the underlying data has changed since it was last /// read, the update is rejected and this returns Store::Status::CONTENTION. Store::Status MemcachedStore::set_data(const std::string& table, const std::string& key, const std::string& data, uint64_t cas, int expiry, SAS::TrailId trail) { Store::Status status = Store::Status::OK; LOG_DEBUG("Writing %d bytes to table %s key %s, CAS = %ld, expiry = %d", data.length(), table.c_str(), key.c_str(), cas, expiry); // 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::WRITE); if (trail != 0) { SAS::Event start(trail, SASEvent::MEMCACHED_SET_START, 0); start.add_var_param(fqkey); start.add_var_param(data); start.add_static_param(cas); start.add_static_param(expiry); SAS::report_event(start); } LOG_DEBUG("%d write replicas for key %s", replicas.size(), fqkey.c_str()); // Calculate the rough expected expiry time. We store this in the flags // as it may be useful in future for read repair function. uint32_t now = time(NULL); uint32_t exptime = now + expiry; // Memcached uses a flexible mechanism for specifying expiration. // - 0 indicates never expire. // - <= MEMCACHED_EXPIRATION_MAXDELTA indicates a relative (delta) time. // - > MEMCACHED_EXPIRATION_MAXDELTA indicates an absolute time. // Absolute time is the only way to force immediate expiry. Unfortunately, // it's not reliable - see https://github.com/Metaswitch/cpp-common/issues/160 // for details. Instead, we use relative time for future times (expiry > 0) // and the earliest absolute time for immediate expiry (expiry == 0). time_t memcached_expiration = (time_t)((expiry > 0) ? expiry : MEMCACHED_EXPIRATION_MAXDELTA + 1); // First try to write the primary data record to the first responding // server. memcached_return_t rc = MEMCACHED_ERROR; size_t ii; size_t replica_idx; // 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) { if ((replicas.size() == 1) && (ii == 1)) { if (rc != MEMCACHED_CONNECTION_FAILURE) { // This is a legitimate error, not a transient server failure, so we // shouldn't retry. break; } replica_idx = 0; LOG_WARNING("Failed to write to sole memcached replica: retrying once"); } else { replica_idx = ii; } LOG_DEBUG("Attempt conditional write to replica %d (connection %p), CAS = %ld", replica_idx, replicas[replica_idx], cas); if (cas == 0) { // New record, so attempt to add. This will fail if someone else // gets there first. rc = memcached_add(replicas[replica_idx], key_ptr, key_len, data.data(), data.length(), memcached_expiration, exptime); } else { // This is an update to an existing record, so use memcached_cas // to make sure it is atomic. rc = memcached_cas(replicas[replica_idx], key_ptr, key_len, data.data(), data.length(), memcached_expiration, exptime, cas); } if (memcached_success(rc)) { LOG_DEBUG("Conditional write succeeded to replica %d", replica_idx); break; } else { LOG_DEBUG("memcached_%s command for %s failed on replica %d, rc = %d (%s), expiry = %d\n%s", (cas == 0) ? "add" : "cas", fqkey.c_str(), replica_idx, rc, memcached_strerror(replicas[replica_idx], rc), expiry, memcached_last_error_message(replicas[replica_idx])); if ((rc == MEMCACHED_NOTSTORED) || (rc == MEMCACHED_DATA_EXISTS)) { if (trail != 0) { SAS::Event err(trail, SASEvent::MEMCACHED_SET_CONTENTION, 0); err.add_var_param(fqkey); SAS::report_event(err); } // A NOT_STORED or EXISTS response indicates a concurrent write failure, // so return this to the application immediately - don't go on to // other replicas. LOG_INFO("Contention writing data for %s to store", fqkey.c_str()); status = Store::Status::DATA_CONTENTION; break; } } } if ((rc == MEMCACHED_SUCCESS) && (replica_idx < replicas.size())) { // Write has succeeded, so write unconditionally (and asynchronously) // to the replicas. for (size_t jj = replica_idx + 1; jj < replicas.size(); ++jj) { LOG_DEBUG("Attempt unconditional write to replica %d", jj); memcached_behavior_set(replicas[jj], MEMCACHED_BEHAVIOR_NOREPLY, 1); memcached_set(replicas[jj], key_ptr, key_len, data.data(), data.length(), memcached_expiration, exptime); memcached_behavior_set(replicas[jj], MEMCACHED_BEHAVIOR_NOREPLY, 0); } } if ((!memcached_success(rc)) && (rc != MEMCACHED_NOTSTORED) && (rc != MEMCACHED_DATA_EXISTS)) { if (trail != 0) { SAS::Event err(trail, SASEvent::MEMCACHED_SET_FAILED, 0); err.add_var_param(fqkey); SAS::report_event(err); } LOG_ERROR("Failed to write data for %s to %d replicas", fqkey.c_str(), replicas.size()); status = Store::Status::ERROR; } return status; }
int main(int argc, char *argv[]) { memcached_st *memc; memcached_return_t rc; memcached_server_st *servers; int return_code= 0; options_parse(argc, argv); initialize_sockets(); memc= memcached_create(NULL); process_hash_option(memc, opt_hash); if (!opt_servers) { char *temp; if ((temp= getenv("MEMCACHED_SERVERS"))) { opt_servers= strdup(temp); } else { fprintf(stderr, "No Servers provided\n"); exit(1); } } if (opt_servers) servers= memcached_servers_parse(opt_servers); else servers= memcached_servers_parse(argv[--argc]); memcached_server_push(memc, servers); memcached_server_list_free(servers); memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t)opt_binary); if (!initialize_sasl(memc, opt_username, opt_passwd)) { memcached_free(memc); return 1; } while (optind < argc) { struct stat sbuf; int fd; char *ptr; ssize_t read_length; char *file_buffer_ptr; fd= open(argv[optind], O_RDONLY); if (fd < 0) { fprintf(stderr, "memcp: %s: %s\n", argv[optind], strerror(errno)); optind++; continue; } (void)fstat(fd, &sbuf); ptr= rindex(argv[optind], '/'); if (ptr) ptr++; else ptr= argv[optind]; if (opt_verbose) { static const char *opstr[] = { "set", "add", "replace" }; printf("op: %s\nsource file: %s\nlength: %zu\n" "key: %s\nflags: %x\nexpires: %llu\n", opstr[opt_method - OPT_SET], argv[optind], (size_t)sbuf.st_size, ptr, opt_flags, (unsigned long long)opt_expires); } if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL) { fprintf(stderr, "malloc: %s\n", strerror(errno)); exit(1); } if ((read_length= read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1) { fprintf(stderr, "read: %s\n", strerror(errno)); exit(1); } if (read_length != sbuf.st_size) { fprintf(stderr, "Failure reading from file\n"); exit(1); } if (opt_method == OPT_ADD) rc= memcached_add(memc, ptr, strlen(ptr), file_buffer_ptr, (size_t)sbuf.st_size, opt_expires, opt_flags); else if (opt_method == OPT_REPLACE) rc= memcached_replace(memc, ptr, strlen(ptr), file_buffer_ptr, (size_t)sbuf.st_size, opt_expires, opt_flags); else rc= memcached_set(memc, ptr, strlen(ptr), file_buffer_ptr, (size_t)sbuf.st_size, opt_expires, opt_flags); if (rc != MEMCACHED_SUCCESS) { fprintf(stderr, "memcp: %s: memcache error %s", ptr, memcached_strerror(memc, rc)); if (memc->cached_errno) fprintf(stderr, " system error %s", strerror(memc->cached_errno)); fprintf(stderr, "\n"); return_code= -1; } free(file_buffer_ptr); close(fd); optind++; } memcached_free(memc); if (opt_servers) free(opt_servers); if (opt_hash) free(opt_hash); shutdown_sasl(); return return_code; }