File Coverage

blib/lib/KiokuDB.pm
Criterion Covered Total %
statement 2 4 50.0
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 4 6 66.6


line stmt bran cond sub pod time code
1             package KiokuDB;
2             BEGIN {
3 7     7   226686 $KiokuDB::AUTHORITY = 'cpan:NUFFIN';
4             }
5             $KiokuDB::VERSION = '0.57';
6 7     7   13075 use Moose;
  0            
  0            
7             # ABSTRACT: Object Graph storage engine
8              
9             use constant SERIAL_IDS => not not our $SERIAL_IDS;
10              
11             use KiokuDB::Backend;
12             use KiokuDB::Collapser;
13             use KiokuDB::Linker;
14             use KiokuDB::LiveObjects;
15             use KiokuDB::TypeMap;
16             use KiokuDB::TypeMap::Shadow;
17             use KiokuDB::TypeMap::Resolver;
18             use KiokuDB::Stream::Objects;
19              
20             use Moose 2.0000 ();
21             use Moose::Util qw(does_role);
22              
23             use Hash::Util::FieldHash::Compat qw(idhash);
24             use Carp qw(croak);
25             use Try::Tiny;
26              
27             use namespace::clean 0.08 -except => [qw(meta SERIAL_IDS)];
28              
29             # with qw(KiokuDB::Role::API); # moved lower
30              
31             no warnings 'recursion';
32              
33             our $REQUIRED_CMD_VERSION = "0.03";
34             sub cmd_is_up_to_date {
35             require KiokuDB::Cmd;
36             try { KiokuDB::Cmd->VERSION($REQUIRED_CMD_VERSION); 1 };
37             }
38              
39              
40             sub connect {
41             my ( $class, $dsn, @args ) = @_;
42              
43             if ( -d $dsn || $dsn =~ /\.yml$/ ) {
44             return $class->configure($dsn, @args);
45             } else {
46             require KiokuDB::Util;
47             return $class->new( backend => KiokuDB::Util::dsn_to_backend($dsn, @args), @args );
48             }
49             }
50              
51             sub configure {
52             my ( $class, $base, @args ) = @_;
53              
54             require Path::Class;
55             $base = Path::Class::dir($base) unless blessed $base;
56              
57             require KiokuDB::Util;
58             my $config = KiokuDB::Util::load_config($base);
59              
60             my $backend = KiokuDB::Util::config_to_backend( $config, base => $base, @args );
61              
62             # FIXME gin extractor, typemap, etc
63             $class->new( %$config, @args, backend => $backend );
64             }
65              
66             has typemap => (
67             does => "KiokuDB::Role::TypeMap",
68             is => "ro",
69             );
70              
71             has allow_class_builders => (
72             isa => "Bool|HashRef",
73             is => "ro",
74             );
75              
76             has [qw(allow_classes allow_bases)] => (
77             isa => "ArrayRef[Str]",
78             is => "ro",
79             );
80              
81             has merged_typemap => (
82             does => "KiokuDB::Role::TypeMap",
83             is => "ro",
84             lazy_build => 1,
85             );
86              
87             sub _find_default_typemaps {
88             my $self = shift;
89              
90             my $b = $self->backend;
91              
92             my @typemaps;
93             if ( $b->can("default_typemap") ) {
94             push @typemaps, $b->default_typemap;
95             }
96              
97              
98             if ( $b->can("serializer") and $b->serializer->can("default_typemap") ) {
99             push @typemaps, $b->serializer->default_typemap;
100             }
101              
102             return @typemaps;
103             }
104              
105             sub _build_merged_typemap {
106             my $self = shift;
107              
108             my @typemaps;
109              
110             if ( my $typemap = $self->typemap ) {
111             push @typemaps, $typemap;
112             }
113              
114             if ( my $classes = $self->allow_classes ) {
115             require KiokuDB::TypeMap::Entry::Naive;
116              
117             push @typemaps, KiokuDB::TypeMap->new(
118             entries => { map { $_ => KiokuDB::TypeMap::Entry::Naive->new } @$classes },
119             );
120             }
121              
122             if ( my $classes = $self->allow_bases ) {
123             require KiokuDB::TypeMap::Entry::Naive;
124              
125             push @typemaps, KiokuDB::TypeMap->new(
126             isa_entries => { map { $_ => KiokuDB::TypeMap::Entry::Naive->new } @$classes },
127             );
128             }
129              
130             if ( my $opts = $self->allow_class_builders ) {
131             require KiokuDB::TypeMap::ClassBuilders;
132             push @typemaps, KiokuDB::TypeMap::ClassBuilders->new( ref $opts ? %$opts : () );
133             }
134              
135             push @typemaps, $self->_find_default_typemaps;
136              
137             if ( not @typemaps ) {
138             return KiokuDB::TypeMap->new;
139             } elsif ( @typemaps == 1 ) {
140             return $typemaps[0];
141             } else {
142             return KiokuDB::TypeMap::Shadow->new( typemaps => \@typemaps );
143             }
144             }
145              
146             has check_class_versions => (
147             isa => "Bool",
148             is => "ro",
149             default => 0,
150             );
151              
152             has class_version_table => (
153             isa => "HashRef[HashRef[Str|CodeRef|HashRef]]",
154             is => "ro",
155             default => sub { return {} },
156             );
157              
158             has typemap_resolver => (
159             isa => "KiokuDB::TypeMap::Resolver",
160             is => "ro",
161             lazy_build => 1,
162             );
163              
164             sub _build_typemap_resolver {
165             my $self = shift;
166              
167             KiokuDB::TypeMap::Resolver->new(
168             typemap => $self->merged_typemap,
169             fallback_entry => KiokuDB::TypeMap::Entry::MOP->new(
170             class_version_table => $self->class_version_table,
171             check_class_versions => $self->check_class_versions,
172             ),
173             );
174             }
175              
176             has live_objects => (
177             isa => "KiokuDB::LiveObjects",
178             is => "ro",
179             coerce => 1,
180             lazy => 1,
181             builder => "_build_live_objects", # lazy_build => 1 sets clearer
182             handles => {
183             clear_live_objects => "clear",
184             new_scope => "new_scope",
185             object_to_id => "object_to_id",
186             objects_to_ids => "objects_to_ids",
187             id_to_object => "id_to_object",
188             ids_to_objects => "ids_to_objects",
189             id_in_storage => "id_in_storage",
190             object_in_storage => "object_in_storage",
191             },
192             );
193              
194             sub _build_live_objects { KiokuDB::LiveObjects->new }
195              
196             has collapser => (
197             isa => "KiokuDB::Collapser",
198             is => "ro",
199             lazy_build => 1,
200             );
201              
202             sub _build_collapser {
203             my $self = shift;
204              
205             KiokuDB::Collapser->new(
206             backend => $self->backend,
207             live_objects => $self->live_objects,
208             typemap_resolver => $self->typemap_resolver,
209             );
210             }
211              
212             has backend => (
213             does => "KiokuDB::Backend",
214             is => "ro",
215             required => 1,
216             coerce => 1,
217             );
218              
219             has linker_queue => (
220             isa => "Bool",
221             is => "ro",
222             default => 1,
223             );
224              
225             has linker => (
226             isa => "KiokuDB::Linker",
227             is => "ro",
228             lazy_build => 1,
229             );
230              
231             sub _build_linker {
232             my $self = shift;
233              
234             KiokuDB::Linker->new(
235             backend => $self->backend,
236             live_objects => $self->live_objects,
237             typemap_resolver => $self->typemap_resolver,
238             queue => $self->linker_queue,
239             );
240             }
241              
242             sub BUILD {
243             my $self = shift;
244              
245             my $backend = $self->backend;
246              
247             $backend->register_handle($self) if $backend->can("register_handle");
248             }
249              
250             with qw(KiokuDB::Role::API);
251              
252             sub exists {
253             my ( $self, @ids ) = @_;
254              
255             return unless @ids;
256              
257             my @exists = map { $_ ? 1 : '' } $self->backend->exists(@ids);
258             return ( @ids == 1 ? $exists[0] : @exists );
259              
260             # FIXME fix for in_storage etc
261              
262             if ( @ids == 1 ) {
263             my $id = $ids[0];
264              
265             if ( my $entry = $self->live_objects->id_to_entry($ids[0]) ) {
266             return not $entry->deleted;
267             }
268              
269             if ( my $entry = ($self->backend->exists($id))[0] ) { # backend returns a list
270             if ( ref $entry ) {
271             $self->live_objects->register_entry( $id => $entry, in_storage => 1 );
272             }
273              
274             return 1;
275             } else {
276             return '';
277             }
278             } else {
279             my ( %entries, %exists );
280              
281             @entries{@ids} = $self->live_objects->ids_to_entries(@ids);
282              
283             my @missing;
284              
285             foreach my $id ( @ids ) {
286             if ( ref ( my $entry = $entries{$id} ) ) {
287             $exists{$id} = not $entry->deleted;
288             } else {
289             push @missing, $id;
290             }
291             }
292              
293             if ( @missing ) {
294             my @values = $self->backend->exists(@missing);
295              
296             if ( my @entries = grep { ref } @values ) {
297             $self->live_objects->register_entry( $_->id => $_, in_storage => 1 ) for @entries;
298             }
299              
300             @exists{@missing} = map { ref($_) ? 1 : $_ } @values;
301             }
302              
303             return @ids == 1 ? $exists{$ids[0]} : @exists{@ids};
304             }
305             }
306              
307             sub lookup {
308             my ( $self, @ids ) = @_;
309              
310             return unless @ids;
311              
312             my $linker = $self->linker;
313              
314             try {
315             my @objects = $linker->get_or_load_objects(@ids);
316              
317             if ( @ids == 1 ) {
318             return $objects[0];
319             } else {
320             return @objects;
321             }
322             } catch {
323             return if blessed($_)
324             and $_->isa("KiokuDB::Error::MissingObjects")
325             and $_->missing_ids_are(@ids);
326              
327             die $_;
328             };
329             }
330              
331             sub search {
332             my ( $self, @args ) = @_;
333              
334             if ( @args == 1 && ref $args[0] eq 'HASH' ) {
335             return $self->simple_search(@args);
336             } else {
337             return $self->backend_search(@args);
338             }
339             }
340              
341             sub _load_entry_stream {
342             my ( $self, $stream ) = @_;
343              
344             KiokuDB::Stream::Objects->new(
345             directory => $self,
346             entry_stream => $stream,
347             );
348             }
349              
350             sub simple_search {
351             my ( $self, @args ) = @_;
352              
353             my $b = $self->backend;
354              
355             my $entries = $b->simple_search( @args, live_objects => $self->live_objects );
356              
357             my $objects = $self->_load_entry_stream($entries);
358              
359             return $b->simple_search_filter($objects, @args);
360             }
361              
362             sub backend_search {
363             my ( $self, @args ) = @_;
364              
365             my $b = $self->backend;
366              
367             my $entries = $b->search( @args, live_objects => $self->live_objects );
368              
369             my $objects = $self->_load_entry_stream($entries);
370              
371             return $b->search_filter($objects, @args);
372             }
373              
374             sub root_set {
375             my ( $self ) = @_;
376              
377             $self->_load_entry_stream( $self->backend->root_entries( live_objects => $self->live_objects ) );
378             }
379              
380             sub all_objects {
381             my ( $self ) = @_;
382              
383             $self->_load_entry_stream( $self->backend->all_entries( live_objects => $self->live_objects ) );
384             }
385              
386             sub grep {
387             my ( $self, $filter ) = @_;
388              
389             my $stream = $self->root_set;
390              
391             $stream->filter(sub { [ grep { $filter->($_) } @$_ ] });
392             }
393              
394             sub scan {
395             my ( $self, $filter ) = @_;
396              
397             my $stream = $self->root_set;
398              
399             while ( my $items = $stream->next ) {
400             foreach my $item ( @$items ) {
401             $item->$filter();
402             }
403             }
404             }
405              
406             sub _parse_args {
407             my ( $self, @args ) = @_;
408              
409             my ( %ids, @ret );
410              
411             while ( @args ) {
412             my $next = shift @args;
413              
414             unless ( ref $next ) {
415             my $obj = shift @args;
416              
417             $ids{$next} = $obj;
418              
419             push @ret, $obj;
420             } else {
421             push @ret, $next;
422             }
423             }
424              
425             return ( \%ids, @ret );
426             }
427              
428             sub _register {
429             my ( $self, @args ) = @_;
430              
431             my ( $ids, @objs ) = $self->_parse_args(@args);
432              
433             if ( scalar keys %$ids ) {
434             $self->live_objects->insert(%$ids);
435             }
436              
437             return @objs;
438             }
439              
440             sub refresh {
441             my ( $self, @objects ) = @_;
442              
443             return unless @objects;
444              
445             my $l = $self->live_objects;
446              
447             croak "Object not in storage"
448             if grep { not $l->object_in_storage($_) } @objects;
449              
450             $self->linker->refresh_objects(@objects);
451              
452             if ( defined wantarray ) {
453             if ( @objects == 1 ) {
454             return $objects[0];
455             } else {
456             return @objects;
457             }
458             }
459             }
460              
461             sub _store {
462             my ( $self, $root, @args ) = @_;
463              
464             my @objects = $self->_register(@args);
465              
466             return unless @objects;
467              
468             $self->store_objects( root_set => $root, objects => \@objects );
469             }
470              
471             sub store { shift->_store( 1, @_ ) }
472             sub store_nonroot { shift->_store( 0, @_ ) }
473              
474             sub _insert {
475             my ( $self, $root, @args ) = @_;
476              
477             my @objects = $self->_register(@args);
478              
479             return unless @objects;
480              
481             my $l = $self->live_objects;
482              
483             # FIXME make optional?
484             if ( my @in_storage = grep { $l->object_in_storage($_) } @objects ) {
485             croak "Objects already in database: @in_storage";
486             }
487              
488             $self->store_objects( root_set => $root, only_in_storage => 1, objects => \@objects );
489              
490             # return IDs only for unknown objects
491             if ( defined wantarray ) {
492             return $self->live_objects->objects_to_ids(@objects);
493             }
494             }
495              
496             sub insert { shift->_insert( 1, @_ ) }
497             sub insert_nonroot { shift->_insert( 0, @_ ) }
498              
499             sub update {
500             my ( $self, @args ) = @_;
501              
502             my @objects = $self->_register(@args);
503              
504             my $l = $self->live_objects;
505              
506             croak "Object not in storage"
507             if grep { not $l->object_in_storage($_) } @objects;
508              
509             $self->store_objects( shallow => 1, only_known => 1, objects => \@objects );
510             }
511              
512             sub deep_update {
513             my ( $self, @args ) = @_;
514              
515             my @objects = $self->_register(@args);
516              
517             my $l = $self->live_objects;
518              
519             croak "Object not in storage"
520             if grep { not $l->object_in_storage($_) } @objects;
521              
522             $self->store_objects( only_known => 1, objects => \@objects );
523             }
524              
525             sub _derive_entries {
526             my ( $self, %args ) = @_;
527              
528             my @objects = @{ $args{objects} };
529              
530             my $l = $self->live_objects;
531              
532             my @entries = $l->objects_to_entries( @{ $args{objects} } );
533              
534             my $method = $args{method} || "derive";
535              
536             my $derive_args = $args{args} || [];
537              
538             my @args = ref($derive_args) eq 'HASH' ? %$derive_args : @$derive_args;
539              
540             $l->update_entries(map {
541             my $obj = shift @objects;
542             $obj => $_->$method( object => $obj, @args );
543             } @entries);
544             }
545              
546             sub set_root {
547             my ( $self, @objects ) = @_;
548              
549             $self->_derive_entries( objects => \@objects, args => { root => 1 } );
550             }
551              
552             sub unset_root {
553             my ( $self, @objects ) = @_;
554              
555             $self->_derive_entries( objects => \@objects, args => { root => 0 } );
556             }
557              
558             sub is_root {
559             my ( $self, @objects ) = @_;
560              
561             my $l = $self->live_objects;
562              
563             my @is_root = map { $l->id_in_root_set($_) } $l->objects_to_ids(@objects);
564              
565             return @objects == 1 ? $is_root[0] : @is_root;
566             }
567              
568             sub store_objects {
569             my ( $self, %args ) = @_;
570              
571             my $objects = $args{objects};
572              
573             my ( $buffer, @ids ) = $self->collapser->collapse(%args);
574              
575             $buffer->imply_root(@ids) if $args{root_set};
576              
577             $buffer->commit($self->backend);
578              
579             if ( @$objects == 1 ) {
580             return $ids[0];
581             } else {
582             return @ids;
583             }
584             }
585              
586             sub delete {
587             my ( $self, @ids_or_objects ) = @_;
588              
589             return unless @ids_or_objects;
590              
591             my $l = $self->live_objects;
592              
593             my @ids = grep { not ref } @ids_or_objects;
594             my @objects = grep { ref } @ids_or_objects;
595              
596             # FIXME requires 'deleted' flag or somesuch
597             unless ( $l->keep_entries ) {
598             push @ids, $l->objects_to_ids(@objects);
599             @objects = ();
600             }
601              
602             my @entries;
603              
604             for ( @objects ) {
605             croak "Object not in storage" unless $l->object_in_storage($_);
606             }
607              
608             push @entries, $l->objects_to_entries(@objects) if @objects;
609              
610             @entries = map { $_->deletion_entry } @entries;
611              
612             # FIXME ideally if ID is pointing at a live object we should use its entry
613             #push @entries, $l->ids_to_entries(@ids) if @ids;
614             my @ids_or_entries = ( @entries, @ids );
615              
616             if ( my @new_entries = grep { ref } $self->backend->delete(@ids_or_entries) ) {
617             push @entries, @new_entries;
618             }
619              
620             $l->remove(@ids_or_objects);
621             }
622              
623             sub scoped_txn {
624             my ( $self, $body, @args ) = @_;
625              
626             $self->txn_do(body => $body, scope => 1, @args);
627             }
628              
629             sub txn_do {
630             my ( $self, @args ) = @_;
631              
632             unshift @args, 'body' if @args % 2 == 1;
633              
634             my %args = @args;
635              
636             my $code = delete $args{body};
637              
638             my $s = $args{scope} && $self->new_scope;
639              
640             my $backend = $self->backend;
641              
642             if ( $backend->can("txn_do") ) {
643             my $scope = $self->live_objects->new_txn;
644              
645             my $rollback = $args{rollback};
646             $args{rollback} = sub { $scope && $scope->rollback; $rollback && $rollback->() };
647              
648             return $backend->txn_do( $code, %args );
649             } else {
650             return $code->();
651             }
652             }
653              
654             sub directory {
655             my $self = shift;
656             return $self;
657             }
658              
659             __PACKAGE__->meta->make_immutable;
660              
661             __PACKAGE__
662              
663             __END__
664              
665             =pod
666              
667             =encoding UTF-8
668              
669             =head1 NAME
670              
671             KiokuDB - Object Graph storage engine
672              
673             =head1 VERSION
674              
675             version 0.57
676              
677             =head1 SYNOPSIS
678              
679             use KiokuDB;
680              
681             # use a DSN
682             my $d = KiokuDB->connect( $dsn, %args );
683              
684             # or manually instantiate a backend
685             my $d = KiokuDB->new(
686             backend => KiokuDB::Backend::Files->new(
687             dir => "/tmp/foo",
688             serializer => "yaml",
689             ),
690             );
691              
692              
693             # create a scope object
694             my $s = $d->new_scope;
695              
696              
697             # takes a snapshot of $some_object
698             my $uuid = $d->store($some_object);
699              
700             # or with a custom ID:
701             $d->store( $id => $some_object ); # $id can be any string
702              
703              
704             # retrieve by ID
705             my $some_object = $d->lookup($uuid);
706              
707              
708              
709             # some backends (like DBI) support simple searches
710             $d->search({ name => "foo" });
711              
712              
713             # others use GIN queries (DBI supports both)
714             $d->search($gin_query);
715              
716             =head1 DESCRIPTION
717              
718             L<KiokuDB> is a Moose based frontend to various data stores, somewhere in
719             between L<Tangram> and L<Pixie>.
720              
721             Its purpose is to provide persistence for "regular" objects with as little
722             effort as possible, without sacrificing control over how persistence is
723             actually done, especially for harder to serialize objects.
724              
725             L<KiokuDB> is also non-invasive: it does not use ties, C<AUTOLOAD>, proxy
726             objects, C<sv_magic> or any other type of trickery.
727              
728             Many features important for proper Perl space semantics are supported,
729             including shared data, circular structures, weak references, tied structures,
730             etc.
731              
732             L<KiokuDB> is meant to solve two related persistence problems:
733              
734             =over 4
735              
736             =item Transparent persistence
737              
738             Store arbitrary objects without changing their class definitions or worrying
739             about schema details, and without needing to conform to the limitations of
740             a relational model.
741              
742             =item Interoperability
743              
744             Persisting arbitrary objects in a way that is compatible with existing
745             data/code (for example interoperating with another app using CouchDB with JSPON
746             semantics).
747              
748             =back
749              
750             =head1 TUTORIAL
751              
752             If you're new to L<KiokuDB> check out L<KiokuDB::Tutorial>.
753              
754             =head1 FUNDAMENTAL CONCEPTS
755              
756             In order to use any persistence framework it is important to understand what it
757             does and how it does it.
758              
759             Systems like L<Tangram> or L<DBIx::Class> generally require explicit meta data
760             and use a schema, which makes them fairly predictable.
761              
762             When using transparent systems like L<KiokuDB> or L<Pixie> it is more important
763             to understand what's going on behind the scenes in order to avoid surprises and
764             limitations.
765              
766             An architectural overview is available on the website:
767             L<http://www.iinteractive.com/kiokudb/arch.html>
768              
769             The process is explained here and in the various component documentation in
770             more detail.
771              
772             =head2 Collapsing
773              
774             When an object is stored using L<KiokuDB> it's collapsed into an
775             L<KiokuDB::Entry|Entry>.
776              
777             An entry is a simplified representation of the object, allowing the data to be
778             saved in formats as simple as JSON.
779              
780             References to other objects are converted to symbolic references in the entry,
781             so objects can be saved independently of each other.
782              
783             The entries are given to the L<KiokuDB::Backend|Backend> for actual storage.
784              
785             Collapsing is explained in detail in L<KiokuDB::Collapser>. The way an entry is
786             created varies with the object's class.
787              
788             =head2 Linking
789              
790             When objects are loaded, entries are retrieved from the backend using their
791             UIDs.
792              
793             When a UID is already loaded (in the live object set of a L<KiokuDB> instance,
794             see L<KiokuDB::LiveObjects>) the live object is used. This way references to
795             shared objects are shared in memory regardless of the order the objects were
796             stored or loaded.
797              
798             This process is explained in detail in L<KiokuDB::Linker>.
799              
800             =head1 ROOT SET MEMBERSHIP
801              
802             Any object that is passed to C<store> or C<insert> directly is implicitly
803             considered a member of the root set.
804              
805             This flag implies that the object is an identified resource and should not be
806             garbage collected with any of the proposed garbage collection schemes.
807              
808             The root flag may be modified explicitly:
809              
810             $kiokudb->set_root(@objects); # or unset_root
811              
812             $kiokudb->update(@objects);
813              
814             Lastly, root set membership may also be specified explicitly by the typemap.
815              
816             A root set member must be explicitly removed using C<delete> or by
817             removing it from the root set. Only non-members of the root set will be
818             purged with any garbage collection scheme.
819              
820             =head1 TRANSACTIONS
821              
822             On supporting backends the C<txn_do> method will execute a block and commit the
823             transaction at its end.
824              
825             Nesting of C<txn_do> blocks is always supported, though rolling back a nested
826             transaction may produce different results on different backends.
827              
828             If the backend does not support transactions C<txn_do> simply executes the code
829             block normally.
830              
831             =head1 CONCURRENCY
832              
833             Most transactional backends are also concurrent.
834              
835             L<KiokuDB::Backend::BDB> and L<KiokuDB::Backend::CouchDB> default to
836             serializable transaction isolation and do not suffer from deadlocks, but
837             serialization errors may occur, aborting the transaction (in which case the
838             transaction should be tried again).
839              
840             L<KiokuDB::Backend::Files> provides good concurrency support but will only
841             detect deadlocks on platforms which return C<EDEADLK> from C<flock>.
842             L<Directory::Transactional> may provide alternative mechanisms in the future.
843              
844             Concurrency support in L<KiokuDB::Backend::DBI> depends on the database. SQLite
845             defaults to serializable transaction isolation out of the box, wheras MySQL and
846             PostgreSQL default to read committed.
847              
848             Depending on your application read committed isolation may be sufficient, but
849             due to the graph structure nature of the data repeatable reads or serializable
850             level isolation is highly recommended. Read committed isolation generally works
851             well when each row in the database is more or less independent of others, and
852             various constraints ensure integrity. Unfortunately this is not the case with
853             the graph layout.
854              
855             To enable stronger isolation guarantees see
856             L<KiokuDB::Backend::DBI/Transactions> for per-database pointers.
857              
858             =head1 ATTRIBUTES
859              
860             L<KiokuDB> uses a number of delegates which do the actual work.
861              
862             Of these only C<backend> is required, the rest have default definitions.
863              
864             Additional attributes that are not commonly used are listed in L</"INTERNAL
865             ATTRIBUTES">.
866              
867             =over 4
868              
869             =item backend
870              
871             This attribute is required.
872              
873             This must be an object that does L<KiokuDB::Backend>.
874              
875             The backend handles storage and retrieval of entries.
876              
877             =item typemap
878              
879             This is an instance L<KiokuDB::TypeMap>.
880              
881             The typemap contains entries which control how L<KiokuDB::Collapser> and
882             L<KiokuDB::Linker> handle different types of objects.
883              
884             =item allow_classes
885              
886             An array references of extra classes to allow.
887              
888             Objects blessed into these classes will be collapsed using
889             L<KiokuDB::TypeMap::Entry::Naive>.
890              
891             =item allow_bases
892              
893             An array references of extra base classes to allow.
894              
895             Objects derived from these classes will be collapsed using
896             L<KiokuDB::TypeMap::Entry::Naive>.
897              
898             =item allow_class_builders
899              
900             If true adds L<KiokuDB::TypeMap::ClassBuilders> to the merged typemap.
901              
902             It's possible to provide a hash reference of options to give to
903             L<KiokuDB::TypeMap::ClassBuilders/new>.
904              
905             =item check_class_versions
906              
907             Controls whether or not the class versions of objects are checked on load.
908              
909             Defaults to true.
910              
911             =item class_version_table
912              
913             A table of classes and versions that is passed to the default typemap entry for
914             Moose/Class::MOP objects.
915              
916             When a class version has changed between the time that an object was stored and
917             the time it's being retrieved, the data must be converted.
918              
919             See L<KiokuDB::TypeMap::Entry::MOP> for more details.
920              
921             =back
922              
923             =head1 METHODS
924              
925             =over 4
926              
927             =item connect $dsn, %args
928              
929             DWIM wrapper for C<new>.
930              
931             C<$dsn> represents some sort of backend (much like L<DBI> dsns map to DBDs).
932              
933             An example DSN is:
934              
935             my $dir = KiokuDB->connect("bdb:dir=path/to/data/");
936              
937             The backend moniker name is extracted by splitting on the colon. The rest of
938             the string is passed to C<new_from_dsn>, which is documented in more detail in
939             L<KiokuDB::Backend>.
940              
941             Typically DSN arguments are separated by C<;>, with C<=> separating keys and
942             values. Arguments with no value are assumed to denote boolean truth (e.g.
943             C<jspon:dir=foo;pretty> means C<< dir => "foo", pretty => 1 >>). However, a
944             backend may override the default parsing, so this is not guaranteed.
945              
946             Extra arguments are passed both to the backend constructor, and the C<KiokuDB>
947             constructor.
948              
949             Note that if you need a typemap you still need to pass it in:
950              
951             KiokuDB->connect( $dsn, typemap => $typemap );
952              
953             The DSN can also be a valid L<JSON> string taking one of the following forms:
954              
955             dsn => '["dbi:SQLite:foo",{"schema":"MyApp::DB"}]'
956              
957             dsn => '{"dsn":"dbi:SQLite:foo","schema":"MyApp::DB"}'
958              
959             This allows more complicated arguments to be specified accurately, or arbitrary
960             options to be specified when the backend has nonstandard DSN parsing (for
961             instance L<KiokuDB::Backend::DBI> simply passes the string to L<DBI>, so this
962             is necessary in order to specify options on the command line).
963              
964             =item configure $config_file, %args
965              
966             TODO
967              
968             =item new %args
969              
970             Creates a new directory object.
971              
972             See L</ATTRIBUTES>
973              
974             =item new_scope
975              
976             Creates a new object scope. Handled by C<live_objects>.
977              
978             The object scope artificially bumps up the reference count of objects to ensure
979             that they live at least as long as the scope does.
980              
981             This ensures that weak references aren't deleted prematurely, and the object
982             graph doesn't get corrupted without needing to create circular structures and
983             cleaning up leaks manually.
984              
985             =item lookup @ids
986              
987             Fetches the objects for the specified IDs from the live object set or from
988             storage.
989              
990             =item store @objects
991              
992             =item store %objects
993              
994             =item store_nonroot @objects
995              
996             =item store_nonroot %objects
997              
998             Recursively collapses C<@objects> and inserts or updates the entries.
999              
1000             This performs a full update of every reachable object from C<@objects>,
1001             snapshotting everything.
1002              
1003             Strings found in the object list are assumed to be IDs for the following objects.
1004              
1005             The C<nonroot> variant will not mark the objects as members of the root set
1006             (therefore they will be subject to garbage collection).
1007              
1008             =item update @objects
1009              
1010             Performs a shallow update of @objects (referents are not updated).
1011              
1012             It is an error to update an object not in the database.
1013              
1014             =item deep_update @objects
1015              
1016             Update @objects and all of the objects they reference. All references
1017             objects must already be in the database.
1018              
1019             =item insert @objects
1020              
1021             =item insert %objects
1022              
1023             =item insert_nonroot @objects
1024              
1025             =item insert_nonroot %objects
1026              
1027             Inserts objects to the database.
1028              
1029             It is an error to insert objects that are already in the database, all elements
1030             of C<@objects> must be new, but their referents don't have to be.
1031              
1032             C<@objects> will be collapsed recursively, but the collapsing stops at known
1033             objects, which will not be updated.
1034              
1035             The C<nonroot> variant will not mark the objects as members of the root set
1036             (therefore they will be subject to garbage collection).
1037              
1038             =item delete @objects_or_ids
1039              
1040             Deletes the specified objects from the store.
1041              
1042             Note that this can cause lookup errors if the object you are deleting is
1043             referred to by another object, because that link will be broken.
1044              
1045             =item set_root @objects
1046              
1047             =item unset_root @objects
1048              
1049             Modify the C<root> flag on the associated entries.
1050              
1051             C<update> must be called for the change to take effect.
1052              
1053             =item txn_do $code, %args
1054              
1055             =item txn_do %args
1056              
1057             =item scoped_txn $code
1058              
1059             Executes $code within the scope of a transaction.
1060              
1061             This requires that the backend supports transactions
1062             (L<KiokuDB::Backend::Role::TXN>).
1063              
1064             If the backend does not support transactions, the code block will simply be
1065             invoked.
1066              
1067             Transactions may be nested.
1068              
1069             If the C<scope> argument is true an implicit call to C<new_scope> will be made,
1070             keeping the scope for the duration of the transaction.
1071              
1072             The return value is propagated from the code block, with handling of
1073             list/scalar/void context.
1074              
1075             C<scoped_txn> is like C<txn_do> but sets C<scope> to true.
1076              
1077             =item txn_begin
1078              
1079             =item txn_commit
1080              
1081             =item txn_rollback
1082              
1083             These methods simply call the corresponding methods on the backend.
1084              
1085             Like C<txn_do> these methods are no-ops if the backend does not support
1086             transactions.
1087              
1088             =item search \%proto
1089              
1090             =item search @args
1091              
1092             Searching requires a backend that supports querying.
1093              
1094             The C<\%proto> form is currently unspecified but in the future should provide a
1095             simple but consistent way of looking up objects by attributes.
1096              
1097             The second form is backend specific querying, for instance
1098             L<Search::GIN::Query> objects passed to L<KiokuDB::Backend::BDB::GIN> or
1099             the generic GIN backend wrapper L<KiokuDB::GIN>.
1100              
1101             Returns a L<Data::Stream::Bulk> of the results.
1102              
1103             =item root_set
1104              
1105             Returns a L<Data::Stream::Bulk> of all the root objects in the database.
1106              
1107             =item all_objects
1108              
1109             Returns a L<Data::Stream::Bulk> of all the objects in the database.
1110              
1111             =item grep $filter
1112              
1113             Returns a L<Data::Stream::Bulk> of the objects in C<root_set> filtered by
1114             C<$filter>.
1115              
1116             =item scan $callback
1117              
1118             Iterates the root set calling C<$callback> for each object.
1119              
1120             =item object_to_id
1121              
1122             =item objects_to_ids
1123              
1124             =item id_to_object
1125              
1126             =item ids_to_objects
1127              
1128             Delegates to L<KiokuDB::LiveObjects>
1129              
1130             =item directory
1131              
1132             Returns C<$self>.
1133              
1134             This is used when setting up L<KiokuDB::Role::API> delegation chains. Calling
1135             C<directory> on any level of delegator will always return the real L<KiokuDB>
1136             instance no matter how deep.
1137              
1138             =back
1139              
1140             =head1 GLOBALS
1141              
1142             =over 4
1143              
1144             =item C<$SERIAL_IDS>
1145              
1146             If set at compile time, the default UUID generation role will use serial IDs,
1147             instead of UUIDs.
1148              
1149             This is useful for testing, since the same IDs will be issued each run, but is
1150             utterly broken in the face of concurrency.
1151              
1152             =back
1153              
1154             =head1 INTERNAL ATTRIBUTES
1155              
1156             These attributes are documented for completeness and should typically not be
1157             needed.
1158              
1159             =over 4
1160              
1161             =item collapser
1162              
1163             L<KiokuDB::Collapser>
1164              
1165             The collapser prepares objects for storage, by creating L<KiokuDB::Entry>
1166             objects to pass to the backend.
1167              
1168             =item linker
1169              
1170             L<KiokuDB::Linker>
1171              
1172             The linker links entries into functioning instances, loading necessary
1173             dependencies from the backend.
1174              
1175             =item live_objects
1176              
1177             L<KiokuDB::LiveObjects>
1178              
1179             The live object set keeps track of objects and entries for the linker and the
1180             resolver.
1181              
1182             It also creates scope objects that help ensure objects don't garbage collect
1183             too early (L<KiokuDB::LiveObjects/new_scope>, L<KiokuDB::LiveObjects::Scope>),
1184             and transaction scope objects used by C<txn_do>
1185             (L<KiokuDB::LiveObjects::TXNScope>).
1186              
1187             =item typemap_resolver
1188              
1189             An instance of L<KiokuDB::TypeMap::Resolver>. Handles actual lookup and
1190             compilation of typemap entries, using the user typemap.
1191              
1192             =back
1193              
1194             =head1 SEE ALSO
1195              
1196             =head2 Prior Art on the CPAN
1197              
1198             =over 4
1199              
1200             =item L<Pixie>
1201              
1202             =item L<DBM::Deep>
1203              
1204             =item L<OOPS>
1205              
1206             =item L<Tangram>
1207              
1208             =item L<DBIx::Class>
1209              
1210             Polymorphic retrieval is possible with L<DBIx::Class::DynamicSubclass>
1211              
1212             =item L<Fey::ORM>
1213              
1214             =item L<MooseX::Storage>
1215              
1216             =back
1217              
1218             =head1 VERSION CONTROL
1219              
1220             KiokuDB is maintained using Git. Information about the repository is available
1221             on L<http://www.iinteractive.com/kiokudb/>
1222              
1223             =head1 AUTHOR
1224              
1225             Yuval Kogman <nothingmuch@woobling.org>
1226              
1227             =head1 COPYRIGHT AND LICENSE
1228              
1229             This software is copyright (c) 2014 by Yuval Kogman, Infinity Interactive.
1230              
1231             This is free software; you can redistribute it and/or modify it under
1232             the same terms as the Perl 5 programming language system itself.
1233              
1234             =cut