Skip to content

Commit

Permalink
Extra settings and tunables (WIP)
Browse files Browse the repository at this point in the history
This should allow for finer grained next stage testing, fake subclassing
and 'composition'; and also
accidentally provide more backwards compatibility (and maybe even some
nice features)

Work in progress.
  • Loading branch information
mnunberg committed Jan 30, 2012
1 parent ab97851 commit 1839081
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 34 deletions.
18 changes: 18 additions & 0 deletions Async.xs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,25 @@ SV *
PLCBA_construct(pkg, options)
const char *pkg
AV *options


SV *
PLCBA__get_base_rv(self)
SV *self

PREINIT:
SV *ret;

CODE:
/*this returns the underlying 'base' object, for selected proxy-methods*/
if(!SvROK(self)) {
die("I was not given a reference");
}
RETVAL = newRV_inc(SvRV(self));

OUTPUT:
RETVAL

void
PLCBA_connect(self)
SV* self
Expand Down
150 changes: 142 additions & 8 deletions Client.xs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ wait_for_single_response(PLCB_t *object)
}


static void PLCB_cleanup(PLCB_t *object)
void plcb_cleanup(PLCB_t *object)
{
if(object->instance) {
libcouchbase_destroy(object->instance);
Expand Down Expand Up @@ -62,21 +62,26 @@ SV *PLCB_construct(const char *pkg, AV *options)

object->io_ops = io_ops;
plcb_ctor_conversion_opts(object, options);
plcb_ctor_init_common(object, instance);
plcb_ctor_init_common(object, instance, options);

libcouchbase_set_cookie(instance, object);

if(libcouchbase_connect(instance) == LIBCOUCHBASE_SUCCESS) {
libcouchbase_wait(instance);
}

plcb_setup_callbacks(object);

blessed_obj = newSV(0);
sv_setiv(newSVrv(blessed_obj, "Couchbase::Client"), PTR2IV(object));

if( (object->my_flags & PLCBf_NO_CONNECT) == 0 &&
(err = libcouchbase_connect(instance) == LIBCOUCHBASE_SUCCESS))
{
libcouchbase_wait(instance);
object->connected = 1;
}

return blessed_obj;
}


#define mk_instance_vars(sv, inst_name, obj_name) \
if(!SvROK(sv)) { die("self must be a reference"); } \
obj_name = NUM2PTR(PLCB_t*, SvIV(SvRV(sv))); \
Expand All @@ -87,6 +92,26 @@ SV *PLCB_construct(const char *pkg, AV *options)
return plcb_ret_blessed_rv(object, av);


int
PLCB_connect(SV *self)
{
libcouchbase_t instance;
libcouchbase_error_t err;
AV *retav;
PLCB_t *object;
mk_instance_vars(self, instance, object);
if(object->connected) {
return 1;
} else {
if( (err = libcouchbase_connect(instance)) == LIBCOUCHBASE_SUCCESS) {
object->connected = 1;
return 1;
}
}
return 0;
}


static SV *PLCB_set_common(SV *self,
SV *key, SV *value,
int storop,
Expand Down Expand Up @@ -369,6 +394,17 @@ static libcouchbase_storage_t PLCB_XS_setmap[] = {
LIBCOUCHBASE_PREPEND,
};

/*used for settings accessors*/
enum {
SETTINGS_ALIAS_BASE,
SETTINGS_ALIAS_COMPRESS,
SETTINGS_ALIAS_COMPRESS_COMPAT,
SETTINGS_ALIAS_SERIALIZE,
SETTINGS_ALIAS_CONVERT,
SETTINGS_ALIAS_DECONVERT,
SETTINGS_ALIAS_COMP_THRESHOLD
};

MODULE = Couchbase::Client PACKAGE = Couchbase::Client PREFIX = PLCB_

PROTOTYPES: DISABLE
Expand All @@ -382,12 +418,14 @@ PLCB_construct(pkg, options)
void
PLCB_DESTROY(self)
SV *self

CODE:
PLCB_t *object;
libcouchbase_t instance;
mk_instance_vars(self, instance, object);
PLCB_cleanup(object);

mk_instance_vars(self, instance, object);
plcb_cleanup(object);
Safefree(object);

SV *
PLCB_get(self, key)
Expand Down Expand Up @@ -575,6 +613,102 @@ PLCB_stats(self, ...)

OUTPUT:
RETVAL


IV
PLCB__settings(self, ...)
SV *self

ALIAS:
enable_compress = SETTINGS_ALIAS_COMPRESS_COMPAT
compression_settings = SETTINGS_ALIAS_COMPRESS
serialization_settings = SETTINGS_ALIAS_SERIALIZE
conversion_settings = SETTINGS_ALIAS_CONVERT
deconversion_settings = SETTINGS_ALIAS_DECONVERT
compress_threshold = SETTINGS_ALIAS_COMP_THRESHOLD

PREINIT:
int flag;
int new_value;

CODE:
switch(ix) {
case SETTINGS_ALIAS_COMPRESS:
case SETTINGS_ALIAS_COMPRESS_COMPAT:
flag = PLCBf_USE_COMPRESSION;
break;
case SETTINGS_ALIAS_SERIALIZE:
flag = PLCBf_USE_STORABLE;
break;
case SETTINGS_ALIAS_CONVERT:
flag = PLCBf_USE_STORABLE|PLCBf_USE_COMPRESSION;
break;
case SETTINGS_ALIAS_DECONVERT:
flag = PLCBf_NO_DECONVERT;
break;
case SETTINGS_ALIAS_COMP_THRESHOLD:
flag = PLCBf_COMPRESS_THRESHOLD;
break;
case 0:
die("This function should not be called directly. "
"use one of its aliases");
default:
die("Wtf?");
break;
}
if(items == 2) {
new_value = sv_2bool(ST(2));
} else if (items == 1) {
new_value = -1;
} else {
die("%s(self, [value])", GvNAME(GvCV(cv)));
}

if(!SvROK(self)) {
die("%s: I was given a bad object", GvNAME(GvCV(cv)));
}

RETVAL = plcb_convert_settings((PLCB_t*)SvRV(self), flag, new_value);

OUTPUT:
RETVAL


NV
PLCB_timeout(self, ...)
SV *self

PREINIT:
NV new_param;
uint32_t usecs;
NV ret;

libcouchbase_t instance;
PLCB_t *object;

CODE:

mk_instance_vars(self, instance, object);

ret = ((NV)(libcouchbase_get_timeout(instance))) / (1000*1000);

if(items == 2) {
new_param = SvNV(ST(1));
if(!new_param) {
warn("Cannot disable timeouts.");
XSRETURN_UNDEF;
}
usecs = new_param * (1000*1000);
libcouchbase_set_timeout(instance, usecs);
}

RETVAL = ret;

OUTPUT:
RETVAL

int
PLCB_connect(self)
SV *self

INCLUDE: Async.xs
2 changes: 1 addition & 1 deletion Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ WriteMakefile(

#these are needed for asynchronous tests and modules
'POE::Sugar::Attributes' => 0.02,
'POE' => 1.350,
'POE' => 1.312,
},
NEEDS_LINKING => 1,
OPTIMIZE => '-O0 -ggdb3',
Expand Down
26 changes: 25 additions & 1 deletion async.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,9 @@ PLCBA_construct(const char *pkg, AV *options)
die("Couldn't create instance!");
}

plcb_ctor_init_common(&async->base, instance);
plcb_ctor_init_common(&async->base, instance, options);
plcba_setup_callbacks(async);
async->base_rv = newRV_inc(newSViv(PTR2IV(&(async->base))));

blessed_obj = newSV(0);
sv_setiv(newSVrv(blessed_obj, pkg), PTR2IV(async));
Expand Down Expand Up @@ -445,3 +446,26 @@ PLCBA_connect(SV *self)
}
libcouchbase_wait(instance);
}

void
PLCBA_DESTROY(SV *self)
{
libcouchbase_t instance;
PLCBA_t *async;
PLCB_t *base;

#define _DEC_AND_NULLIFY(fld) \
if(async->fld) { SvREFCNT_dec(async->fld); async->fld = NULL; }

_DEC_AND_NULLIFY(base_rv);
_DEC_AND_NULLIFY(cv_evmod);
_DEC_AND_NULLIFY(cv_timermod);
_DEC_AND_NULLIFY(cv_err);
_DEC_AND_NULLIFY(cv_waitdone);

#undef _DEC_AND_NULLIFY

/*cleanup our base object. This will also cause the events to be destroyed*/
plcb_cleanup(&async->base);
Safefree(async);
}
5 changes: 2 additions & 3 deletions async_callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ error_callback(libcouchbase_t instance,
{
PLCBA_t *async;
dSP;
//warn("Error callback (err=%d, %s)",
//err, libcouchbase_strerror(instance, err));

async = (PLCBA_t*)libcouchbase_get_cookie(instance);
ENTER;
SAVETMPS;
Expand Down Expand Up @@ -167,4 +166,4 @@ plcba_setup_callbacks(PLCBA_t *async)
libcouchbase_set_error_callback(instance, error_callback);

libcouchbase_set_cookie(instance, async);
}
}
26 changes: 24 additions & 2 deletions async_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,31 @@ static void stop_event_loop(plcba_cbcio *cbcio)
call_sv(async->cv_waitdone, G_DISCARD|G_NOARGS);
}

static void destructor(plcba_cbcio *cbcio)
void destructor(plcba_cbcio *cbcio)
{
/*noop*/
/*free any remaining events*/
PLCBA_c_event *cevent;
PLCBA_t *async;
if(!cbcio) {
return;
}

if(! (async = cbcio->cookie) ) {
return; /*already freed*/
}

cevent = async->cevents;
while(cevent) {
if(cevent->next) {
cevent = cevent->next;
free(cevent->prev);
} else {
free(cevent);
cevent = NULL;
}
}
async->cevents = NULL;
cbcio->cookie = NULL;
}


Expand Down
37 changes: 36 additions & 1 deletion convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ SV* plcb_convert_retrieval(

input_sv = newSVpvn(data, data_len);

if(!plcb_storeflags_has_conversion(object, flags)) {
if(plcb_storeflags_has_conversion(object, flags) == 0
|| (object->my_flags & PLCBf_NO_DECONVERT) ) {
return input_sv;
}

Expand All @@ -185,4 +186,38 @@ SV* plcb_convert_retrieval(
}

return ret_sv;
}


/*this function provides an easy interface to fiddle with the module's settings*/
int plcb_convert_settings(PLCB_t *object, int flag, int new_value)
{
int ret;

if(flag == PLCBf_COMPRESS_THRESHOLD) {
/*this isn't really a flag value, but a proper integer*/
ret = object->compress_threshold;

object->compress_threshold = new_value >= 0
? new_value
: object->compress_threshold;
return ret;
}

ret = (object->my_flags & flag);


if(new_value > 0) {
object->my_flags |= flag;
} else {
if(new_value == 0) {
object->my_flags &= (~flag);
}
}

if(flag == PLCBf_NO_DECONVERT && new_value > 0) {
object->my_flags &= (~ (PLCBf_USE_COMPRESSION|PLCBf_USE_STORABLE));
}

return ret;
}
Loading

0 comments on commit 1839081

Please sign in to comment.