Merge patch from amix

Add support for bool values, use ssize_t in some places (not sure about
this) and some other stuff.
This commit is contained in:
lericson 2009-09-05 02:08:04 +02:00
parent 6396b951ce
commit 5fd68b34c7
4 changed files with 70 additions and 36 deletions

View File

@ -135,8 +135,12 @@ static PyObject *_PylibMC_parse_memcached_value(char *value, size_t size,
case PYLIBMC_FLAG_LONG:
retval = PyInt_FromString(value, NULL, 10);
break;
case PYLIBMC_FLAG_BOOL:
retval = PyInt_FromString(value, NULL, 10);
retval = PyBool_FromLong(PyInt_AS_LONG(retval));
break;
case PYLIBMC_FLAG_NONE:
retval = PyString_FromStringAndSize(value, (Py_ssize_t)size);
retval = PyString_FromStringAndSize(value, (size_t)size);
break;
default:
PyErr_Format(PylibMCExc_MemcachedError,
@ -199,6 +203,9 @@ static PyObject *_PylibMC_RunSetCommand(PylibMC_Client *self,
} else if (PyString_Check(val)) {
store_val = val;
Py_INCREF(store_val);
} else if (PyBool_Check(val)) {
store_flags |= PYLIBMC_FLAG_BOOL;
store_val = PyObject_Str(PyNumber_Int(val));
} else if (PyInt_Check(val)) {
store_flags |= PYLIBMC_FLAG_INTEGER;
store_val = PyObject_Str(PyNumber_Int(val));
@ -345,7 +352,8 @@ static PyObject *PylibMC_Client_get_multi(PylibMC_Client *self, PyObject *args,
char **keys, *prefix = NULL;
unsigned int prefix_len = 0;
size_t *key_lens;
Py_ssize_t nkeys;
size_t nkeys;
unsigned int valid_keys_len = 0;
memcached_return rc;
char curr_key[MEMCACHED_MAX_KEY];
@ -394,6 +402,7 @@ static PyObject *PylibMC_Client_get_multi(PylibMC_Client *self, PyObject *args,
}
keys[i] = PyString_AS_STRING(rkey);
key_objs[i++] = rkey;
valid_keys_len++;
}
}
Py_DECREF(key_it);
@ -416,44 +425,46 @@ static PyObject *PylibMC_Client_get_multi(PylibMC_Client *self, PyObject *args,
*/
retval = PyDict_New();
if ((rc = memcached_mget(self->mc, keys, key_lens, nkeys))
== MEMCACHED_SUCCESS) {
char *curr_val;
if(valid_keys_len > 0) {
if ((rc = memcached_mget(self->mc, keys, key_lens, nkeys))
== MEMCACHED_SUCCESS) {
char *curr_val;
while ((curr_val = memcached_fetch(
self->mc, curr_key, &curr_key_len, &curr_val_len,
&curr_flags, &rc)) != NULL
&& !PyErr_Occurred()) {
if (curr_val == NULL && rc == MEMCACHED_END) {
break;
} else if (rc == MEMCACHED_BAD_KEY_PROVIDED
|| rc == MEMCACHED_NO_KEY_PROVIDED) {
/* Do nothing at all. :-) */
} else if (rc != MEMCACHED_SUCCESS) {
Py_DECREF(retval);
retval = PylibMC_ErrFromMemcached(
self, "memcached_fetch", rc);
} else {
PyObject *val;
while ((curr_val = memcached_fetch(
self->mc, curr_key, &curr_key_len, &curr_val_len,
&curr_flags, &rc)) != NULL
&& !PyErr_Occurred()) {
if (curr_val == NULL && rc == MEMCACHED_END) {
break;
} else if (rc == MEMCACHED_BAD_KEY_PROVIDED
|| rc == MEMCACHED_NO_KEY_PROVIDED) {
/* Do nothing at all. :-) */
} else if (rc != MEMCACHED_SUCCESS) {
Py_DECREF(retval);
retval = PylibMC_ErrFromMemcached(
self, "memcached_fetch", rc);
} else {
PyObject *val;
/* This is safe because libmemcached's max key length
* includes space for a NUL-byte. */
curr_key[curr_key_len] = 0;
val = _PylibMC_parse_memcached_value(
curr_val, curr_val_len, curr_flags);
PyDict_SetItemString(retval, curr_key + prefix_len, val);
Py_DECREF(val);
/* This is safe because libmemcached's max key length
* includes space for a NUL-byte. */
curr_key[curr_key_len] = 0;
val = _PylibMC_parse_memcached_value(
curr_val, curr_val_len, curr_flags);
PyDict_SetItemString(retval, curr_key + prefix_len, val);
Py_DECREF(val);
}
free(curr_val);
}
free(curr_val);
/* Need to cleanup. */
if (PyErr_Occurred()) {
/* Not checking rc because an exception already occured, and
* we wouldn't want to mask it. */
memcached_quit(self->mc);
}
} else {
retval = PylibMC_ErrFromMemcached(self, "memcached_mget", rc);
}
/* Need to cleanup. */
if (PyErr_Occurred()) {
/* Not checking rc because an exception already occured, and
* we wouldn't want to mask it. */
memcached_quit(self->mc);
}
} else {
retval = PylibMC_ErrFromMemcached(self, "memcached_mget", rc);
}
free(key_lens);
@ -712,6 +723,9 @@ static PyObject *PylibMC_ErrFromMemcached(PylibMC_Client *self, const char *what
if (error == MEMCACHED_ERRNO) {
PyErr_Format(PylibMCExc_MemcachedError,
"system error %d from %s: %s", errno, what, strerror(errno));
/* The key exists, but it has no value */
} else if (error == 0) {
PyErr_SetString(PyExc_RuntimeError, "error == 0? " __FILE__ ":" __LINE__);
} else {
PyErr_Format(PylibMCExc_MemcachedError, "error %d from %s: %s",
error, what, memcached_strerror(self->mc, error));

View File

@ -47,6 +47,7 @@
#define PYLIBMC_FLAG_PICKLE (1 << 0)
#define PYLIBMC_FLAG_INTEGER (1 << 1)
#define PYLIBMC_FLAG_LONG (1 << 2)
#define PYLIBMC_FLAG_BOOL (1 << 3)
#define PYLIBMC_INC (1 << 0)
#define PYLIBMC_DEC (1 << 1)

View File

@ -72,6 +72,9 @@ class Client(_pylibmc.client):
stype = _pylibmc.server_type_tcp
addr_tups.append((stype, addr, port))
super(Client, self).__init__(addr_tups)
# Perfomance is generally a lot better with tcp_nodelay
# so set that as the default
self.behaviors["tcp_nodelay"] = True
def get_behaviors(self):
"""Gets the behaviors from the underlying C client instance.

View File

@ -10,8 +10,24 @@ if "LIBMEMCACHED_DIR" in os.environ:
libdirs.append(os.path.join(libdir, "lib"))
readme_text = open("README.rst", "U").read()
BASE_CFLAGS = ["-O3"]
BASE_LDFLAGS = []
mac_snow_leopard = (os.path.exists("/Developer/SDKs/MacOSX10.6.sdk/") and
int(os.uname()[2].split('.')[0]) >= 8)
if mac_snow_leopard:
# Only compile the 64bit version on Snow Leopard
# libmemcached should also be compiled with make
# CFLAGS="-arch x86_64"
# else one will expereince seg. faults
BASE_LDFLAGS.extend(['-arch', 'x86_64'])
BASE_CFLAGS.extend(['-arch', 'x86_64'])
pylibmc_ext = Extension("_pylibmc", ["_pylibmcmodule.c"],
extra_compile_args=BASE_CFLAGS,
extra_link_args=BASE_LDFLAGS,
libraries=["memcached"],
include_dirs=incdirs, library_dirs=libdirs)