Save your first file

Save a three-byte attachment in an in-memory database, give it a name and read it back. This tutorial assumes you can use a Clojure REPL. It does not create files on disk.

Start the REPL

From an authorised xitstash checkout, with Java 17 or later, Clojure CLI and Babashka installed, run:

bb javac
clojure -Sdeps '{:deps {io.github.radarroark/xitdb {:mvn/version "0.48.0"}}}' -M

Wait for the user⇒ prompt.

Load the library

(require '[ol.xitstash :as objects])
(import '[io.github.radarroark.xitdb
          CoreMemory Database Database$ContextFunction Hasher RandomAccessMemory
          ReadCountedHashMap WriteCountedHashMap]
        '[java.security MessageDigest])

The require returns nil. The import returns java.security.MessageDigest.

Save and read the attachment

Evaluate the following expression. It prepares the content, commits a file named note.bin and returns the saved path and bytes:

(with-open [core     (CoreMemory. (RandomAccessMemory.))
            prepared (objects/prepare (byte-array [1 2 3]))]
  (let [db (Database. core (Hasher. (MessageDigest/getInstance "SHA-256")))]
    (locking db
      (.runContext db
        (reify Database$ContextFunction
          (run [_ root]
            (let [store (.putCursor (WriteCountedHashMap. root) "objects")]
              (objects/initialize! store)
              (objects/put! store prepared)
              (objects/create! store [{:name "note.bin"
                                       :digest (:digest prepared)}])))))
      (let [store (.getCursor (ReadCountedHashMap. (.rootCursor db)) "objects")
            file  (objects/lookup store 0 "note.bin")]
        (with-open [input (objects/open store (:digest file))]
          {:path  (objects/path store (:id file))
           :bytes (vec (.readAllBytes input))})))))

Result:

{:path ["note.bin"] :bytes [1 2 3]}

The file lives below catalog root 0. Its bytes were prepared before the transaction and read after the commit. The enclosing with-open forms close the stream, prepared content and memory database.

Run the expression again. It creates a fresh database and returns the same result.

Next

Use xitdb-clj transactions to save attachments alongside Clojure application records. Read Content and history for the distinction between a file name and a payload.