| 1 |
;;;; Konvertierung vom Sexpr-Snapshot-Format in das Binaerformat. |
|---|
| 2 |
;;;; Anleitung: |
|---|
| 3 |
;;;; |
|---|
| 4 |
;;;; Im laufenden Server mit altem Code: |
|---|
| 5 |
;;;; - Einen Snapshot erstellen. Transaktionsfiles koennen wir nicht laden. |
|---|
| 6 |
;;;; |
|---|
| 7 |
;;;; Die Konvertierung findet dann offline statt: |
|---|
| 8 |
;;;; - BOS-Branch kompilieren, dieses File laden. |
|---|
| 9 |
;;;; - Der Anwendungscode kann geladen sein, muss aber nicht. Es |
|---|
| 10 |
;;;; werden aber die im Snapshot referenzierten Pakete benoetigt. |
|---|
| 11 |
;;;; Falls der eigentliche Code nicht geladen ist, einfach ein |
|---|
| 12 |
;;;; MAKE-PACKAGE auf alle fehlenden Pakete machen. |
|---|
| 13 |
;;;; - (CONVERT-SNAPSHOT "/path/to/datastore/snapshot") aufrufen |
|---|
| 14 |
;;;; - Heraus kommt "snapshot.new", das kopiere man nach erfolgreicher |
|---|
| 15 |
;;;; Konvertierung in "snapshot" um. |
|---|
| 16 |
;;;; |
|---|
| 17 |
;;;; Das hier erstellte Snapshotfile ist noch "unkomprimert". Nach |
|---|
| 18 |
;;;; erfolglichem Start der Anwendung teste man den normalen Snapshotvorgang, |
|---|
| 19 |
;;;; das dann erstelle File muesste etwas kleiner sein. |
|---|
| 20 |
|
|---|
| 21 |
(in-package :bknr.datastore) |
|---|
| 22 |
|
|---|
| 23 |
(defvar *layout-counter* 0) |
|---|
| 24 |
|
|---|
| 25 |
(defun convert-snapshot/encode-layout (class-name slots stream) |
|---|
| 26 |
(let ((id (incf *layout-counter*))) |
|---|
| 27 |
(%write-tag #\L stream) |
|---|
| 28 |
(%encode-integer id stream) |
|---|
| 29 |
(%encode-symbol class-name stream) |
|---|
| 30 |
(%encode-integer (length slots) stream) |
|---|
| 31 |
(dolist (slot slots) |
|---|
| 32 |
(%encode-symbol slot stream)) |
|---|
| 33 |
id)) |
|---|
| 34 |
|
|---|
| 35 |
(defun convert-snapshot/create-object (class objid slots values stream) |
|---|
| 36 |
(let ((layout-id (convert-snapshot/encode-layout class nil stream))) |
|---|
| 37 |
(%write-tag #\O stream) |
|---|
| 38 |
(%encode-integer layout-id stream) |
|---|
| 39 |
(%encode-integer objid stream) |
|---|
| 40 |
(convert-snapshot/set-slots objid slots values stream))) |
|---|
| 41 |
|
|---|
| 42 |
(defun convert-snapshot/set-slots (objid slots values stream) |
|---|
| 43 |
(let ((layout-id (convert-snapshot/encode-layout 'dummy slots stream))) |
|---|
| 44 |
(%write-tag #\S stream) |
|---|
| 45 |
(%encode-integer layout-id stream) |
|---|
| 46 |
(%encode-integer objid stream) |
|---|
| 47 |
(dolist (value values) |
|---|
| 48 |
(encode value stream)))) |
|---|
| 49 |
|
|---|
| 50 |
(defun convert-snapshot/exp (exp out) |
|---|
| 51 |
(declare (optimize (speed 3))) |
|---|
| 52 |
(if (consp exp) |
|---|
| 53 |
(case (car exp) |
|---|
| 54 |
(create-object |
|---|
| 55 |
(destructuring-bind (class &rest initargs) (cdr exp) |
|---|
| 56 |
(loop with id = nil |
|---|
| 57 |
for (slot value) on initargs by #'cddr |
|---|
| 58 |
collect slot into slots |
|---|
| 59 |
collect (convert-snapshot/exp value out) into values |
|---|
| 60 |
do |
|---|
| 61 |
(when (eq slot :id) |
|---|
| 62 |
(setf id value)) |
|---|
| 63 |
finally (convert-snapshot/create-object class id slots values out)))) |
|---|
| 64 |
(set-slots |
|---|
| 65 |
(destructuring-bind (obj &rest initargs) (cdr exp) |
|---|
| 66 |
(loop for (slot value) on initargs by #'cddr |
|---|
| 67 |
collect slot into slots |
|---|
| 68 |
collect (convert-snapshot/exp value out) into values |
|---|
| 69 |
finally (convert-snapshot/set-slots obj slots values out)))) |
|---|
| 70 |
(store-object-with-id |
|---|
| 71 |
(let ((o (allocate-instance (find-class 'store-object)))) |
|---|
| 72 |
(setf (slot-value o 'id) (second exp)) |
|---|
| 73 |
o)) |
|---|
| 74 |
(t |
|---|
| 75 |
(eval exp))) |
|---|
| 76 |
exp)) |
|---|
| 77 |
|
|---|
| 78 |
(defun convert-snapshot (file) |
|---|
| 79 |
(with-store-state (:restore) |
|---|
| 80 |
(with-open-file (in file) |
|---|
| 81 |
(with-open-file (out (make-pathname :type "new" :defaults file) |
|---|
| 82 |
:direction :output |
|---|
| 83 |
:element-type '(unsigned-byte 8)) |
|---|
| 84 |
(let ((*package* #.*package*)) |
|---|
| 85 |
(loop for exp = (read in nil 'eof nil) |
|---|
| 86 |
until (eql exp 'eof) |
|---|
| 87 |
do (convert-snapshot/exp exp out))))))) |
|---|