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(rdf_db). 79:- use_module(library(broadcast)). 80:- use_module(library(lists)). 81:- use_module(library(debug)). 82:- use_module(library(uri)). 83
84:- meta_predicate
85 rdfe_transaction(0),
86 rdfe_transaction(0, +). 87
88:- predicate_options(rdfe_load/2, 2,
89 [pass_to(rdf_db:rdf_load/2, 2)]). 90
91:- dynamic
92 undo_log/5, 93 current_transaction/1, 94 transaction_name/2, 95 undo_marker/2, 96 journal/3, 97 snapshot_file/1. 98
112
113:- rdf_meta
114 rdfe_assert(r,r,o),
115 rdfe_assert(r,r,o,+),
116 rdfe_retractall(r,r,o),
117 rdfe_update(r,r,o,t),
118 rdfe_delete(r),
119 rdfe_transaction(:),
120 rdfe_transaction(:, +). 121
122
123 126
127rdfe_assert(Subject, Predicate, Object) :-
128 rdfe_assert(Subject, Predicate, Object, user).
129
130rdfe_assert(Subject, Predicate, Object, PayLoad) :-
131 rdf_assert(Subject, Predicate, Object, PayLoad),
132 rdfe_current_transaction(TID),
133 assert_action(TID, assert(PayLoad), Subject, Predicate, Object),
134 journal(assert(TID, Subject, Predicate, Object, PayLoad)).
135
136rdfe_retractall(Subject, Predicate, Object) :-
137 rdfe_retractall(Subject, Predicate, Object, _).
138
139rdfe_retractall(Subject, Predicate, Object, PayLoad) :-
140 rdfe_current_transaction(TID),
141 ( rdf(Subject, Predicate, Object, PayLoad),
142 assert_action(TID, retract(PayLoad), Subject, Predicate, Object),
143 journal(retract(TID, Subject, Predicate, Object, PayLoad)),
144 fail
145 ; true
146 ),
147 rdf_retractall(Subject, Predicate, Object, PayLoad).
148
157
158rdfe_update(Subject, Predicate, Object, Action) :-
159 rdfe_current_transaction(TID),
160 rdf_update(Subject, Predicate, Object, Action),
161 ( Action = object(New)
162 -> assert_action(TID, object(Object), Subject, Predicate, New)
163 ; Action = predicate(New)
164 -> assert_action(TID, predicate(Predicate), Subject, New, Object)
165 ; Action = subject(New)
166 -> assert_action(TID, subject(Subject), New, Predicate, Object)
167 ; Action = source(New)
168 -> forall(rdf(Subject, Predicate, Object, PayLoad),
169 assert_action(TID, source(PayLoad, New),
170 Subject, Predicate, Object))
171 ),
172 journal(update(TID, Subject, Predicate, Object, Action)).
173
174rdfe_update(Subject, Predicate, Object, PayLoad, Action) :-
175 rdfe_current_transaction(TID),
176 rdf_update(Subject, Predicate, Object, PayLoad, Action),
177 ( Action = source(New)
178 -> assert_action(TID, source(PayLoad, New),
179 Subject, Predicate, Object)
180 ; throw(tbd) 181 ),
182 journal(update(TID, Subject, Predicate, Object, PayLoad, Action)).
183
189
190rdfe_delete(Subject) :-
191 rdfe_transaction(delete(Subject)).
192
193delete(Subject) :-
194 rdfe_retractall(Subject, _, _),
195 rdfe_retractall(_, Subject, _),
196 rdfe_retractall(_, _, Subject).
197
198
199 202
208
209rdfe_load(File) :-
210 rdfe_load(File, []).
211
212
213rdfe_load(File, Options) :-
214 rdfe_current_transaction(TID),
215 absolute_file_name(File,
216 [ access(read),
217 extensions([rdf,rdfs,owl,''])
218 ], Path),
219 rdf_load(Path,
220 [ graph(Graph),
221 modified(Modified)
222 | Options
223 ]),
224 ( Modified == not_modified
225 -> true
226 ; absolute_file_name('.', PWD),
227 size_file(Path, Size),
228 ( Modified = last_modified(Stamp)
229 -> true
230 ; time_file(Path, Stamp)
231 ),
232 SecTime is round(Stamp),
233 rdf_statistics(triples_by_graph(Graph, Triples)),
234 rdf_md5(Graph, MD5),
235 assert_action(TID, load_file(Path), -, -, -),
236 journal(rdf_load(TID,
237 Path,
238 [ pwd(PWD),
239 size(Size),
240 modified(SecTime),
241 triples(Triples),
242 md5(MD5),
243 from(File)
244 ])),
245 ensure_snapshot(Path)
246 ).
247
248
249rdfe_unload(Path) :-
250 rdfe_current_transaction(TID),
251 rdf_unload(Path),
252 assert_action(TID, unload_file(Path), -, -, -),
253 journal(rdf_unload(TID, Path)).
254
255
261
262ensure_snapshot(Path) :-
263 rdfe_current_journal(_),
264 rdf_md5(Path, MD5),
265 ( snapshot_file(Path, MD5,
266 [ access(read),
267 file_errors(fail)
268 ],
269 File)
270 -> debug(snapshot, 'Existing snapshot for ~w on ~w', [Path, File])
271 ; snapshot_file(Path, MD5,
272 [ access(write)
273 ],
274 File),
275 debug(snapshot, 'Saving snapshot for ~w to ~w', [Path, File]),
276 rdf_save_db(File, Path)
277 ),
278 assert(snapshot_file(File)).
279ensure_snapshot(_).
280
281
288
289load_snapshot(Source, Path) :-
290 statistics(cputime, T0),
291 rdf_load_db(Path),
292 statistics(cputime, T1),
293 Time is T1 - T0,
294 rdf_statistics(triples_by_graph(Source, Triples)),
295 rdf_md5(Source, MD5),
296 297 assert(rdf_db:rdf_source(Source, 1e12, Triples, MD5)),
298 print_message(informational,
299 rdf(loaded(Source, Triples, snapshot(Time)))),
300 assert(snapshot_file(Path)).
301
302
306
307snapshot_file(Path, MD5, Options, SnapShot) :-
308 file_base_name(Path, Base),
309 atomic_list_concat([Base, @, MD5], File),
310 absolute_file_name(snapshot(File),
311 [ extensions([trp])
312 | Options
313 ],
314 SnapShot).
315
316
323
324rdfe_snapshot_file(File) :-
325 snapshot_file(File).
326
327
328 331
332:- dynamic
333 system_ns/2. 334:- volatile
335 system_ns/2. 336
340
341rdfe_register_ns(Id, URI) :-
342 rdf_db:ns(Id, URI),
343 !.
344rdfe_register_ns(Id, URI) :-
345 save_system_ns,
346 rdfe_current_transaction(TID),
347 rdf_register_ns(Id, URI),
348 broadcast(rdf_ns(register(Id, URI))),
349 assert_action(TID, ns(register(Id, URI)), -, -, -),
350 journal(ns(TID, register(Id, URI))).
351
352rdfe_unregister_ns(Id, URI) :-
353 save_system_ns,
354 rdfe_current_transaction(TID),
355 retractall(rdf_db:ns(Id, URI)),
356 broadcast(rdf_ns(unregister(Id, URI))),
357 assert_action(TID, ns(unregister(Id, URI)), -, -, -),
358 journal(ns(TID, unregister(Id, URI))).
359
364
365rdfe_reset_ns :-
366 ( system_ns(_, _)
367 -> retractall(rdf_db:ns(Id, URI)),
368 forall(system_ns(Id, URI), assert(rdb_db:ns(Id, URI)))
369 ; true
370 ).
371
372save_system_ns :-
373 system_ns(_, _),
374 !. 375save_system_ns :-
376 forall(rdf_db:ns(Id, URI), assert(system_ns(Id, URI))).
377
378
379 382
388
389rdfe_transaction(Goal) :-
390 rdfe_transaction(Goal, []).
391rdfe_transaction(Goal, Name) :-
392 rdfe_begin_transaction(Name),
393 ( catch(Goal, E, true)
394 -> ( var(E)
395 -> check_file_protection(Error),
396 ( var(Error)
397 -> rdfe_commit
398 ; rdfe_rollback,
399 throw(Error)
400 )
401 ; rdfe_rollback,
402 throw(E)
403 )
404 ; rdfe_rollback,
405 fail
406 ).
407
412
413rdfe_begin_transaction(Name) :-
414 current_transaction(TID), 415 !,
416 append(TID, [1], TID2),
417 asserta(current_transaction(TID2)),
418 assert(transaction_name(TID2, Name)).
419rdfe_begin_transaction(Name) :- 420 flag(rdf_edit_tid, TID, TID+1),
421 asserta(current_transaction([TID])),
422 assert(transaction_name(TID, Name)).
423
424rdfe_current_transaction(TID) :-
425 current_transaction(TID),
426 !.
427rdfe_current_transaction(_) :-
428 throw(error(existence_error(rdf_transaction, _), _)).
429
430rdfe_commit :-
431 retract(current_transaction(TID)),
432 !,
433 retractall(undo_marker(_, _)),
434 ( rdfe_transaction_member(TID, _)
435 -> get_time(Time), 436 journal(commit(TID, Time)),
437 ( TID = [Id]
438 -> broadcast(rdf_transaction(Id))
439 ; true
440 )
441 ; true
442 ).
443
444rdfe_rollback :-
445 retract(current_transaction(TID)),
446 !,
447 journal(rollback(TID)),
448 rollback(TID).
449
456
457rollback(TID) :-
458 append(TID, _, Id),
459 ( retract(undo_log(Id, Action, Subject, Predicate, Object)),
460 ( rollback(Action, Subject, Predicate, Object)
461 -> fail
462 ; print_message(error,
463 rdf_undo_failed(undo(Action, Subject,
464 Predicate, Object))),
465 fail
466 )
467 ; true
468 ).
469
470rollback(assert(PayLoad), Subject, Predicate, Object) :-
471 !,
472 rdf_retractall(Subject, Predicate, Object, PayLoad).
473rollback(retract(PayLoad), Subject, Predicate, Object) :-
474 !,
475 rdf_assert(Subject, Predicate, Object, PayLoad).
476rollback(Action, Subject, Predicate, Object) :-
477 action(Action),
478 !,
479 rdf_update(Subject, Predicate, Object, Action).
480
481
482assert_action(TID, Action, Subject, Predicate, Object) :-
483 asserta(undo_log(TID, Action, Subject, Predicate, Object)).
484
489
490undo(TID) :-
491 append(TID, _, Id),
492 ( retract(undo_log(Id, Action, Subject, Predicate, Object)),
493 ( undo(Action, Subject, Predicate, Object)
494 -> fail
495 ; print_message(warning,
496 rdf_undo_failed(undo(Action, Subject,
497 Predicate, Object))),
498 fail
499 )
500 ; true
501 ).
502
503undo(assert(PayLoad), Subject, Predicate, Object) :-
504 !,
505 rdfe_retractall(Subject, Predicate, Object, PayLoad).
506undo(retract(PayLoad), Subject, Predicate, Object) :-
507 !,
508 rdfe_assert(Subject, Predicate, Object, PayLoad).
509undo(source(Old, New), Subject, Predicate, Object) :-
510 !,
511 rdfe_update(Subject, Predicate, Object, Old, source(New)).
512undo(ns(Action), -, -, -) :-
513 !,
514 ( Action = register(Id, URI)
515 -> rdfe_unregister_ns(Id, URI)
516 ; Action = unregister(Id, URI)
517 -> rdfe_register_ns(Id, URI)
518 ).
519undo(load_file(Path), -, -, -) :-
520 !,
521 rdfe_unload(Path).
522undo(unload_file(Path), -, -, -) :-
523 !,
524 rdfe_load(Path).
525undo(Action, Subject, Predicate, Object) :-
526 action(Action),
527 !,
528 rdfe_update(Subject, Predicate, Object, Action).
529
530action(subject(_)).
531action(predicate(_)).
532action(object(_)).
533
539
540rdfe_undo :-
541 undo_marker(undo, TID),
542 !,
543 ( undo_previous(TID, UnDone)
544 -> retractall(undo_marker(_, _)),
545 assert(undo_marker(undo, UnDone)),
546 broadcast(rdf_undo(undo, UnDone))
547 ; fail 548 ).
549rdfe_undo :-
550 retract(undo_marker(redo, _)),
551 !,
552 last_transaction(TID),
553 undo_previous(TID, UnDone),
554 assert(undo_marker(undo, UnDone)),
555 broadcast(rdf_undo(undo, UnDone)).
556rdfe_undo :-
557 last_transaction(TID),
558 undo_previous(TID, UnDone),
559 assert(undo_marker(undo, UnDone)),
560 broadcast(rdf_undo(undo, UnDone)).
561
562find_previous_undo(-1, _) :-
563 !,
564 fail.
565find_previous_undo(TID, TID) :-
566 undo_log([TID|_], _, _, _, _),
567 !.
568find_previous_undo(TID0, TID) :-
569 TID1 is TID0 - 1,
570 find_previous_undo(TID1, TID).
571
572undo_previous(TID, Undone) :-
573 find_previous_undo(TID, Undone),
574 rdfe_transaction(undo([Undone])).
575
576last_transaction(TID) :-
577 undo_log([TID|_], _, _, _, _),
578 !.
579
583
584rdfe_redo :-
585 ( retract(undo_marker(undo, _))
586 -> last_transaction(TID),
587 undo_previous(TID, UnDone),
588 assert(undo_marker(redo, UnDone)),
589 broadcast(rdf_undo(redo, UnDone))
590 ; retract(undo_marker(redo, TID))
591 -> undo_previous(TID, UnDone),
592 assert(undo_marker(redo, UnDone)),
593 broadcast(rdf_undo(redo, UnDone))
594 ; true
595 ).
596
597
604
605rdfe_can_redo(Redo) :-
606 undo_marker(undo, _),
607 !,
608 last_transaction(TID),
609 find_previous_undo(TID, Redo).
610rdfe_can_redo(Redo) :-
611 undo_marker(redo, TID),
612 find_previous_undo(TID, Redo).
613
614rdfe_can_undo(Undo) :- 615 undo_marker(undo, TID),
616 !,
617 find_previous_undo(TID, Undo).
618rdfe_can_undo(Undo) :- 619 last_transaction(TID),
620 find_previous_undo(TID, Undo).
621
625
626rdfe_transaction_name(TID, Name) :-
627 transaction_name(TID, Name),
628 Name \== [].
629
633
634rdfe_set_transaction_name(Name) :-
635 current_transaction(TID),
636 !,
637 assert(transaction_name(TID, Name)).
638
643
644rdfe_transaction_member(TID, Member) :-
645 ( integer(TID)
646 -> Id = [TID|_]
647 ; append(TID, _, Id)
648 ),
649 undo_log(Id, Action, Subject, Predicate, Object),
650 user_transaction_member(Action, Subject, Predicate, Object, Member).
651
652user_transaction_member(assert(_), Subject, Predicate, Object,
653 assert(Subject, Predicate, Object)) :- !.
654user_transaction_member(retract(_), Subject, Predicate, Object,
655 retract(Subject, Predicate, Object)) :- !.
656user_transaction_member(load_file(Path), -, -, -,
657 file(load(Path))) :- !.
658user_transaction_member(unload_file(Path), -, -, -,
659 file(unload(Path))) :- !.
660user_transaction_member(Update, Subject, Predicate, Object,
661 update(Subject, Predicate, Object, Update)).
662
663
664 667
668:- dynamic
669 rdf_source_permission/2, 670 rdf_current_default_file/2. 671
678
679rdfe_set_file_property(File, access(Access)) :-
680 !,
681 to_uri(File, URL),
682 retractall(rdf_source_permission(URL, _)),
683 assert(rdf_source_permission(URL, Access)),
684 broadcast(rdf_file_property(URL, access(Access))).
685rdfe_set_file_property(File, default(Type)) :-
686 to_uri(File, URL),
687 rdfe_set_file_property(URL, access(rw)), 688 retractall(rdf_current_default_file(_,_)),
689 assert(rdf_current_default_file(URL, Type)),
690 broadcast(rdf_file_property(URL, default(Type))).
691
692
697
698rdfe_get_file_property(FileOrURL, access(Access)) :-
699 ( ground(FileOrURL)
700 -> to_uri(FileOrURL, URL)
701 ; rdf_source(_DB, URL),
702 FileOrURL = URL
703 ),
704 ( rdf_source_permission(URL, Access0)
705 -> Access0 = Access
706 ; uri_file_name(URL, File),
707 access_file(File, write)
708 -> assert(rdf_source_permission(URL, rw)),
709 Access = rw
710 ; assert(rdf_source_permission(URL, ro)),
711 Access = ro
712 ).
713rdfe_get_file_property(FileOrURL, default(Default)) :-
714 ground(FileOrURL),
715 to_uri(FileOrURL, URL),
716 ( rdf_current_default_file(URL, Default)
717 -> true
718 ; FileOrURL = user,
719 Default = fallback
720 ).
721rdfe_get_file_property(URL, default(Default)) :-
722 ( rdf_current_default_file(URL, Default)
723 -> true
724 ; URL = user,
725 Default = fallback
726 ).
727
728
732
733check_file_protection(Error) :-
734 ( rdfe_get_file_property(File, access(ro)),
735 rdfe_is_modified(File)
736 -> Error = error(permission_error(modify, source, File), triple20)
737 ; true
738 ).
739
740
744
745to_uri(URL, URL) :-
746 uri_components(URL, Components),
747 uri_data(scheme, Components, Scheme),
748 nonvar(Scheme),
749 uri_scheme(Scheme),
750 !.
751to_uri(File, URL) :-
752 uri_file_name(URL, File).
753
754
755uri_scheme(file).
756uri_scheme(http).
757uri_scheme(https).
758uri_scheme(ftp).
759uri_scheme(ftps).
760
761
762 765
770
771rdfe_is_modified(Source) :-
772 rdf_source(Graph, Source),
773 rdf_graph_property(Graph, modified(true)).
774
775
776rdfe_clear_modified :-
777 forall(rdf_graph(File),
778 rdfe_clear_modified(File)).
779
783
784rdfe_clear_modified(Graph) :-
785 rdf_set_graph(Graph, modified(false)).
786
787
788 791
796
797rdfe_set_watermark(Name) :-
798 rdfe_current_transaction(TID),
799 assert_action(TID, watermark(Name), -, -, -),
800 journal(watermark(TID, Name)).
801
802
803 806
810
811rdfe_reset :-
812 rdfe_reset_journal,
813 rdfe_reset_ns,
814 rdfe_reset_undo,
815 rdf_reset_db,
816 broadcast(rdf_reset).
817
821
822rdfe_reset_journal :-
823 ( rdfe_current_journal(_)
824 -> rdfe_close_journal
825 ; true
826 ).
827
828rdfe_reset_undo :-
829 retractall(undo_log(_,_,_,_,_)),
830 retractall(current_transaction(_)),
831 retractall(transaction_name(_,_)),
832 retractall(undo_marker(_,_)),
833 retractall(snapshot_file(_)).
834
837
838:- at_halt(rdfe_reset_journal). 839
840
841 844
845journal_version(1).
846
860
861rdfe_open_journal(_, _) :- 862 journal(_, _, _),
863 !.
864rdfe_open_journal(File, read) :-
865 !,
866 absolute_file_name(File,
867 [ extensions([rdfj, '']),
868 access(read)
869 ],
870 Path),
871 rdfe_replay_journal(Path),
872 rdfe_clear_modified.
873rdfe_open_journal(File, write) :-
874 !,
875 absolute_file_name(File,
876 [ extensions([rdfj, '']),
877 access(write)
878 ],
879 Path),
880 open(Path, write, Stream, [close_on_abort(false)]),
881 assert(journal(Path, write, Stream)),
882 get_time(T),
883 journal_open(start, T).
884rdfe_open_journal(File, append) :-
885 working_directory(CWD, CWD),
886 absolute_file_name(File,
887 [ extensions([rdfj, '']),
888 relative_to(CWD),
889 access(write)
890 ],
891 Path),
892 ( exists_file(Path)
893 -> rdfe_replay_journal(Path),
894 rdfe_clear_modified,
895 get_time(T),
896 assert(journal(Path, append(T), []))
897 ; rdfe_open_journal(Path, write)
898 ).
899
900
901journal_open(Type, Time) :-
902 journal_comment(Type, Time),
903 SecTime is round(Time),
904 journal_version(Version),
905 Start =.. [ Type, [ time(SecTime),
906 version(Version)
907 ]
908 ],
909 journal(Start),
910 broadcast(rdf_journal(Start)).
911
(start, Time) :-
913 journal(_, _, Stream),
914 format_time(string(String), '%+', Time),
915 format(Stream,
916 '/* Triple20 Journal File\n\n \c
917 Created: ~w\n \c
918 Triple20 by Jan Wielemaker <wielemak@science.uva.nl>\n\n \c
919 EDIT WITH CARE!\n\c
920 */~n~n', [String]).
921journal_comment(resume, Time) :-
922 journal(_, _, Stream),
923 format_time(string(String), '%+', Time),
924 format(Stream,
925 '\n\c
926 /* Resumed: ~w\n\c
927 */~n~n', [String]).
928
933
934rdfe_close_journal :-
935 get_time(T),
936 SecTime is round(T),
937 journal(end([ time(SecTime)
938 ])),
939 retract(journal(_, Mode, Stream)),
940 ( Mode = append(_)
941 -> true
942 ; close(Stream)
943 ).
944
948
949rdfe_current_journal(Path) :-
950 journal(Path, _Mode, _Stream).
951
952journal(Term) :-
953 journal(Path, append(T), _),
954 !,
955 ( Term = end(_)
956 -> true
957 ; open(Path, append, Stream, [close_on_abort(false)]),
958 retractall(journal(Path, _, _)),
959 assert(journal(Path, append, Stream)),
960 journal_open(resume, T),
961 journal(Term)
962 ).
963journal(Term) :-
964 ( journal(_, _, Stream)
965 -> write_journal(Term, Stream),
966 flush_output(Stream)
967 ; broadcast(rdf_no_journal(Term))
968 ).
969
970write_journal(commit(TID, Time), Stream) :-
971 !,
972 format(Stream, 'commit(~q, ~2f).~n~n', [TID, Time]).
973write_journal(Term, Stream) :-
974 format(Stream, '~q.~n', [Term]).
975
976
982
983rdfe_replay_journal(File) :-
984 absolute_file_name(File,
985 [ extensions([rdfj, '']),
986 access(read)
987 ],
988 Path),
989 open(Path, read, Stream),
990 replay(Stream),
991 close(Stream).
992
993replay(Stream) :-
994 read(Stream, Term),
995 replay(Term, Stream).
996
997replay(end_of_file, _) :- !.
998replay(start(_Attributes), Stream) :-
999 !,
1000 read(Stream, Term),
1001 replay(Term, Stream).
1002replay(resume(_Attributes), Stream) :-
1003 !,
1004 read(Stream, Term),
1005 replay(Term, Stream).
1006replay(end(_Attributes), Stream) :-
1007 !,
1008 read(Stream, Term),
1009 replay(Term, Stream).
1010replay(Term0, Stream) :-
1011 replay_transaction(Term0, Stream),
1012 read(Stream, Term),
1013 replay(Term, Stream).
1014
1015replay_transaction(Term0, Stream) :-
1016 collect_transaction(Term0, Stream, Transaction, Last),
1017 ( committed_transaction(Last)
1018 -> replay_actions(Transaction)
1019 ; true
1020 ).
1021
1022collect_transaction(End, _, [], End) :-
1023 ends_transaction(End),
1024 !.
1025collect_transaction(A, Stream, [A|T], End) :-
1026 read(Stream, Term),
1027 collect_transaction(Term, Stream, T, End).
1028
1029committed_transaction(commit(_)).
1030committed_transaction(commit(_, _)).
1031
1032ends_transaction(end_of_file).
1033ends_transaction(commit(_)).
1034ends_transaction(commit(_, _)).
1035ends_transaction(rollback(_)).
1036ends_transaction(end(_)).
1037ends_transaction(start(_)).
1038
1039replay_actions([]).
1040replay_actions([H|T]) :-
1041 ( replay_action(H)
1042 -> replay_actions(T)
1043 ; print_message(warning,
1044 rdf_replay_failed(H)),
1045 ( debugging(journal)
1046 -> gtrace,
1047 replay_actions([H|T])
1048 ; replay_actions(T)
1049 )
1050 ).
1051
1052
1064
1065replay_action(retract(_, Subject, Predicate, Object, PayLoad)) :-
1066 rdf_retractall(Subject, Predicate, Object, PayLoad).
1067replay_action(assert(_, Subject, Predicate, Object, PayLoad)) :-
1068 rdf_assert(Subject, Predicate, Object, PayLoad).
1069replay_action(update(_, Subject, Predicate, Object, Action)) :-
1070 rdf_update(Subject, Predicate, Object, Action).
1071replay_action(update(_, Subject, Predicate, Object, Payload, Action)) :-
1072 rdf_update(Subject, Predicate, Object, Payload, Action).
1073replay_action(rdf_load(_, File, Options)) :-
1074 memberchk(md5(MD5), Options),
1075 snapshot_file(File, MD5,
1076 [ access(read),
1077 file_errors(fail)
1078 ],
1079 Path),
1080 !,
1081 debug(snapshot, 'Reloading snapshot ~w~n', [Path]),
1082 load_snapshot(File, Path).
1083replay_action(rdf_load(_, File, Options)) :-
1084 find_file(File, Options, Path),
1085 ( memberchk(triples(0), Options),
1086 memberchk(modified(Modified), Options)
1087 -> rdf_retractall(_,_,_,Path:_),
1088 retractall(rdf_db:rdf_source(Path, _, _, _)), 1089 rdf_md5(Path, MD5),
1090 assert(rdf_db:rdf_source(Path, Modified, 0, MD5))
1091 ; rdf_load(Path)
1092 ).
1093replay_action(rdf_unload(_, Source)) :-
1094 rdf_unload(Source).
1095replay_action(ns(_, register(ID, URI))) :-
1096 !,
1097 rdf_register_ns(ID, URI).
1098replay_action(ns(_, unregister(ID, URI))) :-
1099 retractall(rdf_db:ns(ID, URI)).
1100replay_action(watermark(_, _Name)) :-
1101 true.
1102
1103find_file(File, _, File) :-
1104 exists_file(File),
1105 !.
1106find_file(File, Options, Path) :-
1107 memberchk(pwd(PWD), Options),
1108 make_path(File, PWD, Path),
1109 exists_file(Path),
1110 !.
1111
1115
1116make_path(File, PWD, Path) :-
1117 atom_concat(PWD, /, PWD2),
1118 atom_concat(PWD2, Path, File).
1119
1120
1121 1124
1125:- multifile
1126 prolog:message/3,
1127 user:message_hook/3. 1128
1130
1131prolog:message(rdf_replay_failed(Term)) -->
1132 [ 'RDFDB: Replay of ~p failed'-[Term] ].
1133prolog:message(rdf_undo_failed(Term)) -->
1134 [ 'RDFDB: Undo of ~p failed'-[Term] ]