Coverage report: /development/source/library/org/datagraph/spocq-shard/src/shell/metadata-sync.lisp

KindCoveredAll%
expression0445 0.0
branch026 0.0
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;; -*- Mode: lisp; Syntax: ansi-common-lisp; Base: 10; Package: org.datagraph.spocq.implementation; -*-
2
 
3
 (in-package :org.datagraph.spocq.implementation)
4
 
5
 #|
6
 synchronize account and repository metadata from mysql to rdf system repositories
7
 in reaction to indications left by the web ui.
8
 
9
 when an account or repository changes, the respective rails ui 'synchronize' operator
10
 invokes the to replace the previous system repository content with statements generated from the new state.
11
 
12
 the arguments indicate the specific account or repository affected and this code synchronizes the
13
 respective system repository state by
14
 - using the current metadata/{system,account}.nt to remove the old state
15
 - displacing metadata/ to metadata.bak/
16
 - generating the new state from the mysql version
17
 - importing the new state
18
 - saving the new state in a recreated `metadata/`repository.
19
 
20
 
21
 sbcl --core sbcl-spocq.core
22
 (sb-ext:save-lisp-and-die "metadata-sync" :executable t :toplevel #'spocq.i::main-metadata-sync)
23
 
24
 to run for all accounts
25
 
26
 (main-metadata-sync :admins "/srv/dydra/config/admins.txt")
27
 |#
28
 
29
 (defun account-directory (account)
30
   (merge-pathnames (make-pathname :directory `(:relative "accounts" ,account))
31
                    *metadata-root-pathname*))
32
 (defun account-metadata-directory (account)
33
   (merge-pathnames (make-pathname :directory `(:relative "accounts" ,account ,*metadata-file-name*))
34
                    *metadata-root-pathname*))
35
 (defun account-repository-directory (account repository)
36
   ;; this returns the symbolic link located relative to the account, not the actual repository directory
37
   (merge-pathnames (make-pathname :directory `(:relative "accounts" ,account "repositories")
38
                                   :name repository)
39
                    *metadata-root-pathname*))
40
 (defun account-repository-path (account repository)
41
   ;; this returns the symbolic link located relative to the account, not the actual repository directory
42
   (merge-pathnames (make-pathname :directory `(:relative "accounts" ,account "repositories")
43
                                   :name repository)
44
                    *metadata-root-pathname*))
45
 (defun repository-metadata-directory (account repository)
46
   (let ((link (account-repository-directory account repository)))
47
     (when (probe-file link)
48
       ;; resolve the symbolic link to the uuid value and combine that with the repository tree.
49
       (merge-pathnames (make-pathname :directory `(:relative "repositories" ,(sb-posix:readlink link), *metadata-file-name*))
50
                        *metadata-root-pathname*))))
51
 
52
 (defun main-metadata-sync (&rest args &key
53
                            (account (getarg "--account"))
54
                            (repository (getarg "--repository"))
55
                            (admins (getarg "--admins"))
56
                            (clear (getarg "--clear"))
57
                            &allow-other-keys)
58
 
59
   (handler-bind ((serious-condition
60
                   (lambda (condition)
61
                     (print-stacktrace *trace-output*)
62
                     (log-stacktrace "main-metadata-sync: ~s -> ~a." args condition)
63
                     (format *standard-output* "~a~%" condition)
64
                     (log-error "main-metadata-sync: exiting")
65
                     (exit-lisp 70))))
66
       ;; need to generate the task id as, to this point, the store connection has not been initialized
67
       (with-command-line-configuration ((list* :task-id (prin1-to-string (uuid:make-v1-uuid)) args))
68
         (setq *start-timestamp* (iso-time))
69
         (initialize-spocq :title (or (getarg "--title") "metadata"))
70
         (log-info "Start metadata synchronization: ~a" args)
71
         (when account (setf account (string-downcase account)))
72
         (when repository (setf repository (string-downcase repository)))
73
         (if account
74
             ;; if the account was specified, operate on its constituents
75
             (if (and repository (not (equal repository "*")))
76
                 ;; if, of those, a repository was specified, then just its metadata
77
                 (let ((metadata-directory (repository-metadata-directory account repository)))
78
                   (if metadata-directory
79
                       (synchronize-repository-metadata account repository metadata-directory)
80
                       (log-warn "no catalog directory present for repository: ~s ~s" account repository)))
81
                 ;; without a repository, operate on just the account
82
                 (let ((metadata-directory (account-metadata-directory account)))
83
                   (if metadata-directory
84
                       (synchronize-account-metadata account metadata-directory :clear clear :repositories (equal repository "*"))
85
                       (log-warn "no catalog directory present for account: ~s" account))))
86
             (if repository
87
                 (error "repository requires also the account.")
88
                 (loop for account in (mysql-account-list)
89
                   for account-directory = (account-directory account)
90
                   if (probe-file account-directory) ; double check
91
                   do (progn
92
                        ;; clear only when reconstructing the entire account
93
                        (let ((metadata-directory (account-metadata-directory account)))
94
                          (if metadata-directory
95
                              (synchronize-account-metadata account (account-metadata-directory account) :clear clear :repositories t)
96
                              (log-warn "no catalog directory present for account: ~s" account)))
97
                        ;; retained for posterity, this was necessary when each
98
                        ;; revision made its own lmdb environment. with that the
99
                        ;; address space grew into peta-bytes and eventually
100
                        ;; malloc failed:
101
                        ;; operating on all accounts, must clean up
102
                        #+(or)
103
                        (loop for r being each hash-value of *repositories*
104
                          using (hash-key k)
105
                          when (and (typep r 'repository-revision)
106
                                    ;; (not (equal (repository-id r) "system/system"))
107
                                    )
108
                          do (let ((lr (repository-lmdb-repository r)))
109
                               (when lr
110
                                 (print (list :system (repository "system/system")
111
                                              (repository-lmdb-repository (repository "system/system"))
112
                                              (LMDB::%HANDLE (repository-lmdb-repository (repository "system/system")))))
113
                                 (print (list :closing r lr (LMDB::%HANDLE lr)))
114
                                 (rlmdb:close-repository lr)
115
                                 (remhash k *repositories*)
116
                                 t))))
117
                   else do (log-notice "anomalous mysql account: ~s" account))))
118
         (when admins
119
           (log-info "synchronizing admins: ~a" admins)
120
           (when (and (stringp admins(ignore-errors (probe-file admins)))
121
             (setf admins (read-file admins)))
122
           (admin-metadata-sync (append '("system" "administrator") (split-string admins #(#\space #\return #\linefeed))))))))
123
 
124
 
125
 (defun admin-metadata-sync (admin-name-list)
126
   "Remove any existing admins and replace those entries with assertiosn for the supplied names."
127
   
128
   (let* ((site-uri (site-namespace))
129
          (old-admin-metadata (loop for (owner-uri) in (run-sparql-internal "select ?user where {graph <urn:dydra:users> { ?user <http://rdfs.org/sioc/ns#administrator_of> ?site } }"
130
                                                                  :repository-id *system-repository-id*
131
                                                                  :agent (system-agent))
132
                                collect `(spocq.a:|quad| ,owner-uri |sioc|:|administrator_of| ,site-uri |urn:dydra|:|users|)))
133
          (new-admin-metadata
134
           (cons `(spocq.a:|quad| <http://dydra.com/users/system> |sioc|:|administrator_of| ,site-uri |urn:dydra|:|users|)
135
                 (loop for admin-name in admin-name-list
136
                   for owner-uri = (intern-iri (format nil "http://dydra.com/users/~a" admin-name))
137
                   collect `(spocq.a:|quad| ,owner-uri |sioc|:|administrator_of| ,site-uri |urn:dydra|:|users|)))))
138
     ;; must perform distinct transactions
139
     (with-open-transaction (*system-repository-id* :normal-disposition :commit :read-only-p nil)
140
       (repository-delete-field *transaction* old-admin-metadata)
141
       (commit-transaction *transaction*))
142
     (with-open-transaction (*system-repository-id* :normal-disposition :commit :read-only-p nil)
143
       (repository-insert-field *transaction* new-admin-metadata)
144
       (commit-transaction *transaction*))))
145
 #+(or)
146
 (progn
147
 (admin-metadata-sync (split-string (read-file "/srv/dydra/config/admins.txt") #(#\space #\return #\linefeed)))
148
 (run-sparql-internal "select ?graph ?user ?site where {graph ?graph { ?user <http://rdfs.org/sioc/ns#administrator_of> ?site } }"
149
                                                                  :repository-id *system-repository-id*
150
                                                                  :agent (system-agent)))
151
 
152
 (defun replace-nquads-file (pathname metadata)
153
   (let ((bak-pathname (merge-pathnames (make-pathname :type "bak") pathname)))
154
     (ensure-directories-exist pathname)
155
     (when (probe-file pathname)
156
       (rename-file pathname bak-pathname))
157
     (with-open-file (metadata-stream pathname :direction :output :if-exists :error :if-does-not-exist :create)
158
       (values (write-rdf-nquads (mapcar #'rest metadata) metadata-stream)))))
159
 
160
 (defgeneric synchronize-account-metadata (account directory &key clear repositories)
161
   (:documentation "Replace the account metadata as part of a blanket synchronization.
162
    Iff there is metadata present, delete that from the respective system repository.
163
    Then, displace it to .bak and add the new content")
164
   (:method ((account string) directory &key (clear nil) (repositories nil))
165
     (let* ((system-repository-id (make-repository-id :account-name "system" :repository-name "system"))
166
            (account-repository-id (make-repository-id :account-name account :repository-name "system"))
167
            (system-pathname (merge-pathnames (make-pathname :name "system" :type "nt") directory))
168
            (account-pathname (merge-pathnames (make-pathname :name "account" :type "nt") directory)))
169
       (unless (repository-exists-p account-repository-id)
170
         (unless (create-repository account-repository-id)
171
           (error "cannot create repository: ~s" account-repository-id)))
172
       (let ((metadata-statements (mysql-account-metadata-statements account)))
173
         (if metadata-statements
174
             (destructuring-bind (&key ((:system system-metadata) nil) ((:account account-metadata) nil))
175
                                 metadata-statements
176
               (with-open-repository (system-repository-id :normal-disposition :commit :read-only-p nil)
177
                 (when (probe-file system-pathname)
178
                   (spocq.e:delete-data system-pathname))
179
                 (spocq.e:insert-data system-metadata)
180
                 (replace-nquads-file system-pathname system-metadata))
181
               (with-open-repository (account-repository-id :normal-disposition :commit :read-only-p nil)
182
                 (cond (clear
183
                        (repository-clear-graph *transaction* :all))
184
                       ((probe-file account-pathname)
185
                        (spocq.e:delete-data account-pathname)))
186
                 (spocq.e:insert-data account-metadata)
187
                 (replace-nquads-file account-pathname account-metadata)))
188
             (log-notice "anomalous mysql account metadata: ~s" account))))
189
     (when repositories
190
       (loop for repository-path in (directory (account-repository-path account :wild))
191
         for repository = (pathname-name repository-path)
192
         do (synchronize-repository-metadata account repository (repository-metadata-directory account repository))))
193
     (log-notice "synchronized account metadata: ~s: ~s" account directory)
194
     directory))
195
 
196
 (defgeneric synchronize-repository-metadata (account repository directory)
197
   (:documentation "Replace the repository metadata as part of a blanket synchronization.
198
    Iff there is a .bak file present, delete that from the respective system repository.
199
    Then add the new content")
200
   (:method ((account string) (repository string) directory)
201
     (let* ((system-repository-id (make-repository-id :account-name "system" :repository-name "system"))
202
            (account-repository-id (make-repository-id :account-name account :repository-name "system"))
203
            (system-pathname (merge-pathnames (make-pathname :name "system" :type "nt") directory))
204
            (account-pathname (merge-pathnames (make-pathname :name "account" :type "nt") directory))
205
            (account-identifier (compute-account-identifier account))
206
            (repository-uri (compute-repository-identifier account repository))
207
            (old-repository-uri (intern-iri (format nil "http://~a/~a/~a" (site-name) account repository))))
208
       (unless (repository-exists-p account-repository-id)
209
         (unless (create-repository account-repository-id)
210
           (error "cannot create repository: ~s" account-repository-id)))
211
       (let ((metadata-statements (mysql-repository-metadata-statements account repository))
212
             (account-repository-settings (remove repository-uri (account-settings-statements account)
213
                                                  :key #'second :test-not #'equalp)))
214
         (if metadata-statements
215
             ;; delete the known metadata by subject and graph (see delete-repository-metadata)
216
             ;; insert the generated statements
217
             ;; retain them for reference in external files
218
             (destructuring-bind ((&key ((:system system-metadata) nil) ((:account account-metadata) nil)))
219
                                 metadata-statements  
220
               (with-open-repository (system-repository-id :normal-disposition :commit :read-only-p nil)
221
                 ;; (when (probe-file system-pathname) (spocq.e:delete-data system-pathname))
222
                 ;; delete the repository as subject
223
                 (let ((existing-field (repository-match-field *transaction* account-identifier repository-uri '?::p '?::o)))
224
                   (when existing-field
225
                     (repository-delete-field *transaction* existing-field)))
226
                 (spocq.e:insert-data system-metadata)
227
                 (replace-nquads-file system-pathname system-metadata))
228
               (with-open-repository (account-repository-id :normal-disposition :commit :read-only-p nil)
229
                 ;; (when (probe-file account-pathname) (spocq.e:delete-data account-pathname))
230
                 ;; just delete the repository graph explicitly
231
                 (repository-clear-graph *transaction* repository-uri)
232
                 ;; also the alternative repository designator
233
                 (repository-clear-graph *transaction* old-repository-uri)
234
                 (spocq.e:insert-data account-metadata)
235
                 (replace-nquads-file account-pathname (append account-metadata account-repository-settings))))
236
             (log-notice "anomalous mysql repository metadata: ~s ~s" account repository))))
237
     (log-notice "synchronized repository metadata: ~s ~s: ~s" account repository directory)
238
     directory)
239
   (:method :around (account repository directory)
240
     (handler-case (call-next-method)
241
       (error (c)
242
         (warn "synchronization failed: ~s ~s: ~a" account repository c)
243
         c))))
244
 
245
 ;;; (main-metadata-sync :account "james")
246
 ;;; (main-metadata-sync :account "test" :repositories "*")
247
 ;;; (synchronize-repository-metadata "james" "test" (repository-metadata-directory "james" "test"))
248
 ;;; (mysql-repository-metadata-statements "skorkmaz" "movielens1k")
249
 ;;; (test-sparql "select ?s ?p ?o where {graph <http://dydra.com/skorkmaz/movielens1k> { ?s ?p ?o }}" :repository-id "skorkmaz/system")
250
 ;;; (synchronize-repository-metadata "skorkmaz" "movielens1k" (repository-metadata-directory "skorkmaz" "movielens1k"))
251
 ;;; (access-authorized-p (repository "skorkmaz/movielens1k") (make-instance 'agent :name "?") |http://www.w3.org/ns/auth/acl#|:|Read|)
252
 #|
253
 "/bin/sh" "-c" \
254
 "mysql -h localhost -u root stage -BNe \"SELECT id, email, encrypted_password, authentication_token, remember_created_at, reset_password_token, name, fullname, cached_slug, request_timeout_limit, default_repository_prefixes, homepage, blog, company, location, phone, skype_id, jabber_id, region, host FROM accounts WHERE accounts.cached_slug ='openrdf-sesame';\""
255
 
256
 (let* ((account "openrdf-sesame")
257
        (pathname  (merge-pathnames (make-pathname :directory `(:relative "accounts" ,account)
258
                                                                   :name *metadata-file-name*
259
                                                                   :type "nq")
260
                                                    *metadata-root-pathname*)))
261
   (update-account-metadata-cache account pathname))
262
 
263
 (let* ((account "openrdf-sesame")
264
        (repository "graphql")
265
        (link (sb-posix:readlink (merge-pathnames (make-pathname :directory `(:relative "accounts" ,account "repositories" ,repository))
266
                                                  *metadata-root-pathname*)))
267
        (pathname  (merge-pathnames (make-pathname :directory `(:relative "repositories" ,link)
268
                                                                   :name *metadata-file-name*
269
                                                                   :type "nq")
270
                                                    *metadata-root-pathname*)))
271
   (update-repository-metadata-cache account repository pathname))
272
 
273
 (synchronize-repository-metadata "james" "test2" (repository-metadata-directory "james" "test2"))
274
 
275
 (remove (compute-repository-identifier "james" "test") (account-settings-statements "james")
276
         :key #'second :test-not #'equalp)
277
 
278
 (main-metadata-sync :account "openrdf-sesame" :repository "graphql")
279
 (main-metadata-sync)
280
 
281
 (in-package :spocq.i)
282
 (setq *print-length* 10)
283
 (trace spocq.i::replace-nquads-file spocq.e:insert-data spocq.i::call-with-open-repository spocq.i::repository-clear-graph
284
        spocq.i::call-with-open-transaction spocq.i::call-with-revision-transaction)
285
 (trace rdfcache:count rdfcache:sparql-clear rdfcache-object-term-number repository-clear-graph)
286
 (spocq.i::main-metadata-sync :account "nxp" :repository "plm")
287
 
288
 (with-open-repository ("nxp/system" :normal-disposition :commit :read-only-p nil) (print *transaction*))
289
 
290
 ;;; 20201112 nl11
291
 (spocq.i::main-metadata-sync :account "nxf28376" :repository "aggregation_test")
292
 
293
 |#
294
 #|
295
 rapper -i ntriples --count 'http://admin.dydra.com/cgi-bin/timemap.sh?repository-id=statistics/de4.dydra.com&response-limit=200'
296
 curl 'http://admin.dydra.com/cgi-bin/timemap.sh?repository-id=statistics/de4.dydra.com&response-limit=20'
297
 
298
 QUERY_STRING='repository-id=statistics/de1.dydra.com&response-limit=20' ./timemap.sh
299
 QUERY_STRING='repository-id=statistics/de4.dydra.com&response-limit=20' ./timemap.sh
300
 QUERY_STRING='repository-id=statistics/de4.dydra.com&response-limit=20&properties=http://www.mementoweb.org/terms/tb/end' ./timemap.sh
301
 
302
 (compute-timemap (repository "jhacker/basic-term-1") :timemap-properties '(|rdf|:|type|))
303
 (main-timemap :query-parameters "repository=jhacker/basic-term-1")
304
 (main-timemap :query-parameters "repository=statistics/de1.dydra.com&response-limit=20")
305
 (main-timemap :query-parameters "repository=jhacker/basic-term-1&properties=http://www.mementoweb.org/terms/tb/end%20http://www.mementoweb.org/terms/tb/start")
306
 (main-timemap :query-parameters "repository=statistics/de4.dydra.com&response-limit=21&properties=http://www.mementoweb.org/terms/tb/start")
307
 
308
 
309
 <http://wulff.dev/jhacker/basic-term-1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.openarchives.org/ore/terms/ResourceMap> .
310
 <http://wulff.dev/jhacker/basic-term-1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/TimeMap> .
311
 <http://wulff.dev/jhacker/basic-term-1> <http://purl.org/dc/terms/modified> "2013-03-29T14:39:52Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
312
 <http://wulff.dev/jhacker/basic-term-1> <http://purl.org/dc/terms/created> "2013-03-29T14:39:52Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
313
 _:timebundle <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.openarchives.org/ore/terms/Aggregation> .
314
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <urn:dydra:revision:fd578100-ebaf-11e1-a207-0665032ba83f> .
315
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <urn:dydra:revision:eb75de00-ebaf-11e1-a207-0665032ba83f> .
316
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <urn:dydra:revision:9934bd00-ebaf-11e1-a207-0665032ba83f> .
317
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <urn:dydra:revision:45c26f00-ebaf-11e1-a207-0665032ba83f> .
318
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <urn:dydra:revision:eb7da068-be68-434e-ab9d-9dceaa2cc95e> .
319
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <http://wulff.dev/jhacker/basic-term-1> .
320
 _:timebundle <http://purl.org/dc/elements/1.1/title> "Memento Time Bundle for 'http://wulff.dev/jhacker/basic-term-1'" .
321
 _:timebundle <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/TimeBundle> .
322
 <http://wulff.dev/jhacker/basic-term-1> <http://www.openarchives.org/ore/terms/describes> _:timebundle .
323
 <http://wulff.dev/jhacker/basic-term-1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/TimeGate> .
324
 <http://wulff.dev/jhacker/basic-term-1> <http://www.mementoweb.org/terms/tb/timeGateFor> <http://wulff.dev/jhacker/basic-term-1> .
325
 <http://wulff.dev/jhacker/basic-term-1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/OriginalResource> .
326
 <http://wulff.dev/jhacker/basic-term-1> <http://www.mementoweb.org/terms/tb/covers> _:blank0 .
327
 _:blank0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
328
 _:blank0 <http://www.mementoweb.org/terms/tb/start> 2012-06-30T12:53:13Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
329
 <urn:dydra:revision:fd578100-ebaf-11e1-a207-0665032ba83f> <http://www.mementoweb.org/terms/tb/validOver> _:blank1 .
330
 <urn:dydra:revision:fd578100-ebaf-11e1-a207-0665032ba83f> <http://www.mementoweb.org/terms/tb/mementoFor> <http://wulff.dev/jhacker/basic-term-1> .
331
 <urn:dydra:revision:fd578100-ebaf-11e1-a207-0665032ba83f> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Memento> .
332
 _:blank1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
333
 _:blank1 <http://www.mementoweb.org/terms/tb/start> 2012-08-21T16:48:10Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
334
 <urn:dydra:revision:eb75de00-ebaf-11e1-a207-0665032ba83f> <http://www.mementoweb.org/terms/tb/validOver> _:blank2 .
335
 <urn:dydra:revision:eb75de00-ebaf-11e1-a207-0665032ba83f> <http://www.mementoweb.org/terms/tb/mementoFor> <http://wulff.dev/jhacker/basic-term-1> .
336
 <urn:dydra:revision:eb75de00-ebaf-11e1-a207-0665032ba83f> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Memento> .
337
 _:blank2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
338
 _:blank2 <http://www.mementoweb.org/terms/tb/start> 2012-08-21T16:47:40Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
339
 _:blank2 <http://www.mementoweb.org/terms/tb/end> 2012-08-21T16:48:10Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
340
 <urn:dydra:revision:9934bd00-ebaf-11e1-a207-0665032ba83f> <http://www.mementoweb.org/terms/tb/validOver> _:blank3 .
341
 <urn:dydra:revision:9934bd00-ebaf-11e1-a207-0665032ba83f> <http://www.mementoweb.org/terms/tb/mementoFor> <http://wulff.dev/jhacker/basic-term-1> .
342
 <urn:dydra:revision:9934bd00-ebaf-11e1-a207-0665032ba83f> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Memento> .
343
 _:blank3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
344
 _:blank3 <http://www.mementoweb.org/terms/tb/start> 2012-08-21T16:45:22Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
345
 _:blank3 <http://www.mementoweb.org/terms/tb/end> 2012-08-21T16:47:40Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
346
 <urn:dydra:revision:45c26f00-ebaf-11e1-a207-0665032ba83f> <http://www.mementoweb.org/terms/tb/validOver> _:blank4 .
347
 <urn:dydra:revision:45c26f00-ebaf-11e1-a207-0665032ba83f> <http://www.mementoweb.org/terms/tb/mementoFor> <http://wulff.dev/jhacker/basic-term-1> .
348
 <urn:dydra:revision:45c26f00-ebaf-11e1-a207-0665032ba83f> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Memento> .
349
 _:blank4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
350
 _:blank4 <http://www.mementoweb.org/terms/tb/start> 2012-08-21T16:43:02Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
351
 _:blank4 <http://www.mementoweb.org/terms/tb/end> 2012-08-21T16:45:22Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
352
 <urn:dydra:revision:eb7da068-be68-434e-ab9d-9dceaa2cc95e> <http://www.mementoweb.org/terms/tb/validOver> _:blank5 .
353
 <urn:dydra:revision:eb7da068-be68-434e-ab9d-9dceaa2cc95e> <http://www.mementoweb.org/terms/tb/mementoFor> <http://wulff.dev/jhacker/basic-term-1> .
354
 <urn:dydra:revision:eb7da068-be68-434e-ab9d-9dceaa2cc95e> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Memento> .
355
 _:blank5 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
356
 _:blank5 <http://www.mementoweb.org/terms/tb/start> 2012-06-30T12:53:13Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
357
 _:blank5 <http://www.mementoweb.org/terms/tb/end> 2012-08-21T16:43:02Z^^<http://www.w3.org/2001/XMLSchema#dateTime> .
358
 
359
 
360
 ;;; the lim it is 30, but the actual result is just 28 as the next revision would not fit
361
 (main-timemap :query-parameters "repository=statistics/de4.dydra.com&response-limit=30")
362
 
363
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.openarchives.org/ore/terms/ResourceMap> .
364
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/TimeMap> .
365
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://purl.org/dc/terms/modified> "2013-03-29T17:28:45Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
366
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://purl.org/dc/terms/created> "2013-03-29T17:28:45Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
367
 _:timebundle <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.openarchives.org/ore/terms/Aggregation> .
368
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <http://admin.dydra.com/statistics/de4.dydra.com> .
369
 _:timebundle <http://purl.org/dc/elements/1.1/title> "Memento Time Bundle for 'http://admin.dydra.com/statistics/de4.dydra.com'" .
370
 _:timebundle <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/TimeBundle> .
371
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://www.openarchives.org/ore/terms/describes> _:timebundle .
372
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/TimeGate> .
373
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://www.mementoweb.org/terms/tb/timeGateFor> <http://admin.dydra.com/statistics/de4.dydra.com> .
374
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/OriginalResource> .
375
 <http://admin.dydra.com/statistics/de4.dydra.com> <http://www.mementoweb.org/terms/tb/covers> _:blank0 .
376
 _:blank0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
377
 _:blank0 <http://www.mementoweb.org/terms/tb/start> "2013-03-05T22:34:44Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
378
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <urn:dydra:revision:445b8651-32a6-a04d-8fcb-c2c10a7669b1> .
379
 <urn:dydra:revision:445b8651-32a6-a04d-8fcb-c2c10a7669b1> <http://www.mementoweb.org/terms/tb/validOver> _:blank1 .
380
 <urn:dydra:revision:445b8651-32a6-a04d-8fcb-c2c10a7669b1> <http://www.mementoweb.org/terms/tb/mementoFor> <http://admin.dydra.com/statistics/de4.dydra.com> .
381
 <urn:dydra:revision:445b8651-32a6-a04d-8fcb-c2c10a7669b1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Memento> .
382
 _:blank1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
383
 _:blank1 <http://www.mementoweb.org/terms/tb/start> "2013-03-26T17:54:43Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
384
 _:timebundle <http://www.openarchives.org/ore/terms/aggregates> <urn:dydra:revision:83c07043-d2a2-1d4e-9d20-0b047c97d671> .
385
 <urn:dydra:revision:83c07043-d2a2-1d4e-9d20-0b047c97d671> <http://www.mementoweb.org/terms/tb/validOver> _:blank2 .
386
 <urn:dydra:revision:83c07043-d2a2-1d4e-9d20-0b047c97d671> <http://www.mementoweb.org/terms/tb/mementoFor> <http://admin.dydra.com/statistics/de4.dydra.com> .
387
 <urn:dydra:revision:83c07043-d2a2-1d4e-9d20-0b047c97d671> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Memento> .
388
 _:blank2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.mementoweb.org/terms/tb/Period> .
389
 _:blank2 <http://www.mementoweb.org/terms/tb/start> "2013-03-26T16:54:42Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
390
 _:blank2 <http://www.mementoweb.org/terms/tb/end> "2013-03-26T17:54:43Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
391
 
392
 
393
 |#