Skip to content

Commit

Permalink
Implement persistency support.
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei Zmievski committed Dec 21, 2008
1 parent 0abeaeb commit 730a024
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 54 deletions.
2 changes: 1 addition & 1 deletion memcached-api.php
Expand Up @@ -69,7 +69,7 @@ class Memcached {
const OPT_PREFIX_KEY;


public function __construct( $locale ) {}
public function __construct( $persistent_id = '' ) {}

public function get( $key, $cache_cb = null ) {}

Expand Down
208 changes: 155 additions & 53 deletions memcached.c
Expand Up @@ -15,9 +15,6 @@
/* $ Id: $ */

/* TODO
* - refcount on php_memc_t
* - persistent_id in php_memc_t
* - persistent switch-over in constructor
*/

#ifdef HAVE_CONFIG_H
Expand Down Expand Up @@ -48,84 +45,189 @@ typedef struct {
unsigned int in_set:1;

memcached_st *conn;

unsigned is_persistent:1;
const char *plist_key;
int plist_key_len;
} php_memc_t;

/* {{{ memcached_functions[] */
static zend_function_entry memcached_functions[] = {
{ NULL, NULL, NULL }
};
/* }}} */

static zend_function_entry memcached_class_functions[] = {
{ NULL, NULL, NULL }
};
/* }}} */

/* {{{ memcached_module_entry
*/
zend_module_entry memcached_module_entry = {
STANDARD_MODULE_HEADER,
"memcached",
memcached_functions,
PHP_MINIT(memcached),
PHP_MSHUTDOWN(memcached),
NULL,
NULL,
PHP_MINFO(memcached),
PHP_MEMCACHED_VERSION,
STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_MEMCACHED
ZEND_GET_MODULE(memcached)
#endif

ZEND_RSRC_DTOR_FUNC(php_memc_dtor)
/****************************************
Forward declarations
****************************************/
int php_memc_list_entry(void);


/****************************************
Function implementations
****************************************/
static PHP_METHOD(Memcached, __construct)
{
if (rsrc->ptr) {
php_memc_t *obj = (php_memc_t *)rsrc->ptr;
/* TODO dtor code */
rsrc->ptr = NULL;
}
zval *object = getThis();
php_memc_t *i_obj;
char *persistent_id = NULL;
int persistent_id_len;
zend_bool skip_ctor = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &persistent_id,
&persistent_id_len) == FAILURE) {
ZVAL_NULL(object);
return;
}

i_obj = (php_memc_t *) zend_object_store_get_object(object TSRMLS_CC);

if (persistent_id) {
char *plist_key = NULL;
int plist_key_len = 0;
zend_rsrc_list_entry *le;
php_memc_t *pi_obj = NULL;

plist_key_len = spprintf(&plist_key, 0, "memcached:id=%s", persistent_id);
if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len+1, (void *)&le) == SUCCESS) {
if (le->type == php_memc_list_entry()) {
pi_obj = (php_memc_t *) le->ptr;
}
}

if (pi_obj) {
skip_ctor = 1;
} else {
pi_obj = pecalloc(1, sizeof(*pi_obj), 1);

if (pi_obj == NULL) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate handle");
/* not reached */
}

pi_obj->is_persistent = 1;
if ((pi_obj->plist_key = pemalloc(plist_key_len + 1, 1)) == NULL) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory: cannot allocate handle");
/* not reached */
}
memcpy((char *)pi_obj->plist_key, plist_key, plist_key_len + 1);
pi_obj->plist_key_len = plist_key_len + 1;
}

pi_obj->ce = i_obj->ce;
pi_obj->properties = i_obj->properties;
efree(i_obj);
i_obj = pi_obj;
zend_object_store_set_object(object, i_obj TSRMLS_CC);

if (plist_key) {
efree(plist_key);
}
}

if (skip_ctor) {
return;
}

if (persistent_id) {
zend_rsrc_list_entry le;

le.type = php_memc_list_entry();
le.ptr = i_obj;
if (zend_hash_update(&EG(persistent_list), (char *)i_obj->plist_key,
i_obj->plist_key_len, (void *)&le, sizeof(le), NULL) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "could not register persistent entry");
/* not reached */
}
}
}

static void php_memc_free(php_memc_t *obj TSRMLS_DC)

/****************************************
Internal support code
****************************************/
static void php_memc_free(php_memc_t *i_obj TSRMLS_DC)
{
pefree(obj, obj->is_persistent);
pefree(i_obj, i_obj->is_persistent);
}

static void php_memc_free_storage(php_memc_t *obj TSRMLS_DC)
static void php_memc_free_storage(php_memc_t *i_obj TSRMLS_DC)
{
if (obj->properties) {
zend_hash_destroy(obj->properties);
efree(obj->properties);
obj->properties = NULL;
if (i_obj->properties) {
zend_hash_destroy(i_obj->properties);
efree(i_obj->properties);
i_obj->properties = NULL;
}

php_memc_free(obj TSRMLS_CC);
if (!i_obj->is_persistent) {
php_memc_free(i_obj TSRMLS_CC);
}
}

zend_object_value php_memc_new(zend_class_entry *ce TSRMLS_DC)
{
zend_object_value retval;
php_memc_t *obj;
php_memc_t *i_obj;
zval *tmp;

obj = emalloc(sizeof(*obj));
memset(obj, 0, sizeof(*obj));
obj->ce = ce;
ALLOC_HASHTABLE(obj->properties);
zend_hash_init(obj->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(obj->properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
i_obj = emalloc(sizeof(*i_obj));
memset(i_obj, 0, sizeof(*i_obj));
i_obj->ce = ce;
ALLOC_HASHTABLE(i_obj->properties);
zend_hash_init(i_obj->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(i_obj->properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

retval.handle = zend_objects_store_put(obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC);
retval.handle = zend_objects_store_put(i_obj, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)php_memc_free_storage, NULL TSRMLS_CC);
retval.handlers = &std_object_handlers;

return retval;
}

ZEND_RSRC_DTOR_FUNC(php_memc_dtor)
{
FILE *fp;
fp = fopen("/tmp/a.log", "a");
if (rsrc->ptr) {
php_memc_t *i_obj = (php_memc_t *)rsrc->ptr;
fprintf(fp, "destroying list entry for '%s'\n", i_obj->plist_key);
php_memc_free(i_obj TSRMLS_CC);
rsrc->ptr = NULL;
}
fclose(fp);
}

int php_memc_list_entry(void)
{
return le_memc;
}

/* {{{ memcached_functions[] */
static zend_function_entry memcached_functions[] = {
{ NULL, NULL, NULL }
};
/* }}} */

/* {{{ memcached_class_methods */
static zend_function_entry memcached_class_methods[] = {
PHP_ME(Memcached, __construct, NULL, ZEND_ACC_PUBLIC)
{ NULL, NULL, NULL }
};
/* }}} */

/* {{{ memcached_module_entry
*/
zend_module_entry memcached_module_entry = {
STANDARD_MODULE_HEADER,
"memcached",
memcached_functions,
PHP_MINIT(memcached),
PHP_MSHUTDOWN(memcached),
NULL,
NULL,
PHP_MINFO(memcached),
PHP_MEMCACHED_VERSION,
STANDARD_MODULE_PROPERTIES
};
/* }}} */


/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(memcached)
Expand All @@ -134,7 +236,7 @@ PHP_MINIT_FUNCTION(memcached)

le_memc = zend_register_list_destructors_ex(NULL, php_memc_dtor, "Memcached persistent connection", module_number);

INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_functions);
INIT_CLASS_ENTRY(ce, "Memcached", memcached_class_methods);
memcached_ce = zend_register_internal_class(&ce TSRMLS_CC);
memcached_ce->create_object = php_memc_new;

Expand Down

0 comments on commit 730a024

Please sign in to comment.