Grooming + examples.

draft
Karchnu 2022-10-12 14:51:53 +02:00
parent 779e13e83d
commit 3f1e8edf95
1 changed files with 79 additions and 40 deletions

View File

@ -17,63 +17,65 @@
(alias ln osicat:make-link)
(alias ls osicat:list-directory)
(defun to-upper-case (some-string)
(format nil "~@:(~a~)" some-string))
; Example: 18 -> 000000000000018.data
(defun number->filename (number)
(format nil "~15,'0D.data" number))
; Example: "vehicle" "color" object -> (vehicle-color object) -> "Red"
(defun get-object-attribute (struct-name attribute-name object)
(funcall ; example: call function "VEHICLE-COLOR"
(find-symbol (to-upper-case
(concatenate 'string struct-name "-" attribute-name)))
object))
; index = 1-1
; partition = 1-n
; String Path [String] [String] Int
(defstruct db struct-name path (indexes ()) (partitions ()) (current-index 0)
; {Int -> struct}
(data (make-hash-table))
(defstruct db
struct-name ; String
path ; Path
(indexes ()) ; [String]
(partitions ()) ; [String]
(current-index 0) ; Int
(data (make-hash-table)) ; {Int -> struct}
)
(defun db/new (struct-name path)
(ensure-directories-exist (concatenate 'string path "/data/"))
(make-db :struct-name struct-name :path path))
; example: db-path/indexes/by_name/
(defun db/new-index (database attribute-name)
; Create a directory for the indexes.
(ensure-directories-exist
(concatenate 'string (db-path database) "/indexes/by_" attribute-name "/"))
; Add this new index to the list.
(push attribute-name (db-indexes database)))
; Example: ./storage/cars 18 -> ./storage/cars/data/000000000000018.data
; USAGE: when dealing with hash keys from the in-memory db.
; The hash key is the number used to build the filename.
(defun db/data-filepath (dbpath number)
(concatenate 'string dbpath "/data/" (number->filename number)))
; example: db-path/partitions/by_color/
(defun db/new-partition (database attribute-name)
; Create a directory for the partitions.
(ensure-directories-exist
(concatenate 'string (db-path database) "/partitions/by_" attribute-name "/"))
; Add this new index to the list.
(push attribute-name (db-partitions database)))
(defun to-upper-case (some-string)
(format nil "~@:(~a~)" some-string))
(defun get-object-attribute (database attribute-name object)
(funcall ; example: call function "VEHICLE-COLOR"
(find-symbol (to-upper-case
(concatenate 'string (db-struct-name database) "-" attribute-name)))
object))
; Example: returns "storage/cars/indexes/by_name/".
; Example: returns "./storage/cars/indexes/by_name/".
(defun db/index/get-directory-path (database name)
(concatenate 'string (db-path database) "/indexes/by_" name "/" ))
; Example: returns "storage/cars/partitions/by_color/".
; Example: returns "./storage/cars/partitions/by_color/Red/".
(defun db/partition/get-directory-path (database name value)
(concatenate 'string (db-path database) "/partitions/by_" name "/" value "/"))
; Example: returns "Corvet".
(defun db/index/get-filename (database index-name object)
(get-object-attribute database index-name object))
(get-object-attribute (db-struct-name database) index-name object))
; Example: database "name" object -> "./storage/cars/indexes/by_name/Corvet".
(defun db/index/get-symlink-path (database index-name object)
(concatenate 'string
(db/index/get-directory-path database index-name)
(db/index/get-filename database index-name object)))
; Example: database "name" object "0000000015.data"
; -> (ln "./storage/cars/indexes/by_name/Corvet"
; :target "../../data/0000000015.data"
; :hard nil)
(defun db/index/new (database index-name object file-name)
(let ((symlink-path
(db/index/get-symlink-path database index-name object)))
(let ((symlink-path (db/index/get-symlink-path database index-name object)))
; Works even when the database directory is moved.
(ln symlink-path
@ -81,14 +83,20 @@
:hard nil)
))
; Example: database "color" object
; -> "./storage/cars/partitions/by_color/Red/0000000015.data".
(defun db/partition/get-symlink-path (database partition-name object file-name)
(concatenate 'string
(db/partition/get-directory-path database partition-name
; example: "Red"
(get-object-attribute database partition-name object))
; example: "000000000000018.data"
(get-object-attribute (db-struct-name database) partition-name object))
; example: "0000000015.data"
file-name))
; Example: database "color" object "0000000015.data"
; -> (ln "./storage/cars/partitions/by_color/Red/0000000015.data"
; :target "../../../data/0000000015.data"
; :hard nil)
(defun db/partition/new (database partition-name object file-name)
(let ((symlink-path
(db/partition/get-symlink-path database partition-name object file-name)))
@ -100,9 +108,37 @@
:target (concatenate 'string "../../../data/" file-name)
:hard nil)))
; Example: 000000000000018.data
; example: db-path/indexes/by_name/
(defun db/new-index (database attribute-name)
; Create a directory for the indexes.
(ensure-directories-exist
(concatenate 'string (db-path database) "/indexes/by_" attribute-name "/"))
; Add this new index to the list.
(push attribute-name (db-indexes database))
; Generate index for all DB elements.
(maphash #'(lambda (number element)
(db/index/new database attribute-name element (number->filename number)))
(db-data database)))
; example: db-path/partitions/by_color/
(defun db/new-partition (database attribute-name)
; Create a directory for the partitions.
(ensure-directories-exist
(concatenate 'string (db-path database) "/partitions/by_" attribute-name "/"))
; Add this new index to the list.
(push attribute-name (db-partitions database))
; Generate partition for all DB elements.
(maphash #'(lambda (number element)
(db/partition/new database attribute-name element (number->filename number)))
(db-data database)))
; Example: database -> "000000000000018.data".
(defun db/add/new-data-filename (database)
(format nil "~15,'0D.data" (db-current-index database)))
(number->filename (db-current-index database)))
; Example: {db-path}/data/000000000000018.data
(defun db/add/new-data-filepath (database file-name)
@ -111,6 +147,8 @@
(defun db/add (database object)
(incf (db-current-index database))
(let ((file-name (db/add/new-data-filename database)))
; write object to file
(util:write-object-to-file
object
(db/add/new-data-filepath database file-name))
@ -124,6 +162,7 @@
do (db/partition/new database partition object file-name)))
; store new in-memory data
; database.data[database.current-index] = object
(setf (gethash (db-current-index database) (db-data database)) object))
; TODO: should we search for the data from the FS or in-memory?
@ -143,12 +182,12 @@
(defparameter cars (db/new "vehicle" "./storage/cars/"))
(db/add cars (make-vehicle :name "Corvet" :color "Red"))
(db/add cars (make-vehicle :name "Deudeuch" :color "Beige"))
(db/new-index cars "name")
(db/new-partition cars "color")
(db/add cars (make-vehicle :name "Corvet" :color "Red"))
(db/add cars (make-vehicle :name "Deudeuch" :color "Beige"))
(format t "~&~S~&" cars)
(format t "db/get-by-index ~S~&" (db/get-by-index cars "name" "Corvet"))