Implement Doc's serialization entirely in XS.
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/04ac681c Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/04ac681c Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/04ac681c Branch: refs/heads/master Commit: 04ac681c5de6ae3dc736400e7160f78ee9ddcdb8 Parents: 2da34a6 Author: Marvin Humphrey <[email protected]> Authored: Wed Nov 14 19:52:17 2012 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Fri Nov 16 16:54:16 2012 -0800 ---------------------------------------------------------------------- perl/lib/Lucy.pm | 19 +---------- perl/xs/Lucy/Document/Doc.c | 67 ++++++++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/04ac681c/perl/lib/Lucy.pm ---------------------------------------------------------------------- diff --git a/perl/lib/Lucy.pm b/perl/lib/Lucy.pm index 9481d47..537572e 100644 --- a/perl/lib/Lucy.pm +++ b/perl/lib/Lucy.pm @@ -107,28 +107,11 @@ sub error {$Clownfish::Err::error} package Lucy::Document::Doc; our $VERSION = '0.003000'; $VERSION = eval $VERSION; - use Storable qw( nfreeze thaw ); - use bytes; - no bytes; + use Storable (); # Needed by serialize/deserialize. use overload fallback => 1, '%{}' => \&get_fields; - - sub serialize_fields { - my ( $self, $outstream ) = @_; - my $buf = nfreeze( $self->get_fields ); - $outstream->write_c32( bytes::length($buf) ); - $outstream->print($buf); - } - - sub deserialize_fields { - my ( $self, $instream ) = @_; - my $len = $instream->read_c32; - my $buf; - $instream->read( $buf, $len ); - $self->set_fields( thaw($buf) ); - } } { http://git-wip-us.apache.org/repos/asf/lucy/blob/04ac681c/perl/xs/Lucy/Document/Doc.c ---------------------------------------------------------------------- diff --git a/perl/xs/Lucy/Document/Doc.c b/perl/xs/Lucy/Document/Doc.c index 3dc6036..b42231e 100644 --- a/perl/xs/Lucy/Document/Doc.c +++ b/perl/xs/Lucy/Document/Doc.c @@ -17,7 +17,6 @@ #define C_LUCY_DOC #include "XSBind.h" #include "Lucy/Document/Doc.h" -#include "Clownfish/Host.h" #include "Lucy/Store/InStream.h" #include "Lucy/Store/OutStream.h" #include "Clownfish/Util/Memory.h" @@ -64,19 +63,75 @@ lucy_Doc_store(lucy_Doc *self, const lucy_CharBuf *field, lucy_Obj *value) { SvREFCNT_dec(key_sv); } +static SV* +S_nfreeze_fields(lucy_Doc *self) { + dSP; + ENTER; + SAVETMPS; + EXTEND(SP, 1); + PUSHMARK(SP); + mPUSHs((SV*)newRV_inc((SV*)self->fields)); + PUTBACK; + call_pv("Storable::nfreeze", G_SCALAR); + SPAGAIN; + SV *frozen = POPs; + SvREFCNT_inc(frozen); + PUTBACK; + FREETMPS; + LEAVE; + return frozen; +} + void lucy_Doc_serialize(lucy_Doc *self, lucy_OutStream *outstream) { Lucy_OutStream_Write_C32(outstream, self->doc_id); - lucy_Host_callback(self, "serialize_fields", 1, - CFISH_ARG_OBJ("outstream", outstream)); + SV *frozen = S_nfreeze_fields(self); + STRLEN len; + char *buf = SvPV(frozen, len); + Lucy_OutStream_Write_C64(outstream, len); + Lucy_OutStream_Write_Bytes(outstream, buf, len); + SvREFCNT_dec(frozen); +} + +static HV* +S_thaw_fields(lucy_InStream *instream) { + // Read frozen data into an SV buffer. + size_t len = (size_t)Lucy_InStream_Read_C64(instream); + SV *buf_sv = newSV(len + 1); + SvPOK_on(buf_sv); + SvCUR_set(buf_sv, len); + char *buf = SvPVX(buf_sv); + Lucy_InStream_Read_Bytes(instream, buf, len); + + // Call back to Storable to thaw the frozen hash. + dSP; + ENTER; + SAVETMPS; + EXTEND(SP, 1); + PUSHMARK(SP); + mPUSHs(buf_sv); + PUTBACK; + call_pv("Storable::thaw", G_SCALAR); + SPAGAIN; + SV *frozen = POPs; + if (frozen && !SvROK(frozen)) { + CFISH_THROW(CFISH_ERR, "thaw failed"); + } + HV *fields = (HV*)SvRV(frozen); + SvREFCNT_inc((SV*)fields); + PUTBACK; + FREETMPS; + LEAVE; + + return fields; } lucy_Doc* lucy_Doc_deserialize(lucy_Doc *self, lucy_InStream *instream) { int32_t doc_id = (int32_t)Lucy_InStream_Read_C32(instream); - lucy_Doc_init(self, NULL, doc_id); - lucy_Host_callback(self, "deserialize_fields", 1, - CFISH_ARG_OBJ("instream", instream)); + HV *fields = S_thaw_fields(instream); + lucy_Doc_init(self, fields, doc_id); + SvREFCNT_dec(fields); return self; }
