From 3f1e8edf9552d6b914659883c69175de3eafca06 Mon Sep 17 00:00:00 2001 From: Karchnu Date: Wed, 12 Oct 2022 14:51:53 +0200 Subject: [PATCH] Grooming + examples. --- src/dodb.cl | 119 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 40 deletions(-) diff --git a/src/dodb.cl b/src/dodb.cl index 8bdce7e..22947c0 100644 --- a/src/dodb.cl +++ b/src/dodb.cl @@ -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"))