35
36:- module(rdf_edit,
37 [ rdfe_assert/3, 38 rdfe_assert/4, 39 rdfe_retractall/3, 40 rdfe_retractall/4, 41 rdfe_update/4, 42 rdfe_update/5, 43 rdfe_load/1, 44 rdfe_load/2, 45 rdfe_delete/1, 46
47 rdfe_register_ns/2, 48 rdfe_unregister_ns/2, 49
50 rdfe_reset/0, 51
52 rdfe_transaction/1, 53 rdfe_transaction/2, 54 rdfe_transaction_member/2, 55 rdfe_transaction_name/2, 56 rdfe_set_transaction_name/1, 57
58 rdfe_set_watermark/1, 59
60 rdfe_undo/0, 61 rdfe_redo/0,
62 rdfe_can_undo/1, 63 rdfe_can_redo/1, 64
65 rdfe_set_file_property/2, 66 rdfe_get_file_property/2, 67
68 rdfe_is_modified/1, 69 rdfe_clear_modified/1, 70
71 rdfe_open_journal/2, 72 rdfe_close_journal/0,
73 rdfe_replay_journal/1, 74 rdfe_current_journal/1, 75
76 rdfe_snapshot_file/1 77 ]). 78:- use_module(library(semweb/rdf_prefixes),
79 [ (rdf_meta)/1,
80 op(_,_,rdf_meta)
81 ]). 82
83:- autoload(rdf_db,
84 [ rdf_assert/4, rdf/4, rdf_retractall/4, rdf_update/4,
85 rdf_update/5, rdf_load/2, rdf_statistics/1, rdf_md5/2,
86 rdf_unload/1, rdf_save_db/2, rdf_load_db/1, rdf_register_ns/2,
87 rdf_source/2, rdf_graph_property/2, rdf_graph/1, rdf_set_graph/2,
88 rdf_reset_db/0, rdf_load/1
89 ]). 90:- autoload(library(broadcast),[broadcast/1]). 91:- use_module(library(debug),[debug/3,debugging/1]). 92:- autoload(library(gui_tracer),[gtrace/0]). 93:- autoload(library(lists),[append/3]). 94:- autoload(library(uri),[uri_file_name/2,uri_components/2,uri_data/3]). 95
96:- meta_predicate
97 rdfe_transaction(0),
98 rdfe_transaction(0, +). 99
100:- predicate_options(rdfe_load/2, 2,
101 [pass_to(rdf_db:rdf_load/2, 2)]). 102
103:- dynamic
104 undo_log/5, 105 current_transaction/1, 106 transaction_name/2, 107 undo_marker/2, 108 journal/3, 109 snapshot_file/1. 110
124
125:- rdf_meta
126 rdfe_assert(r,r,o),
127 rdfe_assert(r,r,o,+),
128 rdfe_retractall(r,r,o),
129 rdfe_update(r,r,o,t),
130 rdfe_delete(r),
131 rdfe_transaction(:),
132 rdfe_transaction(:, +). 133
134
135 138
139rdfe_assert(Subject, Predicate, Object) :-
140 rdfe_assert(Subject, Predicate, Object, user).
141
142rdfe_assert(Subject, Predicate, Object, PayLoad) :-
143 rdf_assert(Subject, Predicate, Object, PayLoad),
144 rdfe_current_transaction(TID),
145 assert_action(TID, assert(PayLoad), Subject, Predicate, Object),
146 journal(assert(TID, Subject, Predicate, Object, PayLoad)).
147
148rdfe_retractall(Subject, Predicate, Object) :-
149 rdfe_retractall(Subject, Predicate, Object, _).
150
151rdfe_retractall(Subject, Predicate, Object, PayLoad) :-
152 rdfe_current_transaction(TID),
153 ( rdf(Subject, Predicate, Object, PayLoad),
154 assert_action(TID, retract(PayLoad), Subject, Predicate, Object),
155 journal(retract(TID, Subject, Predicate, Object, PayLoad)),
156 fail
157 ; true
158 ),
159 rdf_retractall(Subject, Predicate, Object, PayLoad).
160
169
170rdfe_update(Subject, Predicate, Object, Action) :-
171 rdfe_current_transaction(TID),
172 rdf_update(Subject, Predicate, Object, Action),
173 ( Action = object(New)
174 -> assert_action(TID, object(Object), Subject, Predicate, New)
175 ; Action = predicate(New)
176 -> assert_action(TID, predicate(Predicate), Subject, New, Object)
177 ; Action = subject(New)
178 -> assert_action(TID, subject(Subject), New, Predicate, Object)
179 ; Action = source(New)
180 -> forall(rdf(Subject, Predicate, Object, PayLoad),
181 assert_action(TID, source(PayLoad, New),
182 Subject, Predicate, Object))
183 ),
184 journal(update(TID, Subject, Predicate, Object, Action)).
185
186rdfe_update(Subject, Predicate, Object, PayLoad, Action) :-
187 rdfe_current_transaction(TID),
188 rdf_update(Subject, Predicate, Object, PayLoad, Action),
189 ( Action = source(New)
190 -> assert_action(TID, source(PayLoad, New),
191 Subject, Predicate, Object)
192 ; throw(tbd) 193 ),
194 journal(update(TID, Subject, Predicate, Object, PayLoad, Action)).
195
201
202rdfe_delete(Subject) :-
203 rdfe_transaction(delete(Subject)).
204
205delete(Subject) :-
206 rdfe_retractall(Subject, _, _),
207 rdfe_retractall(_, Subject, _),
208 rdfe_retractall(_, _, Subject).
209
210
211 214
220
221rdfe_load(File) :-
222 rdfe_load(File, []).
223
224
225rdfe_load(File, Options) :-
226 rdfe_current_transaction(TID),
227 absolute_file_name(File,
228 [ access(read),
229 extensions([rdf,rdfs,owl,ttl,nt,''])
230 ], Path),
231 rdf_load(Path,
232 [ graph(Graph),
233 modified(Modified)
234 | Options
235 ]),
236 ( Modified == not_modified
237 -> true
238 ; absolute_file_name('.', PWD),
239 size_file(Path, Size),
240 ( Modified = last_modified(Stamp)
241 -> true
242 ; time_file(Path, Stamp)
243 ),
244 SecTime is round(Stamp),
245 rdf_statistics(triples_by_graph(Graph, Triples)),
246 rdf_md5(Graph, MD5),
247 assert_action(TID, load_file(Path), -, -, -),
248 journal(rdf_load(TID,
249 Path,
250 [ pwd(PWD),
251 size(Size),
252 modified(SecTime),
253 triples(Triples),
254 md5(MD5),
255 from(File)
256 ])),
257 ensure_snapshot(Path)
258 ).
259
260
261rdfe_unload(Path) :-
262 rdfe_current_transaction(TID),
263 rdf_unload(Path),
264 assert_action(TID, unload_file(Path), -, -, -),
265 journal(rdf_unload(TID, Path)).
266
267
273
274ensure_snapshot(Path) :-
275 rdfe_current_journal(_),
276 rdf_md5(Path, MD5),
277 ( snapshot_file(Path, MD5,
278 [ access(read),
279 file_errors(fail)
280 ],
281 File)
282 -> debug(snapshot, 'Existing snapshot for ~w on ~w', [Path, File])
283 ; snapshot_file(Path, MD5,
284 [ access(write)
285 ],
286 File),
287 debug(snapshot, 'Saving snapshot for ~w to ~w', [Path, File]),
288 rdf_save_db(File, Path)
289 ),
290 assert(snapshot_file(File)).
291ensure_snapshot(_).
292
293
300
301load_snapshot(Source, Path) :-
302 statistics(cputime, T0),
303 rdf_load_db(Path),
304 statistics(cputime, T1),
305 Time is T1 - T0,
306 rdf_statistics(triples_by_graph(Source, Triples)),
307 rdf_md5(Source, MD5),
308 309 assert(rdf_db:rdf_source(Source, 1e12, Triples, MD5)),
310 print_message(informational,
311 rdf(loaded(Source, Triples, snapshot(Time)))),
312 assert(snapshot_file(Path)).
313
314
318
319snapshot_file(Path, MD5, Options, SnapShot) :-
320 file_base_name(Path, Base),
321 atomic_list_concat([Base, @, MD5], File),
322 absolute_file_name(snapshot(File),
323 [ extensions([trp])
324 | Options
325 ],
326 SnapShot).
327
328
335
336rdfe_snapshot_file(File) :-
337 snapshot_file(File).
338
339
340 343
344:- dynamic
345 system_ns/2. 346:- volatile
347 system_ns/2. 348
352
353rdfe_register_ns(Id, URI) :-
354 rdf_db:ns(Id, URI),
355 !.
356rdfe_register_ns(Id, URI) :-
357 save_system_ns,
358 rdfe_current_transaction(TID),
359 rdf_register_ns(Id, URI),
360 broadcast(rdf_ns(register(Id, URI))),
361 assert_action(TID, ns(register(Id, URI)), -, -, -),
362 journal(ns(TID, register(Id, URI))).
363
364rdfe_unregister_ns(Id, URI) :-
365 save_system_ns,
366 rdfe_current_transaction(TID),
367 retractall(rdf_db:ns(Id, URI)),
368 broadcast(rdf_ns(unregister(Id, URI))),
369 assert_action(TID, ns(unregister(Id, URI)), -, -, -),
370 journal(ns(TID, unregister(Id, URI))).
371
376
377rdfe_reset_ns :-
378 ( system_ns(_, _)
379 -> retractall(rdf_db:ns(Id, URI)),
380 forall(system_ns(Id, URI), assert(rdf_db:ns(Id, URI)))
381 ; true
382 ).
383
384save_system_ns :-
385 system_ns(_, _),
386 !. 387save_system_ns :-
388 forall(rdf_db:ns(Id, URI), assert(system_ns(Id, URI))).
389
390
391 394
400
401rdfe_transaction(Goal) :-
402 rdfe_transaction(Goal, []).
403rdfe_transaction(Goal, Name) :-
404 rdfe_begin_transaction(Name),
405 ( catch(Goal, E, true)
406 -> ( var(E)
407 -> check_file_protection(Error),
408 ( var(Error)
409 -> rdfe_commit
410 ; rdfe_rollback,
411 throw(Error)
412 )
413 ; rdfe_rollback,
414 throw(E)
415 )
416 ; rdfe_rollback,
417 fail
418 ).
419
424
425rdfe_begin_transaction(Name) :-
426 current_transaction(TID), 427 !,
428 append(TID, [1], TID2),
429 asserta(current_transaction(TID2)),
430 assert(transaction_name(TID2, Name)).
431rdfe_begin_transaction(Name) :- 432 flag(rdf_edit_tid, TID, TID+1),
433 asserta(current_transaction([TID])),
434 assert(transaction_name(TID, Name)).
435
436rdfe_current_transaction(TID) :-
437 current_transaction(TID),
438 !.
439rdfe_current_transaction(_) :-
440 throw(error(existence_error(rdf_transaction, _), _)).
441
442rdfe_commit :-
443 retract(current_transaction(TID)),
444 !,
445 retractall(undo_marker(_, _)),
446 ( rdfe_transaction_member(TID, _)
447 -> get_time(Time), 448 journal(commit(TID, Time)),
449 ( TID = [Id]
450 -> broadcast(rdf_transaction(Id))
451 ; true
452 )
453 ; true
454 ).
455
456rdfe_rollback :-
457 retract(current_transaction(TID)),
458 !,
459 journal(rollback(TID)),
460 rollback(TID).
461
468
469rollback(TID) :-
470 append(TID, _, Id),
471 ( retract(undo_log(Id, Action, Subject, Predicate, Object)),
472 ( rollback(Action, Subject, Predicate, Object)
473 -> fail
474 ; print_message(error,
475 rdf_undo_failed(undo(Action, Subject,
476 Predicate, Object))),
477 fail
478 )
479 ; true
480 ).
481
482rollback(assert(PayLoad), Subject, Predicate, Object) :-
483 !,
484 rdf_retractall(Subject, Predicate, Object, PayLoad).
485rollback(retract(PayLoad), Subject, Predicate, Object) :-
486 !,
487 rdf_assert(Subject, Predicate, Object, PayLoad).
488rollback(Action, Subject, Predicate, Object) :-
489 action(Action),
490 !,
491 rdf_update(Subject, Predicate, Object, Action).
492
493
494assert_action(TID, Action, Subject, Predicate, Object) :-
495 asserta(undo_log(TID, Action, Subject, Predicate, Object)).
496
501
502undo(TID) :-
503 append(TID, _, Id),
504 ( retract(undo_log(Id, Action, Subject, Predicate, Object)),
505 ( undo(Action, Subject, Predicate, Object)
506 -> fail
507 ; print_message(warning,
508 rdf_undo_failed(undo(Action, Subject,
509 Predicate, Object))),
510 fail
511 )
512 ; true
513 ).
514
515undo(assert(PayLoad), Subject, Predicate, Object) :-
516 !,
517 rdfe_retractall(Subject, Predicate, Object, PayLoad).
518undo(retract(PayLoad), Subject, Predicate, Object) :-
519 !,
520 rdfe_assert(Subject, Predicate, Object, PayLoad).
521undo(source(Old, New), Subject, Predicate, Object) :-
522 !,
523 rdfe_update(Subject, Predicate, Object, Old, source(New)).
524undo(ns(Action), -, -, -) :-
525 !,
526 ( Action = register(Id, URI)
527 -> rdfe_unregister_ns(Id, URI)
528 ; Action = unregister(Id, URI)
529 -> rdfe_register_ns(Id, URI)
530 ).
531undo(load_file(Path), -, -, -) :-
532 !,
533 rdfe_unload(Path).
534undo(unload_file(Path), -, -, -) :-
535 !,
536 rdfe_load(Path).
537undo(Action, Subject, Predicate, Object) :-
538 action(Action),
539 !,
540 rdfe_update(Subject, Predicate, Object, Action).
541
542action(subject(_)).
543action(predicate(_)).
544action(object(_)).
545
551
552rdfe_undo :-
553 undo_marker(undo, TID),
554 !,
555 ( undo_previous(TID, UnDone)
556 -> retractall(undo_marker(_, _)),
557 assert(undo_marker(undo, UnDone)),
558 broadcast(rdf_undo(undo, UnDone))
559 ; fail 560 ).
561rdfe_undo :-
562 retract(undo_marker(redo, _)),
563 !,
564 last_transaction(TID),
565 undo_previous(TID, UnDone),
566 assert(undo_marker(undo, UnDone)),
567 broadcast(rdf_undo(undo, UnDone)).
568rdfe_undo :-
569 last_transaction(TID),
570 undo_previous(TID, UnDone),
571 assert(undo_marker(undo, UnDone)),
572 broadcast(rdf_undo(undo, UnDone)).
573
574find_previous_undo(-1, _) :-
575 !,
576 fail.
577find_previous_undo(TID, TID) :-
578 undo_log([TID|_], _, _, _, _),
579 !.
580find_previous_undo(TID0, TID) :-
581 TID1 is TID0 - 1,
582 find_previous_undo(TID1, TID).
583
584undo_previous(TID, Undone) :-
585 find_previous_undo(TID, Undone),
586 rdfe_transaction(undo([Undone])).
587
588last_transaction(TID) :-
589 undo_log([TID|_], _, _, _, _),
590 !.
591
595
596rdfe_redo :-
597 ( retract(undo_marker(undo, _))
598 -> last_transaction(TID),
599 undo_previous(TID, UnDone),
600 assert(undo_marker(redo, UnDone)),
601 broadcast(rdf_undo(redo, UnDone))
602 ; retract(undo_marker(redo, TID))
603 -> undo_previous(TID, UnDone),
604 assert(undo_marker(redo, UnDone)),
605 broadcast(rdf_undo(redo, UnDone))
606 ; true
607 ).
608
609
616
617rdfe_can_redo(Redo) :-
618 undo_marker(undo, _),
619 !,
620 last_transaction(TID),
621 find_previous_undo(TID, Redo).
622rdfe_can_redo(Redo) :-
623 undo_marker(redo, TID),
624 find_previous_undo(TID, Redo).
625
626rdfe_can_undo(Undo) :- 627 undo_marker(undo, TID),
628 !,
629 find_previous_undo(TID, Undo).
630rdfe_can_undo(Undo) :- 631 last_transaction(TID),
632 find_previous_undo(TID, Undo).
633
637
638rdfe_transaction_name(TID, Name) :-
639 transaction_name(TID, Name),
640 Name \== [].
641
645
646rdfe_set_transaction_name(Name) :-
647 current_transaction(TID),
648 !,
649 assert(transaction_name(TID, Name)).
650
655
656rdfe_transaction_member(TID, Member) :-
657 ( integer(TID)
658 -> Id = [TID|_]
659 ; append(TID, _, Id)
660 ),
661 undo_log(Id, Action, Subject, Predicate, Object),
662 user_transaction_member(Action, Subject, Predicate, Object, Member).
663
664user_transaction_member(assert(_), Subject, Predicate, Object,
665 assert(Subject, Predicate, Object)) :- !.
666user_transaction_member(retract(_), Subject, Predicate, Object,
667 retract(Subject, Predicate, Object)) :- !.
668user_transaction_member(load_file(Path), -, -, -,
669 file(load(Path))) :- !.
670user_transaction_member(unload_file(Path), -, -, -,
671 file(unload(Path))) :- !.
672user_transaction_member(Update, Subject, Predicate, Object,
673 update(Subject, Predicate, Object, Update)).
674
675
676 679
680:- dynamic
681 rdf_source_permission/2, 682 rdf_current_default_file/2. 683
690
691rdfe_set_file_property(File, access(Access)) :-
692 !,
693 to_uri(File, URL),
694 retractall(rdf_source_permission(URL, _)),
695 assert(rdf_source_permission(URL, Access)),
696 broadcast(rdf_file_property(URL, access(Access))).
697rdfe_set_file_property(File, default(Type)) :-
698 to_uri(File, URL),
699 rdfe_set_file_property(URL, access(rw)), 700 retractall(rdf_current_default_file(_,_)),
701 assert(rdf_current_default_file(URL, Type)),
702 broadcast(rdf_file_property(URL, default(Type))).
703
704
709
710rdfe_get_file_property(FileOrURL, access(Access)) :-
711 ( ground(FileOrURL)
712 -> to_uri(FileOrURL, URL)
713 ; rdf_source(_DB, URL),
714 FileOrURL = URL
715 ),
716 ( rdf_source_permission(URL, Access0)
717 -> Access0 = Access
718 ; uri_file_name(URL, File),
719 access_file(File, write)
720 -> assert(rdf_source_permission(URL, rw)),
721 Access = rw
722 ; assert(rdf_source_permission(URL, ro)),
723 Access = ro
724 ).
725rdfe_get_file_property(FileOrURL, default(Default)) :-
726 ground(FileOrURL),
727 to_uri(FileOrURL, URL),
728 ( rdf_current_default_file(URL, Default)
729 -> true
730 ; FileOrURL = user,
731 Default = fallback
732 ).
733rdfe_get_file_property(URL, default(Default)) :-
734 ( rdf_current_default_file(URL, Default)
735 -> true
736 ; URL = user,
737 Default = fallback
738 ).
739
740
744
745check_file_protection(Error) :-
746 ( rdfe_get_file_property(File, access(ro)),
747 rdfe_is_modified(File)
748 -> Error = error(permission_error(modify, source, File), triple20)
749 ; true
750 ).
751
752
756
757to_uri(URL, URL) :-
758 uri_components(URL, Components),
759 uri_data(scheme, Components, Scheme),
760 nonvar(Scheme),
761 uri_scheme(Scheme),
762 !.
763to_uri(File, URL) :-
764 uri_file_name(URL, File).
765
766
767uri_scheme(file).
768uri_scheme(http).
769uri_scheme(https).
770uri_scheme(ftp).
771uri_scheme(ftps).
772
773
774 777
782
783rdfe_is_modified(Source) :-
784 rdf_source(Graph, Source),
785 rdf_graph_property(Graph, modified(true)).
786
787
788rdfe_clear_modified :-
789 forall(rdf_graph(File),
790 rdfe_clear_modified(File)).
791
795
796rdfe_clear_modified(Graph) :-
797 rdf_set_graph(Graph, modified(false)).
798
799
800 803
808
809rdfe_set_watermark(Name) :-
810 rdfe_current_transaction(TID),
811 assert_action(TID, watermark(Name), -, -, -),
812 journal(watermark(TID, Name)).
813
814
815 818
822
823rdfe_reset :-
824 rdfe_reset_journal,
825 rdfe_reset_ns,
826 rdfe_reset_undo,
827 rdf_reset_db,
828 broadcast(rdf_reset).
829
833
834rdfe_reset_journal :-
835 ( rdfe_current_journal(_)
836 -> rdfe_close_journal
837 ; true
838 ).
839
840rdfe_reset_undo :-
841 retractall(undo_log(_,_,_,_,_)),
842 retractall(current_transaction(_)),
843 retractall(transaction_name(_,_)),
844 retractall(undo_marker(_,_)),
845 retractall(snapshot_file(_)).
846
849
850:- at_halt(rdfe_reset_journal). 851
852
853 856
857journal_version(1).
858
872
873rdfe_open_journal(_, _) :- 874 journal(_, _, _),
875 !.
876rdfe_open_journal(File, read) :-
877 !,
878 absolute_file_name(File,
879 [ extensions([rdfj, '']),
880 access(read)
881 ],
882 Path),
883 rdfe_replay_journal(Path),
884 rdfe_clear_modified.
885rdfe_open_journal(File, write) :-
886 !,
887 absolute_file_name(File,
888 [ extensions([rdfj, '']),
889 access(write)
890 ],
891 Path),
892 open(Path, write, Stream, [close_on_abort(false)]),
893 assert(journal(Path, write, Stream)),
894 get_time(T),
895 journal_open(start, T).
896rdfe_open_journal(File, append) :-
897 working_directory(CWD, CWD),
898 absolute_file_name(File,
899 [ extensions([rdfj, '']),
900 relative_to(CWD),
901 access(write)
902 ],
903 Path),
904 ( exists_file(Path)
905 -> rdfe_replay_journal(Path),
906 rdfe_clear_modified,
907 get_time(T),
908 assert(journal(Path, append(T), []))
909 ; rdfe_open_journal(Path, write)
910 ).
911
912
913journal_open(Type, Time) :-
914 journal_comment(Type, Time),
915 SecTime is round(Time),
916 journal_version(Version),
917 Start =.. [ Type, [ time(SecTime),
918 version(Version)
919 ]
920 ],
921 journal(Start),
922 broadcast(rdf_journal(Start)).
923
(start, Time) :-
925 journal(_, _, Stream),
926 format_time(string(String), '%+', Time),
927 format(Stream,
928 '/* Triple20 Journal File\n\n \c
929 Created: ~w\n \c
930 Triple20 by Jan Wielemaker <wielemak@science.uva.nl>\n\n \c
931 EDIT WITH CARE!\n\c
932 */~n~n', [String]).
933journal_comment(resume, Time) :-
934 journal(_, _, Stream),
935 format_time(string(String), '%+', Time),
936 format(Stream,
937 '\n\c
938 /* Resumed: ~w\n\c
939 */~n~n', [String]).
940
945
946rdfe_close_journal :-
947 get_time(T),
948 SecTime is round(T),
949 journal(end([ time(SecTime)
950 ])),
951 retract(journal(_, Mode, Stream)),
952 ( Mode = append(_)
953 -> true
954 ; close(Stream)
955 ).
956
960
961rdfe_current_journal(Path) :-
962 journal(Path, _Mode, _Stream).
963
964journal(Term) :-
965 journal(Path, append(T), _),
966 !,
967 ( Term = end(_)
968 -> true
969 ; open(Path, append, Stream, [close_on_abort(false)]),
970 retractall(journal(Path, _, _)),
971 assert(journal(Path, append, Stream)),
972 journal_open(resume, T),
973 journal(Term)
974 ).
975journal(Term) :-
976 ( journal(_, _, Stream)
977 -> write_journal(Term, Stream),
978 flush_output(Stream)
979 ; broadcast(rdf_no_journal(Term))
980 ).
981
982write_journal(commit(TID, Time), Stream) :-
983 !,
984 format(Stream, 'commit(~q, ~2f).~n~n', [TID, Time]).
985write_journal(Term, Stream) :-
986 format(Stream, '~q.~n', [Term]).
987
988
994
995rdfe_replay_journal(File) :-
996 absolute_file_name(File,
997 [ extensions([rdfj, '']),
998 access(read)
999 ],
1000 Path),
1001 open(Path, read, Stream),
1002 replay(Stream),
1003 close(Stream).
1004
1005replay(Stream) :-
1006 read(Stream, Term),
1007 replay(Term, Stream).
1008
1009replay(end_of_file, _) :- !.
1010replay(start(_Attributes), Stream) :-
1011 !,
1012 read(Stream, Term),
1013 replay(Term, Stream).
1014replay(resume(_Attributes), Stream) :-
1015 !,
1016 read(Stream, Term),
1017 replay(Term, Stream).
1018replay(end(_Attributes), Stream) :-
1019 !,
1020 read(Stream, Term),
1021 replay(Term, Stream).
1022replay(Term0, Stream) :-
1023 replay_transaction(Term0, Stream),
1024 read(Stream, Term),
1025 replay(Term, Stream).
1026
1027replay_transaction(Term0, Stream) :-
1028 collect_transaction(Term0, Stream, Transaction, Last),
1029 ( committed_transaction(Last)
1030 -> replay_actions(Transaction)
1031 ; true
1032 ).
1033
1034collect_transaction(End, _, [], End) :-
1035 ends_transaction(End),
1036 !.
1037collect_transaction(A, Stream, [A|T], End) :-
1038 read(Stream, Term),
1039 collect_transaction(Term, Stream, T, End).
1040
1041committed_transaction(commit(_)).
1042committed_transaction(commit(_, _)).
1043
1044ends_transaction(end_of_file).
1045ends_transaction(commit(_)).
1046ends_transaction(commit(_, _)).
1047ends_transaction(rollback(_)).
1048ends_transaction(end(_)).
1049ends_transaction(start(_)).
1050
1051replay_actions([]).
1052replay_actions([H|T]) :-
1053 ( replay_action(H)
1054 -> replay_actions(T)
1055 ; print_message(warning,
1056 rdf_replay_failed(H)),
1057 ( debugging(journal)
1058 -> gtrace,
1059 replay_actions([H|T])
1060 ; replay_actions(T)
1061 )
1062 ).
1063
1064
1076
1077replay_action(retract(_, Subject, Predicate, Object, PayLoad)) :-
1078 rdf_retractall(Subject, Predicate, Object, PayLoad).
1079replay_action(assert(_, Subject, Predicate, Object, PayLoad)) :-
1080 rdf_assert(Subject, Predicate, Object, PayLoad).
1081replay_action(update(_, Subject, Predicate, Object, Action)) :-
1082 rdf_update(Subject, Predicate, Object, Action).
1083replay_action(update(_, Subject, Predicate, Object, Payload, Action)) :-
1084 rdf_update(Subject, Predicate, Object, Payload, Action).
1085replay_action(rdf_load(_, File, Options)) :-
1086 memberchk(md5(MD5), Options),
1087 snapshot_file(File, MD5,
1088 [ access(read),
1089 file_errors(fail)
1090 ],
1091 Path),
1092 !,
1093 debug(snapshot, 'Reloading snapshot ~w~n', [Path]),
1094 load_snapshot(File, Path).
1095replay_action(rdf_load(_, File, Options)) :-
1096 find_file(File, Options, Path),
1097 ( memberchk(triples(0), Options),
1098 memberchk(modified(Modified), Options)
1099 -> rdf_retractall(_,_,_,Path:_),
1100 retractall(rdf_db:rdf_source(Path, _, _, _)), 1101 rdf_md5(Path, MD5),
1102 assert(rdf_db:rdf_source(Path, Modified, 0, MD5))
1103 ; rdf_load(Path)
1104 ).
1105replay_action(rdf_unload(_, Source)) :-
1106 rdf_unload(Source).
1107replay_action(ns(_, register(ID, URI))) :-
1108 !,
1109 rdf_register_ns(ID, URI).
1110replay_action(ns(_, unregister(ID, URI))) :-
1111 retractall(rdf_db:ns(ID, URI)).
1112replay_action(watermark(_, _Name)) :-
1113 true.
1114
1115find_file(File, _, File) :-
1116 exists_file(File),
1117 !.
1118find_file(File, Options, Path) :-
1119 memberchk(pwd(PWD), Options),
1120 make_path(File, PWD, Path),
1121 exists_file(Path),
1122 !.
1123
1127
1128make_path(File, PWD, Path) :-
1129 atom_concat(PWD, /, PWD2),
1130 atom_concat(PWD2, Path, File).
1131
1132
1133 1136
1137:- multifile
1138 prolog:message/3,
1139 user:message_hook/3. 1140
1142
1143prolog:message(rdf_replay_failed(Term)) -->
1144 [ 'RDFDB: Replay of ~p failed'-[Term] ].
1145prolog:message(rdf_undo_failed(Term)) -->
1146 [ 'RDFDB: Undo of ~p failed'-[Term] ]