Skip to content

Commit

Permalink
Implemented and tested saving to a flat file
Browse files Browse the repository at this point in the history
  • Loading branch information
Paula Gearon committed Sep 2, 2020
1 parent dadbfe6 commit 2049df2
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/asami/durable/flat.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
(defprotocol FlatStore
(write-object! [this obj] "Writes an object to storage. Returns an ID")
(get-object [this id] "Reads and object from storage, based on an ID")
(force! [this] "Ensures that all written data is fully persisted"))
(force! [this] "Ensures that all written data is fully persisted")
(close [this] "Releases any resources associated with the store"))
16 changes: 12 additions & 4 deletions src/asami/durable/flat_file.clj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

(def file-name "raw.dat")

(defprotocol Clearable
(clear! [this] "Clears out any resources which may be held"))

;; These functions do update the PagedFile state, but only to expand the mapped region.
(defrecord PagedFile [^RandomAccessFile f regions region-size]
Paged
Expand Down Expand Up @@ -115,7 +118,9 @@
(doto (.asReadOnlyBuffer region)
(.position region-offset)
(.get bytes)))
bytes))))
bytes)))
Clearable
(clear! [this] (reset! regions nil)))

(defn paged-file
"Creates a paged file reader"
Expand All @@ -127,7 +132,7 @@

;; rfile: A file that will only be appended to
;; paged: A paged reader for the file
(defrecord FlatFile [rfile paged]
(defrecord FlatFile [^RandomAccessFile rfile paged]
FlatStore
(write-object!
[this obj]
Expand All @@ -140,7 +145,10 @@
[this id]
(decoder/read-object paged id))
(force! [this]
(.force (.getChannel rfile true))))
(.force (.getChannel rfile) true))
(close [this]
(clear! paged)
(.close rfile)))

(defn flat-store
"Creates a flat file store. This wraps an append-only file and a paged reader."
Expand All @@ -152,4 +160,4 @@
file-length (.length raf)]
(when-not (zero? file-length)
(.seek raf file-length))
(->FlatFile raf (paged-file raf) file-length)))
(->FlatFile raf (paged-file raf))))
48 changes: 48 additions & 0 deletions test/asami/durable/test_flat.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
(ns ^{:doc "Tests flat store functionality, saving and retrieving data"
:author "Paula Gearon"}
asami.durable.test-flat
(:require [asami.durable.flat :refer [write-object! get-object force!]]
#?(:clj [asami.durable.flat-file :as ff])
#?(:clj [clojure.java.io :as io])
[clojure.test :refer [deftest is]])
#?(:clj (:import [java.net URI])))

(def store-name "test-fstore")

(defn uri [s] #?(:clj (URI. s) :cljs (goog/Uri. s)))

(def data
["Hello"
"Goodbye"
:the
:quick
(uri "http://brown.com/fox")
"jumps over the lazy dog."
1812
"It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.\n\nHowever little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered the rightful property of some one or other of their daughters.\n\n“My dear Mr. Bennet,” said his lady to him one day, “have you heard that Netherfield Park is let at last?”\n\nMr. Bennet replied that he had not.\n\n“But it is,” returned she; “for Mrs. Long has just been here, and she told me all about it.”\n\nMr. Bennet made no answer.\n\n“Do you not want to know who has taken it?” cried his wife impatiently.\n\n“You want to tell me, and I have no objection to hearing it.”\n\nThis was invitation enough."])

(deftest test-store
(let [fmapped (volatile! nil)]
(is (not (.exists (io/file store-name ff/file-name))))
(with-open [store (ff/flat-store store-name)]
(vreset! fmapped (reduce-kv (fn [m k v]
(let [id (write-object! store v)]
(assoc m k id)))
{} data))
(is (= (count data) (count @fmapped)))
(doseq [[n id] @fmapped]
(is (= (nth data n) (get-object store id))))
(doseq [[n id] (shuffle (seq @fmapped))]
(is (= (nth data n) (get-object store id))))
(force! store))

(with-open [store (ff/flat-store store-name)]
(doseq [[n id] @fmapped]
(is (= (nth data n) (get-object store id))))
(doseq [[n id] (shuffle (seq @fmapped))]
(is (= (nth data n) (get-object store id))))))
#?(:clj
(let [f (io/file store-name ff/file-name)
d (io/file store-name)]
(is (.delete f))
(is (.delete d)))))

0 comments on commit 2049df2

Please sign in to comment.