[Bps-public-commit] Prophet - A disconnected, replicated p2p database branch, master, updated. cd637399ea4769629eca14ccd2a98cb0e0c89f75
jesse
jesse at bestpractical.com
Sat Jan 17 17:36:19 EST 2009
The branch, master has been updated
via cd637399ea4769629eca14ccd2a98cb0e0c89f75 (commit)
from f1e567e3a25cf9c0e7ed3c059b9fdfd3b2b0cf55 (commit)
Summary of changes:
lib/Prophet/CLI/CollectionCommand.pm | 3 +-
lib/Prophet/Collection.pm | 16 +++------
lib/Prophet/Record.pm | 24 ++++++++++----
lib/Prophet/Replica/prophet.pm | 11 ++++++-
lib/Prophet/Replica/sqlite.pm | 57 +++++++++++++++++++++++++++------
5 files changed, 79 insertions(+), 32 deletions(-)
- Log -----------------------------------------------------------------
commit cd637399ea4769629eca14ccd2a98cb0e0c89f75
Author: Jesse Vincent <jesse at bestpractical.com>
Date: Sat Jan 17 17:35:32 2009 -0500
list_records now returns record objects rather than record ids
sqlite replicas now maintain a memory cache of records
records found through a search are precached.
diff --git a/lib/Prophet/CLI/CollectionCommand.pm b/lib/Prophet/CLI/CollectionCommand.pm
index 5a56fd5..017d747 100644
--- a/lib/Prophet/CLI/CollectionCommand.pm
+++ b/lib/Prophet/CLI/CollectionCommand.pm
@@ -10,8 +10,7 @@ sub get_collection_object {
type => { default => $self->type },
});
- my $record_class = $self->_get_record_object(type => $args{type});
- my $class = $record_class->collection_class;
+ my $class = $self->_get_record_object(type => $args{type})->collection_class;
Prophet::App->require($class);
my $records = $class->new(
diff --git a/lib/Prophet/Collection.pm b/lib/Prophet/Collection.pm
index ac159b6..2c92d86 100644
--- a/lib/Prophet/Collection.pm
+++ b/lib/Prophet/Collection.pm
@@ -71,25 +71,19 @@ returns true.
sub matching {
my $self = shift;
my $coderef = shift;
- return undef unless $self->handle->type_exists( type => $self->type );
+ # return undef unless $self->handle->type_exists( type => $self->type );
# find all items,
Carp::cluck unless defined $self->type;
- my $records = $self->handle->list_records( type => $self->type );
-
+ my $records = $self->handle->list_records( record_class => $self->record_class, type => $self->type );
# run coderef against each item;
# if it matches, add it to items
- for my $key (@$records) {
- my $record = $self->record_class->new( { app_handle => $self->app_handle, handle => $self->handle, type => $self->type } );
- $record->load( uuid => $key );
- if ( $coderef->($record) ) {
- $self->add_item($record);
- }
-
+ for my $record (@$records) {
+ $self->add_item($record) if ( $coderef->($record) );
}
- #return a count of items found
+ # XXX TODO return a count of items found
}
diff --git a/lib/Prophet/Record.pm b/lib/Prophet/Record.pm
index b8c7a3e..4215e35 100644
--- a/lib/Prophet/Record.pm
+++ b/lib/Prophet/Record.pm
@@ -69,6 +69,8 @@ class_has uuid_generator => (
default => sub { require Data::UUID; Data::UUID->new()}
);
+
+
=head1 METHODS
=head2 new { handle => Prophet::Replica, type => $type }
@@ -280,10 +282,21 @@ sub load {
return($self->luid) if ($self->luid);
}
- delete $self->{props};
return undef;
}
+# a private method to let collection search results instantiate records more quickly
+# (See Prophet::Replica::sqlite)
+sub _instantiate_from_hash {
+ my $self = shift;
+ my %args = ( uuid => undef, luid => undef, @_);
+ # we might not have a luid cheaply (see the prophet filesys backend)
+ $self->luid($args{'luid'}) if (defined $args{'luid'});
+ # We _Always_ have a luid
+ $self->uuid($args{'uuid'});
+ # XXX TODO - expect props as well
+}
+
sub loaded {
my $self = shift;
return $self->uuid ? 1 : 0;
@@ -324,7 +337,6 @@ sub set_props {
$self->canonicalize_props( $args{'props'} );
$self->validate_props( $args{'props'} ) || return undef;
- delete $self->{props};
$self->handle->set_record_props(
type => $self->type,
uuid => $self->uuid,
@@ -344,12 +356,10 @@ sub get_props {
confess "get_props called on a record that hasn't been loaded or created yet." if !$self->uuid;
- return $self->handle->get_record_props(
+ return $self->handle->get_record_props(
uuid => $self->uuid,
- type => $self->type
- ) || {};;
- return $self->{props} || {};
- #$self->{props} ||=
+ type => $self->type) || {};
+
}
=head2 prop $name
diff --git a/lib/Prophet/Replica/prophet.pm b/lib/Prophet/Replica/prophet.pm
index 9e2e6db..e79ef86 100644
--- a/lib/Prophet/Replica/prophet.pm
+++ b/lib/Prophet/Replica/prophet.pm
@@ -1001,8 +1001,9 @@ sub record_exists {
sub list_records {
my $self = shift;
- my %args = validate( @_ => { type => 1 } );
+ my %args = validate( @_ => { type => 1, record_class => 1 } );
+ return [] unless $self->type_exists( type => $args{type} );
#return just the filenames, which, File::Find::Rule doesn't seem capable of
my @record_uuids
= map { my @path = split( qr'/', $_ ); pop @path }
@@ -1012,10 +1013,18 @@ sub list_records {
)
);
return [
+ map {
+ my $record = $args{record_class}->new( { app_handle => $self->app_handle, handle => $self, type => $args{type} } );
+ $record->_instantiate_from_hash( uuid => $_);
+ $record;
+ }
grep {
$self->_record_cas_filename( type => $args{'type'}, uuid => $_ )
} @record_uuids
];
+
+
+
}
sub list_types {
diff --git a/lib/Prophet/Replica/sqlite.pm b/lib/Prophet/Replica/sqlite.pm
index af5fe8c..20b51bb 100644
--- a/lib/Prophet/Replica/sqlite.pm
+++ b/lib/Prophet/Replica/sqlite.pm
@@ -79,7 +79,7 @@ has '+resolution_db_handle' => (
},
);
-
+our $PROP_CACHE;
use constant scheme => 'sqlite';
use constant userdata_dir => 'userdata';
@@ -383,6 +383,7 @@ sub _delete_record_props_from_db {
my %args = validate( @_, { uuid => 1 } );
$self->dbh->do("DELETE FROM record_props where uuid = ?", {}, $args{uuid});
+ delete $PROP_CACHE->{$args{uuid}};
}
@@ -620,7 +621,10 @@ sub set_record_props {
my $inside_edit = $self->current_edit ? 1 : 0;
$self->begin_edit() unless ($inside_edit);
-
+
+ # clear the cache before computing the diffs. this is probably paranoid
+ delete $PROP_CACHE->{$args{uuid}};
+
my $old_props = $self->get_record_props( uuid => $args{'uuid'}, type => $args{'type'});
my %new_props = %$old_props;
@@ -634,6 +638,9 @@ sub set_record_props {
$self->_write_record_to_db( type => $args{'type'}, uuid => $args{'uuid'}, props => \%new_props);
+ # Clear the cache now that we've actually written out changed props
+ delete $PROP_CACHE->{$args{uuid}};
+
my $change = Prophet::Change->new( { record_type => $args{'type'}, record_uuid => $args{'uuid'}, change_type => 'update_file' });
$change->add_prop_change( name => $_, old => $old_props->{$_}, new => $args{props}->{$_}) for (keys %{$args{props}});
$self->current_edit->add_change( change => $change );
@@ -644,11 +651,15 @@ sub set_record_props {
sub get_record_props {
my $self = shift;
- my %args = (uuid => undef, type => undef, @_); # validate is slooow validate( @_, { uuid => 1, type => 1 } );
- my $sth = $self->dbh->prepare( "SELECT prop, value from record_props WHERE uuid = ?");
- $sth->execute($args{uuid});
- my $items = $sth->fetchall_arrayref;
- return {map { @$_ } @$items};
+ my %args = ( uuid => undef, type => undef, @_ )
+ ; # validate is slooow validate( @_, { uuid => 1, type => 1 } );
+ unless ( exists $PROP_CACHE->{ $args{uuid} } ) {
+ my $sth = $self->dbh->prepare("SELECT prop, value from record_props WHERE uuid = ?");
+ $sth->execute( $args{uuid} );
+ my $items = $sth->fetchall_arrayref;
+ $PROP_CACHE->{ $args{uuid} } = {map {@$_} @$items};
+ }
+ return $PROP_CACHE->{ $args{uuid} };
}
sub record_exists {
@@ -662,13 +673,37 @@ sub record_exists {
}
+=head2 list_records { type => $type }
+
+Returns a reference to a list of record objects for all records of type $type.
+
+Order is not guaranteed.
+
+=cut
+
sub list_records {
my $self = shift;
- my %args = validate( @_ => { type => 1 } );
-
- my $sth = $self->dbh->prepare("SELECT uuid from records WHERE type = ?");
+ my %args = validate( @_ => { type => 1, record_class => 1 } );
+ my @data;
+ my $sth = $self->dbh->prepare("SELECT records.uuid, records.luid, record_props.prop, record_props.value ".
+ "FROM records, record_props ".
+ "WHERE records.uuid = record_props.uuid AND records.type = ?");
$sth->execute($args{type});
- my @data = map { $_->[0]} @{ $sth->fetchall_arrayref};
+
+ my %found;
+
+ for (@{$sth->fetchall_arrayref}) {
+ $found{$_->[0]}->{luid} = $_->[1];
+ $found{$_->[0]}->{props}->{$_->[2]} = $_->[3];
+ }
+
+
+ for my $uuid (keys %found) {
+ my $record = $args{record_class}->new( { app_handle => $self->app_handle, handle => $self, type => $args{type} } );
+ $record->_instantiate_from_hash( uuid => $uuid, luid => $found{$uuid}->{luid});
+ #$PROP_CACHE->{$uuid} = $found{$uuid}->{props};
+ push @data, $record;
+ }
return \@data;
}
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list