(in-package #:db.agraph.user)

#|

This example shows that using a federated triple store is just
as simple as using a regular one. As data, we take Gov.ntriples 
and split it into two pieces (Gov-1.ntriples and Gov-2.ntriples).
Then we build three disk-based persistent triple-stores: gov, gov-1 
and gov-2. Finally, we federate gov-1 and gov-2 into fed-12:

  (federate-triple-stores "fed-21" (list "gov-1" "gov-2"))

Now we can query either the entire store (using gov), either half
of the store (using gov-1 or gov-2) or the federated-store (using
fed-12).

|#

(defparameter *source-directory* "/repository/data/")
(defparameter *target-directory* "/tmp/")

(defun shared-setup ()
  (register-namespace "cyc" "http://www.cyc.com/2002/04/08/cyc#")
  )

(defun create-example-triple-stores (&key 
				     (source-directory *source-directory*)
				     (target-directory *target-directory*))
  (shared-setup)
  (flet ((source-path (name)
	   (make-pathname
	    :name name :type "ntriples" :defaults source-directory))
	 (target-path (name)
	   (make-pathname 
	    :name name :defaults target-directory)))
    (create-triple-store (target-path "gov"))
    (load-ntriples (source-path "Gov"))
    (index-all-triples)

    (create-triple-store (target-path "gov-1"))
    (load-ntriples (source-path "Gov-1"))
    (index-all-triples)

    (create-triple-store (target-path "gov-2"))
    (load-ntriples (source-path "Gov-2"))
    (index-all-triples)))

(defun open-example-triple-stores (&key 
				     (target-directory *target-directory*))
  (shared-setup)
  (flet ((target-path (name)
	   (make-pathname 
	    :name name :defaults target-directory)))
    (open-triple-store (target-path "gov"))
    (open-triple-store (target-path "gov-1"))
    (open-triple-store (target-path "gov-2"))
    (federate-triple-stores "fed-12" (list "gov-1" "gov-2"))))

;; Create the stores 
(create-example-triple-stores)

;; Open the stores
(open-example-triple-stores)

;;; triple-count

(format t "Gov: ~:d, Federated Gov: ~:d."
	(triple-count :db "Gov") (triple-count :db "fed-12"))

;;; Tell me about CargoShips

(count-cursor 
 (get-triples 
  :p !rdf:type 
  :o !cyc:CargoShip
  :db "gov")) 
;==> 3

(count-cursor 
 (get-triples 
  :p !rdf:type 
  :o !cyc:CargoShip
  :db "fed-12"))
;===> 3

(print-triples 
 (get-triples 
  :p !rdf:type 
  :o !cyc:CargoShip
  :db "gov"))
 
(print-triples 
 (get-triples 
  :p !rdf:type 
  :o !cyc:CargoShip
  :db "fed-12"))

;;; prolog select works too
;; 
;; Here, I chosen a query that can only be answered by looking in
;; both stores.

(defun find-arg66 (triple-store-name)
  (with-triple-store (db triple-store-name)
    (select0 (?p ?o)
      (q- !<http://www.cyc.com/2002/04/08/cyc#arg6GenlAttribute> ?p ?o))))

(length (find-arg66 "gov"))		;8
(length (find-arg66 "gov-1"))		;4
(length (find-arg66 "gov-2"))		;4
(length (find-arg66 "fed-12"))		;8 !

;; at very close to the _same_ speed
(defun speed-test ()
  (print "Gov")
  (time (loop repeat 1000 do (find-arg66 (find-triple-store "gov"))))
  (terpri)
  (print "Federated")
  (time (loop repeat 1000 do (find-arg66 (find-triple-store "fed-12")))))

(compile 'speed-test)
(speed-test)

#|
"Gov" 
; cpu time (non-gc) 1,300 msec user, 20 msec system
; cpu time (gc)     130 msec user, 0 msec system
; cpu time (total)  1,430 msec user, 20 msec system
; real time  1,521 msec
; space allocation:
;  3,025,031 cons cells, 37,964,864 other bytes, 0 static bytes

"Federated" 
; cpu time (non-gc) 1,370 msec user, 20 msec system
; cpu time (gc)     140 msec user, 0 msec system
; cpu time (total)  1,510 msec user, 20 msec system
; real time  1,723 msec
; space allocation:
;  3,099,184 cons cells, 40,213,112 other bytes, 23,736 static bytes
|#

