1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2003-2013, University of Amsterdam 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(rdf_edit, 37 [ rdfe_assert/3, % Sub, Pred, Obj 38 rdfe_assert/4, % Sub, Pred, Obj, PayLoad 39 rdfe_retractall/3, % Sub, Pred, Obj 40 rdfe_retractall/4, % Sub, Pred, Obj, PayLoad 41 rdfe_update/4, % Sub, Pred, Obj, +Action 42 rdfe_update/5, % Sub, Pred, Obj, +PayLoad, +Action 43 rdfe_load/1, % +File 44 rdfe_load/2, % +File, +Options 45 rdfe_delete/1, % +Resource 46 47 rdfe_register_ns/2, % +Id, +URI 48 rdfe_unregister_ns/2, % +Id, +URI 49 50 rdfe_reset/0, % clear everything 51 52 rdfe_transaction/1, % :Goal 53 rdfe_transaction/2, % :Goal, +Name 54 rdfe_transaction_member/2, % +Transactions, -Action 55 rdfe_transaction_name/2, % +Transactions, -Name 56 rdfe_set_transaction_name/1,% +Name 57 58 rdfe_set_watermark/1, % +Name 59 60 rdfe_undo/0, % 61 rdfe_redo/0, 62 rdfe_can_undo/1, % -TID 63 rdfe_can_redo/1, % -TID 64 65 rdfe_set_file_property/2, % +File, +Property 66 rdfe_get_file_property/2, % ?File, ?Property 67 68 rdfe_is_modified/1, % ?File 69 rdfe_clear_modified/1, % +File 70 71 rdfe_open_journal/2, % +File, +Mode 72 rdfe_close_journal/0, 73 rdfe_replay_journal/1, % +File 74 rdfe_current_journal/1, % -Path 75 76 rdfe_snapshot_file/1 % -File 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( ), 86 rdfe_transaction( , ). 87 88:- predicate_options(rdfe_load/2, 2, 89 [pass_to(rdf_db:rdf_load/2, 2)]). 90 91:- dynamic 92 undo_log/5, % TID, Action, Subj, Pred, Obj 93 current_transaction/1, % TID 94 transaction_name/2, % TID, Name 95 undo_marker/2, % Mode, TID 96 journal/3, % Path, Mode, Stream 97 snapshot_file/1. % File
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 /******************************* 124 * BASIC EDIT OPERATIONS * 125 *******************************/ 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).
! subject(+Subject)
! predicate(+Predicate)
! object(+Object)
! source(+Source)
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) % source is used internally 181 ), 182 journal(update(TID, Subject, Predicate, Object, PayLoad, Action)).
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 /******************************* 200 * FILE HANDLING * 201 *******************************/
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)).
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(_).
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 % 1e10: modified far in the future
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)).
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).
324rdfe_snapshot_file(File) :- 325 snapshot_file(File). 326 327 328 /******************************* 329 * NAMESPACE HANDLING * 330 *******************************/ 331 332:- dynamic 333 system_ns/2. 334:- volatile 335 system_ns/2.
rdf_register_ns(Id, URI)
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 360% rdfe_register_ns/0 361% 362% Reset namespaces to the state they where before usage of the 363% rdf_edit layer. 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 !. % already done 375save_system_ns :- 376 forall(rdf_db:ns(Id, URI), assert(system_ns(Id, URI))). 377 378 379 /******************************* 380 * TRANSACTIONS * 381 *******************************/
389rdfe_transaction(Goal) :- 390 rdfe_transaction(, []). 391rdfe_transaction(Goal, Name) :- 392 rdfe_begin_transaction(Name), 393 ( catch(, 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 ).
413rdfe_begin_transaction(Name) :- 414 current_transaction(TID), % nested transaction 415 !, 416 append(TID, [1], TID2), 417 asserta(current_transaction(TID2)), 418 assert(transaction_name(TID2, Name)). 419rdfe_begin_transaction(Name) :- % toplevel transaction 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), % transaction is not empty 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).
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)).
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(_)).
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 % start of undo log 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 !.
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 ).
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) :- % continue undo 615 undo_marker(undo, TID), 616 !, 617 find_previous_undo(TID, Undo). 618rdfe_can_undo(Undo) :- % start undo 619 last_transaction(TID), 620 find_previous_undo(TID, Undo).
626rdfe_transaction_name(TID, Name) :-
627 transaction_name(TID, Name),
628 Name \== [].
634rdfe_set_transaction_name(Name) :-
635 current_transaction(TID),
636 !,
637 assert(transaction_name(TID, Name)).
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 /******************************* 665 * PROTECTION * 666 *******************************/ 667 668:- dynamic 669 rdf_source_permission/2, % file, ro/rw 670 rdf_current_default_file/2. % file, all/fallback
access(ro/rw)
default(all/fallback)
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)), % must be writeable 688 retractall(rdf_current_default_file(_,_)), 689 assert(rdf_current_default_file(URL, Type)), 690 broadcast(rdf_file_property(URL, default(Type))).
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 ; access_file(URL, write) 707 -> assert(rdf_source_permission(URL, rw)), 708 Access = rw 709 ; assert(rdf_source_permission(URL, ro)), 710 Access = ro 711 ). 712rdfe_get_file_property(FileOrURL, default(Default)) :- 713 ground(FileOrURL), 714 to_uri(FileOrURL, URL), 715 ( rdf_current_default_file(URL, Default) 716 -> true 717 ; FileOrURL = user, 718 Default = fallback 719 ). 720rdfe_get_file_property(URL, default(Default)) :- 721 ( rdf_current_default_file(URL, Default) 722 -> true 723 ; URL = user, 724 Default = fallback 725 ).
732check_file_protection(Error) :-
733 ( rdfe_get_file_property(File, access(ro)),
734 rdfe_is_modified(File)
735 -> Error = error(permission_error(modify, source, File), triple20)
736 ; true
737 ).
744to_uri(URL, URL) :- 745 uri_components(URL, Components), 746 uri_data(scheme, Components, Scheme), 747 nonvar(Scheme), 748 uri_scheme(Scheme), 749 !. 750to_uri(File, URL) :- 751 uri_file_name(URL, File). 752 753 754uri_scheme(file). 755uri_scheme(http). 756uri_scheme(https). 757uri_scheme(ftp). 758uri_scheme(ftps). 759 760 761 /******************************* 762 * MODIFIED * 763 *******************************/
770rdfe_is_modified(Source) :- 771 rdf_source(Graph, Source), 772 rdf_graph_property(Graph, modified(true)). 773 774 775rdfe_clear_modified :- 776 forall(rdf_graph(File), 777 rdfe_clear_modified(File)).
783rdfe_clear_modified(Graph) :- 784 rdf_set_graph(Graph, modified(false)). 785 786 787 /******************************* 788 * WATERMARKS * 789 *******************************/
796rdfe_set_watermark(Name) :- 797 rdfe_current_transaction(TID), 798 assert_action(TID, watermark(Name), -, -, -), 799 journal(watermark(TID, Name)). 800 801 802 /******************************* 803 * RESET * 804 *******************************/
810rdfe_reset :-
811 rdfe_reset_journal,
812 rdfe_reset_ns,
813 rdfe_reset_undo,
814 rdf_reset_db,
815 broadcast(rdf_reset).
821rdfe_reset_journal :- 822 ( rdfe_current_journal(_) 823 -> rdfe_close_journal 824 ; true 825 ). 826 827rdfe_reset_undo :- 828 retractall(undo_log(_,_,_,_,_)), 829 retractall(current_transaction(_)), 830 retractall(transaction_name(_,_)), 831 retractall(undo_marker(_,_)), 832 retractall(snapshot_file(_)). 833 834% close possible open journal at exit. Using a Prolog hook 835% guarantees closure, even for most crashes. 836 837:- at_halt(rdfe_reset_journal). 838 839 840 /******************************* 841 * JOURNALLING * 842 *******************************/ 843 844journal_version(1).
860rdfe_open_journal(_, _) :- % already open 861 journal(_, _, _), 862 !. 863rdfe_open_journal(File, read) :- 864 !, 865 absolute_file_name(File, 866 [ extensions([rdfj, '']), 867 access(read) 868 ], 869 Path), 870 rdfe_replay_journal(Path), 871 rdfe_clear_modified. 872rdfe_open_journal(File, write) :- 873 !, 874 absolute_file_name(File, 875 [ extensions([rdfj, '']), 876 access(write) 877 ], 878 Path), 879 open(Path, write, Stream, [close_on_abort(false)]), 880 assert(journal(Path, write, Stream)), 881 get_time(T), 882 journal_open(start, T). 883rdfe_open_journal(File, append) :- 884 working_directory(CWD, CWD), 885 absolute_file_name(File, 886 [ extensions([rdfj, '']), 887 relative_to(CWD), 888 access(write) 889 ], 890 Path), 891 ( exists_file(Path) 892 -> rdfe_replay_journal(Path), 893 rdfe_clear_modified, 894 get_time(T), 895 assert(journal(Path, append(T), [])) 896 ; rdfe_open_journal(Path, write) 897 ). 898 899 900journal_open(Type, Time) :- 901 journal_comment(Type, Time), 902 SecTime is round(Time), 903 journal_version(Version), 904 Start =.. [ Type, [ time(SecTime), 905 version(Version) 906 ] 907 ], 908 journal(Start), 909 broadcast(rdf_journal(Start)). 910 911journal_comment(start, Time) :- 912 journal(_, _, Stream), 913 format_time(string(String), '%+', Time), 914 format(Stream, 915 '/* Triple20 Journal File\n\n \c 916 Created: ~w\n \c 917 Triple20 by Jan Wielemaker <wielemak@science.uva.nl>\n\n \c 918 EDIT WITH CARE!\n\c 919 */~n~n', [String]). 920journal_comment(resume, Time) :- 921 journal(_, _, Stream), 922 format_time(string(String), '%+', Time), 923 format(Stream, 924 '\n\c 925 /* Resumed: ~w\n\c 926 */~n~n', [String]).
933rdfe_close_journal :-
934 get_time(T),
935 SecTime is round(T),
936 journal(end([ time(SecTime)
937 ])),
938 retract(journal(_, Mode, Stream)),
939 ( Mode = append(_)
940 -> true
941 ; close(Stream)
942 ).
948rdfe_current_journal(Path) :- 949 journal(Path, _Mode, _Stream). 950 951journal(Term) :- 952 journal(Path, append(T), _), 953 !, 954 ( Term = end(_) 955 -> true 956 ; open(Path, append, Stream, [close_on_abort(false)]), 957 retractall(journal(Path, _, _)), 958 assert(journal(Path, append, Stream)), 959 journal_open(resume, T), 960 journal(Term) 961 ). 962journal(Term) :- 963 ( journal(_, _, Stream) 964 -> write_journal(Term, Stream), 965 flush_output(Stream) 966 ; broadcast(rdf_no_journal(Term)) 967 ). 968 969write_journal(commit(TID, Time), Stream) :- 970 !, 971 format(Stream, 'commit(~q, ~2f).~n~n', [TID, Time]). 972write_journal(Term, Stream) :- 973 format(Stream, '~q.~n', [Term]).
982rdfe_replay_journal(File) :- 983 absolute_file_name(File, 984 [ extensions([rdfj, '']), 985 access(read) 986 ], 987 Path), 988 open(Path, read, Stream), 989 replay(Stream), 990 close(Stream). 991 992replay(Stream) :- 993 read(Stream, Term), 994 replay(Term, Stream). 995 996replay(end_of_file, _) :- !. 997replay(start(_Attributes), Stream) :- 998 !, 999 read(Stream, Term), 1000 replay(Term, Stream). 1001replay(resume(_Attributes), Stream) :- 1002 !, 1003 read(Stream, Term), 1004 replay(Term, Stream). 1005replay(end(_Attributes), Stream) :- 1006 !, 1007 read(Stream, Term), 1008 replay(Term, Stream). 1009replay(Term0, Stream) :- 1010 replay_transaction(Term0, Stream), 1011 read(Stream, Term), 1012 replay(Term, Stream). 1013 1014replay_transaction(Term0, Stream) :- 1015 collect_transaction(Term0, Stream, Transaction, Last), 1016 ( committed_transaction(Last) 1017 -> replay_actions(Transaction) 1018 ; true 1019 ). 1020 1021collect_transaction(End, _, [], End) :- 1022 ends_transaction(End), 1023 !. 1024collect_transaction(A, Stream, [A|T], End) :- 1025 read(Stream, Term), 1026 collect_transaction(Term, Stream, T, End). 1027 1028committed_transaction(commit(_)). 1029committed_transaction(commit(_, _)). 1030 1031ends_transaction(end_of_file). 1032ends_transaction(commit(_)). 1033ends_transaction(commit(_, _)). 1034ends_transaction(rollback(_)). 1035ends_transaction(end(_)). 1036ends_transaction(start(_)). 1037 1038replay_actions([]). 1039replay_actions([H|T]) :- 1040 ( replay_action(H) 1041 -> replay_actions(T) 1042 ; print_message(warning, 1043 rdf_replay_failed(H)), 1044 ( debugging(journal) 1045 -> gtrace, 1046 replay_actions([H|T]) 1047 ; replay_actions(T) 1048 ) 1049 ).
1064replay_action(retract(_, Subject, Predicate, Object, PayLoad)) :- 1065 rdf_retractall(Subject, Predicate, Object, PayLoad). 1066replay_action(assert(_, Subject, Predicate, Object, PayLoad)) :- 1067 rdf_assert(Subject, Predicate, Object, PayLoad). 1068replay_action(update(_, Subject, Predicate, Object, Action)) :- 1069 rdf_update(Subject, Predicate, Object, Action). 1070replay_action(update(_, Subject, Predicate, Object, Payload, Action)) :- 1071 rdf_update(Subject, Predicate, Object, Payload, Action). 1072replay_action(rdf_load(_, File, Options)) :- 1073 memberchk(md5(MD5), Options), 1074 snapshot_file(File, MD5, 1075 [ access(read), 1076 file_errors(fail) 1077 ], 1078 Path), 1079 !, 1080 debug(snapshot, 'Reloading snapshot ~w~n', [Path]), 1081 load_snapshot(File, Path). 1082replay_action(rdf_load(_, File, Options)) :- 1083 find_file(File, Options, Path), 1084 ( memberchk(triples(0), Options), 1085 memberchk(modified(Modified), Options) 1086 -> rdf_retractall(_,_,_,Path:_), 1087 retractall(rdf_db:rdf_source(Path, _, _, _)), % TBD: move 1088 rdf_md5(Path, MD5), 1089 assert(rdf_db:rdf_source(Path, Modified, 0, MD5)) 1090 ; rdf_load(Path) 1091 ). 1092replay_action(rdf_unload(_, Source)) :- 1093 rdf_unload(Source). 1094replay_action(ns(_, register(ID, URI))) :- 1095 !, 1096 rdf_register_ns(ID, URI). 1097replay_action(ns(_, unregister(ID, URI))) :- 1098 retractall(rdf_db:ns(ID, URI)). 1099replay_action(watermark(_, _Name)) :- 1100 true. 1101 1102find_file(File, _, File) :- 1103 exists_file(File), 1104 !. 1105find_file(File, Options, Path) :- 1106 memberchk(pwd(PWD), Options), 1107 make_path(File, PWD, Path), 1108 exists_file(Path), 1109 !.
1115make_path(File, PWD, Path) :- 1116 atom_concat(PWD, /, PWD2), 1117 atom_concat(PWD2, Path, File). 1118 1119 1120 /******************************* 1121 * MESSAGES * 1122 *******************************/ 1123 1124:- multifile 1125 prolog:message/3, 1126 user:message_hook/3. 1127 1128% Catch messages. 1129 1130prologmessage(rdf_replay_failed(Term)) --> 1131 [ 'RDFDB: Replay of ~p failed'-[Term] ]. 1132prologmessage(rdf_undo_failed(Term)) --> 1133 [ 'RDFDB: Undo of ~p failed'-[Term] ]
RDF edit layer
This library provides a number of functions on top of the rdf_db module: