You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2009/12/03 21:24:36 UTC
svn commit: r886907 - in /lucene/lucy/trunk: core/Lucy/Object/Obj.bp
core/Lucy/Object/Obj.c perl/lib/Lucy/Object/Obj.pm perl/t/binding/019-obj.t
Author: marvin
Date: Thu Dec 3 20:24:35 2009
New Revision: 886907
URL: http://svn.apache.org/viewvc?rev=886907&view=rev
Log:
Commit obj_serialize.diff from LUCY-81, adding the base routines for Lucy
object serialization and hooks for Perl Storable module.
Modified:
lucene/lucy/trunk/core/Lucy/Object/Obj.bp
lucene/lucy/trunk/core/Lucy/Object/Obj.c
lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm
lucene/lucy/trunk/perl/t/binding/019-obj.t
Modified: lucene/lucy/trunk/core/Lucy/Object/Obj.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/Obj.bp?rev=886907&r1=886906&r2=886907&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/Obj.bp (original)
+++ lucene/lucy/trunk/core/Lucy/Object/Obj.bp Thu Dec 3 20:24:35 2009
@@ -131,6 +131,21 @@
public abstract double
To_F64(Obj *self);
+ /** Serialize the object by writing to the supplied OutStream.
+ */
+ public void
+ Serialize(Obj *self, OutStream *outstream);
+
+ /** Inflate an object by reading the serialized form from the instream.
+ * The assumption is that the object has been allocated, assigned a
+ * refcount and a vtable, but that everything else is uninitialized.
+ *
+ * Implementations should also be prepared to handle NULL as an argument,
+ * in which case they should create the object from nothing.
+ */
+ public incremented Obj*
+ Deserialize(Obj *self, InStream *instream);
+
/** Return a representation of the object using only scalars, hashes, and
* arrays. Some implementations support JSON serialization via Dump() and
* its companion method, Load(); for others, Dump() is only a debugging
Modified: lucene/lucy/trunk/core/Lucy/Object/Obj.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/Obj.c?rev=886907&r1=886906&r2=886907&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/Obj.c (original)
+++ lucene/lucy/trunk/core/Lucy/Object/Obj.c Thu Dec 3 20:24:35 2009
@@ -12,6 +12,8 @@
#include "Lucy/Object/Err.h"
#include "Lucy/Object/Hash.h"
#include "Lucy/Object/VTable.h"
+#include "Lucy/Store/InStream.h"
+#include "Lucy/Store/OutStream.h"
#include "Lucy/Util/Memory.h"
Obj*
@@ -54,6 +56,35 @@
return (self == other);
}
+void
+Obj_serialize(Obj *self, OutStream *outstream)
+{
+ CharBuf *class_name = Obj_Get_Class_Name(self);
+ size_t size = CB_Get_Size(class_name);
+ OutStream_Write_C32(outstream, size);
+ OutStream_Write_Bytes(outstream, CB_Get_Ptr8(class_name), size);
+}
+
+Obj*
+Obj_deserialize(Obj *self, InStream *instream)
+{
+ size_t size = InStream_Read_C32(instream);
+ CharBuf *class_name = CB_new(size);
+ CB_Set_Size(class_name, size);
+ InStream_Read_Bytes(instream, CB_Get_Ptr8(class_name), size);
+ if (!self) {
+ VTable *vtable = VTable_singleton(class_name, OBJ);
+ self = VTable_Make_Obj(vtable);
+ }
+ else {
+ CharBuf *my_class = VTable_Get_Name(self->vtable);
+ if (!CB_Equals(class_name, (Obj*)my_class))
+ THROW(ERR, "Class mismatch: %o %o", class_name, my_class);
+ }
+ DECREF(class_name);
+ return Obj_init(self);
+}
+
CharBuf*
Obj_to_string(Obj *self)
{
Modified: lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm?rev=886907&r1=886906&r2=886907&view=diff
==============================================================================
--- lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm (original)
+++ lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm Thu Dec 3 20:24:35 2009
@@ -21,6 +21,78 @@
OUTPUT: RETVAL
void
+STORABLE_freeze(self, ...)
+ lucy_Obj *self;
+PPCODE:
+{
+ CHY_UNUSED_VAR(self);
+ if (items < 2 || !SvTRUE(ST(1))) {
+ SV *retval;
+ lucy_ByteBuf *serialized_bb;
+ lucy_RAMFileHandle *file_handle = lucy_RAMFH_open(NULL,
+ LUCY_FH_WRITE_ONLY | LUCY_FH_CREATE, NULL);
+ lucy_OutStream *target = lucy_OutStream_open((lucy_Obj*)file_handle);
+
+ Lucy_Obj_Serialize(self, target);
+
+ Lucy_OutStream_Close(target);
+ serialized_bb = Lucy_RAMFile_Get_Contents(
+ Lucy_RAMFH_Get_File(file_handle));
+ retval = XSBind_bb_to_sv(serialized_bb);
+ LUCY_DECREF(file_handle);
+ LUCY_DECREF(target);
+
+ if (SvCUR(retval) == 0) { /* Thwart Storable bug */
+ THROW(LUCY_ERR, "Calling serialize produced an empty string");
+ }
+ ST(0) = sv_2mortal(retval);
+ XSRETURN(1);
+ }
+}
+
+=begin comment
+
+Calls deserialize(), and copies the object pointer. Since deserialize is an
+abstract method, it will confess() unless implemented.
+
+=end comment
+=cut
+
+void
+STORABLE_thaw(blank_obj, cloning, serialized_sv)
+ SV *blank_obj;
+ SV *cloning;
+ SV *serialized_sv;
+PPCODE:
+{
+ char *class_name = HvNAME(SvSTASH(SvRV(blank_obj)));
+ lucy_ZombieCharBuf klass
+ = lucy_ZCB_make_str(class_name, strlen(class_name));
+ lucy_VTable *vtable = (lucy_VTable*)lucy_VTable_singleton(
+ (lucy_CharBuf*)&klass, NULL);
+ STRLEN len;
+ char *ptr = SvPV(serialized_sv, len);
+ lucy_ViewByteBuf *contents = lucy_ViewBB_new(ptr, len);
+ lucy_RAMFile *ram_file = lucy_RAMFile_new((lucy_ByteBuf*)contents, true);
+ lucy_RAMFileHandle *file_handle
+ = lucy_RAMFH_open(NULL, LUCY_FH_READ_ONLY, ram_file);
+ lucy_InStream *instream = lucy_InStream_open((lucy_Obj*)file_handle);
+ lucy_Obj *self = Lucy_VTable_Foster_Obj(vtable, blank_obj);
+ lucy_Obj *deserialized = Lucy_Obj_Deserialize(self, instream);
+
+ CHY_UNUSED_VAR(cloning);
+ LUCY_DECREF(contents);
+ LUCY_DECREF(ram_file);
+ LUCY_DECREF(file_handle);
+ LUCY_DECREF(instream);
+
+ /* Catch bad deserialize() override. */
+ if (deserialized != self) {
+ THROW(LUCY_ERR, "Error when deserializing obj of class %o", &klass);
+ }
+}
+
+void
DESTROY(self)
lucy_Obj *self;
PPCODE:
@@ -52,6 +124,8 @@
Mimic
Equals
Hash_Code
+ Serialize
+ Deserialize
Destroy
)
],
Modified: lucene/lucy/trunk/perl/t/binding/019-obj.t
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/t/binding/019-obj.t?rev=886907&r1=886906&r2=886907&view=diff
==============================================================================
--- lucene/lucy/trunk/perl/t/binding/019-obj.t (original)
+++ lucene/lucy/trunk/perl/t/binding/019-obj.t Thu Dec 3 20:24:35 2009
@@ -1,7 +1,7 @@
use strict;
use warnings;
-use Test::More tests => 16;
+use Test::More tests => 19;
package TestObj;
use base qw( Lucy::Object::Obj );
@@ -15,9 +15,29 @@
my $self = shift;
return "STRING: " . $self->SUPER::to_string;
}
+
+ sub serialize {
+ my ( $self, $outstream ) = @_;
+ $self->SUPER::serialize($outstream);
+ $outstream->write_string("zowie");
+ }
+
+ sub deserialize {
+ my ( $self, $instream ) = @_;
+ $self = $self->SUPER::deserialize($instream);
+ $instream->read_string;
+ return $self;
+ }
+}
+
+package BadSerialize;
+use base qw( Lucy::Object::Obj );
+{
+ sub serialize { }
}
package main;
+use Storable qw( freeze thaw );
ok( defined $TestObj::version,
"Using base class should grant access to "
@@ -39,8 +59,8 @@
ok( $object->is_a("Lucy::Object::Obj"), "custom is_a correct" );
ok( !$object->is_a("Lucy::Object"), "custom is_a too long" );
ok( !$object->is_a("Lucy"), "custom is_a substring" );
-ok( !$object->is_a(""), "custom is_a blank" );
-ok( !$object->is_a("thing"), "custom is_a wrong" );
+ok( !$object->is_a(""), "custom is_a blank" );
+ok( !$object->is_a("thing"), "custom is_a wrong" );
eval { my $another_obj = TestObj->new( kill_me_now => 1 ) };
like( $@, qr/kill_me_now/, "reject bad param" );
@@ -60,7 +80,22 @@
is( $object->get_refcount, 1,
"correct refcount after destruction of ref" );
+my $copy = thaw( freeze($object) );
+is( ref($copy), ref($object), "freeze/thaw" );
+
$object = SonOfTestObj->new;
like( $object->to_string, qr/STRING:.*?SonOfTestObj/,
"overridden XS bindings can be called via SUPER" );
+my $frozen = freeze($object);
+my $dupe = thaw($frozen);
+is( ref($dupe), ref($object), "override serialize/deserialize" );
+
+SKIP: {
+ skip( "Invalid serialization causes leaks", 1 ) if $ENV{LUCY_VALGRIND};
+ my $bad = BadSerialize->new;
+ eval { my $froze = freeze($bad); };
+ like( $@, qr/empty/i,
+ "Don't allow subclasses to perform invalid serialization" );
+}
+