Python wrappers for the disk cache methods

This commit is contained in:
Kovid Goyal 2021-01-01 14:08:23 +05:30
parent 58b1868536
commit 49562e96cc
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 67 additions and 19 deletions

View File

@ -425,7 +425,7 @@ create_cache_entry(const void *key, const size_t key_sz) {
}
bool
add_to_disk_cache(PyObject *self_, const void *key, size_t key_sz, const uint8_t *data, size_t data_sz) {
add_to_disk_cache(PyObject *self_, const void *key, size_t key_sz, const void *data, size_t data_sz) {
DiskCache *self = (DiskCache*)self_;
if (!ensure_state(self)) return false;
if (key_sz > MAX_KEY_SIZE) { PyErr_SetString(PyExc_KeyError, "cache key is too long"); return false; }
@ -505,34 +505,32 @@ read_from_cache_entry(const DiskCache *self, const CacheEntry *s, uint8_t *dest)
}
}
bool
read_from_disk_cache(PyObject *self_, const void *key, size_t key_sz, uint8_t **data, size_t *data_sz) {
void*
read_from_disk_cache(PyObject *self_, const void *key, size_t key_sz, void*(allocator)(void*, size_t), void* allocator_data) {
DiskCache *self = (DiskCache*)self_;
if (!ensure_state(self)) return false;
if (key_sz > MAX_KEY_SIZE) { PyErr_SetString(PyExc_KeyError, "cache key is too long"); return false; }
void *data = NULL;
if (!ensure_state(self)) return data;
if (key_sz > MAX_KEY_SIZE) { PyErr_SetString(PyExc_KeyError, "cache key is too long"); return data; }
mutex(lock);
CacheEntry *s = NULL;
HASH_FIND(hh, self->entries, key, key_sz, s);
if (!s) { PyErr_SetString(PyExc_KeyError, "No cached entry with specified key found"); goto end; }
data = allocator(allocator_data, s->data_sz);
if (!data) { PyErr_NoMemory(); goto end; }
*data = (uint8_t*)malloc(s->data_sz);
if (!*data) { PyErr_NoMemory(); goto end; }
*data_sz = s->data_sz;
if (s->data) { memcpy(*data, s->data, *data_sz); }
if (s->data) { memcpy(data, s->data, s->data_sz); }
else if (self->currently_writing.hash_key && self->currently_writing.hash_keylen == key_sz && memcmp(self->currently_writing.hash_key, key, key_sz) == 0) {
memcpy(*data, self->currently_writing.data, *data_sz);
xor_data(s->encryption_key, sizeof(s->encryption_key), *data, *data_sz);
memcpy(data, self->currently_writing.data, s->data_sz);
xor_data(s->encryption_key, sizeof(s->encryption_key), data, s->data_sz);
}
else {
read_from_cache_entry(self, s, *data);
xor_data(s->encryption_key, sizeof(s->encryption_key), *data, *data_sz);
read_from_cache_entry(self, s, data);
xor_data(s->encryption_key, sizeof(s->encryption_key), data, s->data_sz);
}
end:
mutex(unlock);
if (PyErr_Occurred()) return false;
return true;
return data;
}
#define PYWRAP(name) static PyObject* py##name(DiskCache *self, PyObject *args)
@ -556,9 +554,57 @@ PYWRAP(xor_data) {
return ans;
}
static PyObject*
add(PyObject *self, PyObject *args) {
const char *key, *data;
Py_ssize_t keylen, datalen;
PA("y#y#", &key, &keylen, &data, &datalen);
if (!add_to_disk_cache(self, key, keylen, data, datalen)) return NULL;
Py_RETURN_NONE;
}
static PyObject*
pyremove(PyObject *self, PyObject *args) {
const char *key;
Py_ssize_t keylen;
PA("y#", &key, &keylen);
bool removed = remove_from_disk_cache(self, key, keylen);
if (PyErr_Occurred()) return NULL;
if (removed) Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
typedef struct {
PyObject *bytes;
} BytesWrapper;
static void*
bytes_alloc(void *x, size_t sz) {
BytesWrapper *w = x;
w->bytes = PyBytes_FromStringAndSize(NULL, sz);
if (!w->bytes) return NULL;
return PyBytes_AS_STRING(w->bytes);
}
static PyObject*
get(PyObject *self, PyObject *args) {
const char *key;
Py_ssize_t keylen;
PA("y#", &key, &keylen);
BytesWrapper w = {0};
read_from_disk_cache(self, key, keylen, bytes_alloc, &w);
if (PyErr_Occurred()) { Py_CLEAR(w.bytes); return NULL; }
return w.bytes;
}
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
static PyMethodDef methods[] = {
MW(ensure_state, METH_NOARGS),
{"add", add, METH_VARARGS, NULL},
{"remove", pyremove, METH_VARARGS, NULL},
{"get", get, METH_VARARGS, NULL},
{NULL} /* Sentinel */
};

View File

@ -9,6 +9,8 @@
#include "data-types.h"
PyObject* create_disk_cache(void);
bool add_to_disk_cache(PyObject *self, const void *key, size_t key_sz, const uint8_t *data, size_t data_sz);
bool add_to_disk_cache(PyObject *self, const void *key, size_t key_sz, const void *data, size_t data_sz);
bool remove_from_disk_cache(PyObject *self_, const void *key, size_t key_sz);
bool read_from_disk_cache(PyObject *self_, const void *key, size_t key_sz, uint8_t **data, size_t *data_sz);
void* read_from_disk_cache(PyObject *self_, const void *key, size_t key_sz, void*(allocator)(void*, size_t), void*);
static inline void* disk_cache_malloc_allocator(void *x UNUSED, size_t sz) { return malloc(sz); }
static inline void* read_from_disk_cache_simple(PyObject *self_, const void *key, size_t key_sz) { return read_from_disk_cache(self_, key, key_sz, disk_cache_malloc_allocator, NULL); }