Nitpick program flow of client.gets and others

This commit is contained in:
lericson 2010-10-08 21:25:14 +02:00
parent 3f687bb551
commit 432cd63ccd
2 changed files with 49 additions and 53 deletions

View File

@ -405,6 +405,13 @@ static PyObject *PylibMC_Client_get(PylibMC_Client *self, PyObject *arg) {
} }
static PyObject *PylibMC_Client_gets(PylibMC_Client *self, PyObject *arg) { static PyObject *PylibMC_Client_gets(PylibMC_Client *self, PyObject *arg) {
const char* keys[2];
size_t keylengths[2];
memcached_result_st results_obj;
memcached_result_st *results = NULL;
memcached_return_t rc;
PyObject* ret = NULL;
if (!_PylibMC_CheckKey(arg)) { if (!_PylibMC_CheckKey(arg)) {
return NULL; return NULL;
} else if (!PySequence_Length(arg)) { } else if (!PySequence_Length(arg)) {
@ -415,25 +422,17 @@ static PyObject *PylibMC_Client_gets(PylibMC_Client *self, PyObject *arg) {
return NULL; return NULL;
} }
/* we have to do this with mget because that's the only function /* Use an mget to fetch the key.
* that libmemcached exposes that returns a memcached_result_st, * mget is the only function that returns a memcached_result_st,
* which is the only way to get at the returned cas value */ * which is the only way to get at the returned cas value. */
*keys = PyString_AS_STRING(arg);
const char* keys[2] = {PyString_AS_STRING(arg), NULL}; *keylengths = (size_t)PyString_GET_SIZE(arg);
size_t keylengths[2] = {(size_t)PyString_GET_SIZE(arg), 0};
memcached_result_st results_obj;
memcached_result_st *results = NULL;
memcached_return_t rc;
PyObject* ret = NULL;
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
rc = memcached_mget(self->mc, keys, keylengths, 1); rc = memcached_mget(self->mc, keys, keylengths, 1);
if (rc == MEMCACHED_SUCCESS) { if (rc == MEMCACHED_SUCCESS) {
/* we don't have to check if the allocation was successful memcached_result_create(self->mc, &results_obj);
because it's right on our stack */
results = memcached_result_create(self->mc, &results_obj);
/* this will be NULL if the key wasn't found, or /* this will be NULL if the key wasn't found, or
memcached_result_st if it was */ memcached_result_st if it was */
results = memcached_fetch_result(self->mc, &results_obj, &rc); results = memcached_fetch_result(self->mc, &results_obj, &rc);
@ -447,27 +446,24 @@ static PyObject *PylibMC_Client_gets(PylibMC_Client *self, PyObject *arg) {
uint32_t flags = memcached_result_flags(results); uint32_t flags = memcached_result_flags(results);
uint64_t cas = memcached_result_cas(results); uint64_t cas = memcached_result_cas(results);
PyObject *r = _PylibMC_parse_memcached_value((char*)mc_val, val_size, flags); ret = _PylibMC_parse_memcached_value((char *)mc_val, val_size, flags);
if(r != NULL) { ret = Py_BuildValue("(NL)", ret, cas);
ret = Py_BuildValue("(OL)", r, cas);
/* we don't need our own reference to r, it just belongs to /* reset cursor if mget for some reason returned more than one result.
the ret tuple */ this should be a no-op otherwise. */
Py_DECREF(r);
}
memcached_quit(self->mc); memcached_quit(self->mc);
} else if (rc == MEMCACHED_END) {
/* Since python-memcache returns None when the key doesn't exist,
* so shall we. */
ret = Py_None;
Py_INCREF(Py_None);
} else {
ret = PylibMC_ErrFromMemcached(self, "memcached_gets", rc);
}
/* deallocate any indirect buffers, even though the struct itself /* deallocate any indirect buffers, even though the struct itself
is on our stack */ is on our stack */
memcached_result_free(&results_obj); memcached_result_free(&results_obj);
return ret; return ret;
} else if (rc == MEMCACHED_END) {
/* Key not found => (None, None) */
Py_RETURN_NONE;
} else {
return PylibMC_ErrFromMemcached(self, "memcached_gets", rc);
}
} }
/* {{{ Set commands (set, replace, add, prepend, append) */ /* {{{ Set commands (set, replace, add, prepend, append) */

View File

@ -268,8 +268,8 @@ Test CAS
>>> mc.behaviors['cas'] = True >>> mc.behaviors['cas'] = True
>>> mc.delete('foo') and False >>> mc.delete('foo') and False
False False
>>> mc.gets('foo') == None >>> mc.gets('foo')
True (None, None)
>>> mc.set('foo', 'bar') >>> mc.set('foo', 'bar')
True True
>>> foostr, cas = mc.gets('foo') >>> foostr, cas = mc.gets('foo')