File Coverage

blib/lib/KiokuDB.pm
Criterion Covered Total %
statement 228 291 78.3
branch 62 106 58.4
condition 12 22 54.5
subroutine 50 60 83.3
pod 20 28 71.4
total 372 507 73.3


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