Browse files

example is starting to work

  • Loading branch information...
1 parent 407b56e commit ff7a77b45b72470ceef3e7edc6d61ca921509324 chrisdew committed Feb 8, 2011
Showing with 131 additions and 145 deletions.
  1. +17 −124 README.md
  2. +3 −3 docs/db.html
  3. +47 −10 docs/disk-io.html
  4. +1 −1 examples/create-database.js
  5. +3 −3 lib/db.js
  6. +60 −4 lib/disk-io.js
View
141 README.md
@@ -5,132 +5,25 @@ Alpha development. Does NOT yet work yet.
BarricaneDB is a loose implementation of the [Prevalence](http://www.ibm.com/developerworks/library/wa-objprev/) System Design Pattern, as implemented in Java by [Prevaylor](http://www.prevayler.org/), but for [NodeJS](http://nodejs.org/).
-Features
---------
-* Fantastically fast.
-* Stupidly simple, thank you <code>__defineSetter__</code> and friends.
-* ORM-less, just work with your objects directly.
-* Snapshot plus transaction log gives persistance in event of an application crash.
+BarricaneDB is really just an ultra-simple persistance layer for a single process. It can persist your application's model without any explicit 'save' commands. Every Javascript <code>x.y = "foo";</code> (on registered instances) causes asynchronous persistance to disk.
-Anti-Features
--------------
-* Untested in production.
-* Performance can still be greatly improved.
-* Single process.
-* Not durable - you will lose 1-5 seconds of changes on a crash (OS dependent).
+See the [examples](https://examples) for how easy it is to get started.
-Usage
------
-First install it:
+Installation
+------------
+* Package not available yet - will be <code>npm install barricane-db</code>
- npm install barricane-db
+Reasons why BarricaneDB will never be a good fit for your application.
+----------------------------------------------------------------------
+* Your data set is too big to fit in RAM.
+* Your application needs ACID guarantees. BarricaneDB could loose 1-5 seconds of data on a process crash (OS dependent).
+* Your application doesn't happily shard into BarricaneDB's one-DB-per-process design.
+* You need to query your database from outside the NodeJS process - e.g. Crystal Reports.
-Then create and populate a test database:
+Reasons why BarricaneDB is not _currently_ a good fit.
+------------------------------------------------------
+* Your application needs a production-tested solution.
+* You need good error handling.
+* You need async database opening (persistence is already fully async).
+* Transactions are important to you.
- var bdb = require('barricane-db');
-
- var db = new bdb.DB({path: '/tmp', name: 'test_db'});
-
- // run of the mill constructors and a method
- function House(address) {
- this.address = address;
- db.register(this);
- }
- House.prototype.logConstructionMaterial = function() {
- console.log(this.address + ' is made of stone');
- }
-
- function Person(personalName, familyName) {
- this.personalName = personalName;
- this.familyName = familyName;
- this.spouse = null; // MUST declare any field which needs persistance
- // ONLY registered constructors, plain objects,
- // arrays, strings, numbers and dates will be
- // persisted.
- db.register(this);
- }
-
- // This is only needed if the database is found on disk - BDB needs to know
- // how to reconstruct the objects from the snapshot and transaction log.
- db.registerConstructors(House, Person);
-
- // the database should not exist yet
- var alreadyExisted = db.loadDBIfExists();
- console.log("alreadyExisted:", alreadyExists);
- // ->> false
-
-
- var house = new House("301 Cobblestone Wy., Bedrock, 70777");
- var fred = new Person("Fred", "Flintstone");
- var wilma = new Person("Wilma", "Flintsone");
- fred.spouse = wilma;
- wilma.spouse = fred;
-
- db.end(); // this waits for all writes to complete before performing
- // a snapshot and closing the database
-
-
-Then load and reconstitute the database:
-
- var bdb = require('barricane-db');
-
- var db = new bdb.DB({path: '/tmp', name: 'test_db'});
-
- // of course you'll really be requiring your constructors from a common
- // file - this needless duplication is just to keep this example simple
- function House(address) {
- this.address = address;
- db.register(this);
- }
- House.prototype.logConstructionMaterial = function() {
- console.log(this.address + ' is made of stone');
- }
-
- function Person(personalName, familyName) {
- this.personalName = personalName;
- this.familyName = familyName;
- this.spouse = null; // MUST declare any field which needs persistance
- // ONLY registered constructors, plain objects,
- // arrays, strings, numbers and dates will be
- // persisted.
-
- db.register(this);
- }
-
- db.registerConstructors(House, Person);
- var alreadyExisted = db.loadDBIfExists();
- console.log("alreadyExisted:", alreadyExists);
- // ->> true
-
- // get all the people
- var people = db.getInstancesByConstructor(Person);
- console.log("numPeople:", people.length); // 2
-
- // find wilma
- var wilma = null;
- people.forEach(function(i, person, people) {
- if (person.name === "Wilma") {
- wilma = person;
- }
- });
-
- console.log("wilma:", wilma.firstName, wilma.familyName);
- // --> wilma: Wilma Flintstone
-
- // once you've found an object you can follow references, as normal,
- // through your object graph
-
- var house = fred.house
- console.log("house:", house.address);
- // --> house: 301 Cobblestone Wy., Bedrock, 70777
-
- var fred = wilma.spouse
- console.log("fred:", fred.firstName, fred.familyName);
- // --> fred: Fred Flintstone
-
- // methods still work correctly
- house.logConstructionMaterial();
- // --> 301 Cobblestone Wy., Bedrock, 70777 is made of stone
-
- db.end(); // If you don't bother with this, the database will
- // use the transaction log to catch up.
View
6 docs/db.html
@@ -40,7 +40,7 @@
<code>process.db</code> database.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DB</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">registerInstance</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">instance</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
- <span class="nx">instance</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">UUID_TAG</span><span class="p">]</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">options</span><span class="p">.</span><span class="nx">uuid</span><span class="p">();</span>
+ <span class="nx">instance</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">UUID_TAG</span><span class="p">]</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">uuid</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">instances</span><span class="p">[</span><span class="nx">instance</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">UUID_TAG</span><span class="p">]]</span> <span class="o">=</span> <span class="nx">instance</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="p">{};</span> <span class="c1">// the backing store for the instance data</span>
@@ -71,8 +71,8 @@
<span class="p">}</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Just a wrapper.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DB</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">deleteSync</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">io</span><span class="p">.</span><span class="nx">deleteSync</span><span class="p">();</span>
-<span class="p">}</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Just a wrapper.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DB</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">endSync</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
- <span class="k">this</span><span class="p">.</span><span class="nx">io</span><span class="p">.</span><span class="nx">endSync</span><span class="p">();</span>
+<span class="p">}</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Just a wrapper.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DB</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">io</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>Export the symbols.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">DB</span> <span class="o">=</span> <span class="nx">DB</span><span class="p">;</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
View
57 docs/disk-io.html
@@ -8,32 +8,69 @@
<span class="kd">function</span> <span class="nx">DiskIO</span><span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{};</span>
- <span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">path</span> <span class="o">||</span> <span class="s1">&#39;/tmp/barricane.db&#39;</span><span class="p">;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">path</span> <span class="o">||</span> <span class="s1">&#39;/tmp&#39;</span><span class="p">;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">name</span> <span class="o">||</span> <span class="s1">&#39;unnamed_db&#39;</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">codec</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">codec</span> <span class="o">||</span> <span class="k">new</span> <span class="nx">codec</span><span class="p">.</span><span class="nx">Codec</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">magic</span><span class="p">);</span>
+ </pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Psuedo constants.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">FILENAME</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s2">&quot;.&quot;</span>
+ <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">codec</span><span class="p">.</span><span class="nx">defaultFileExtension</span> <span class="o">+</span> <span class="s2">&quot;.barricane-db&quot;</span><span class="p">;</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">OLD_FILENAME</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">LIVE_FILENAME</span> <span class="o">+</span> <span class="s2">&quot;.old&quot;</span><span class="p">;</span>
+ </pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">fd</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> <span class="c1">// The file descriptor for persistence.</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">oldFd</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> <span class="c1">// The file descriptor for the old copy of the database.</span>
<span class="k">this</span><span class="p">.</span><span class="nx">writeStream</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
- </pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Writes must be counted, so we only close the file when all has been
+ </pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Writes must be counted, so we only close the file when all has been
written.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">outstandingWrites</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
- </pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>If end is requested, this will contain a callback.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">ending</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
-<span class="p">}</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>This writes an object to disk.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DiskIO</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">write</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">instance</span><span class="p">)</span> <span class="p">{</span>
+ </pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>If end is requested, this will contain a callback.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">ending</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
+<span class="p">}</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>This writes an object to disk.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DiskIO</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">persist</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">instance</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">outstandingWrites</span><span class="o">++</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">serialised</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">codec</span><span class="p">.</span><span class="nx">serialise</span><span class="p">(</span><span class="nx">instance</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">writeStream</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">serialised</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">outstandingWrites</span><span class="o">--</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">that</span><span class="p">.</span><span class="nx">outstandingWrites</span> <span class="o">===</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nx">that</span><span class="p">.</span><span class="nx">ending</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">that</span><span class="p">.</span><span class="nx">writeStream</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span> <span class="c1">// FIXME: we need to call the callback only after the end.</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">ending</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
-<span class="p">};</span>
-
-<span class="nx">DiskIO</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">openSync</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
-<span class="p">}</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>This deletes any database files.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DiskIO</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">deleteSync</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>First get the contents of the path.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">contents</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">path</span><span class="p">);</span>
- <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;contents:&#39;</span><span class="p">,</span> <span class="nx">contents</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>&lt;-- CONTINUE</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">}</span>
+<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>This opens the DiskIO for use.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DiskIO</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">openSync</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">preexisting</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
+ </pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>First get the contents of the path.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">contents</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">path</span><span class="p">);</span>
+ </pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>If there's a pre-existing file, we move it to old then read in the
+contents later.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">contents</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">if</span> <span class="p">(</span><span class="nx">contents</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">===</span> <span class="k">this</span><span class="p">.</span><span class="nx">FILENAME</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">fs</span><span class="p">.</span><span class="nx">renameSync</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">FILENAME</span><span class="p">,</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">OLD_FILENAME</span><span class="p">);</span>
+ <span class="nx">preexisting</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="p">}</span>
+ </pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Create a new file for persistence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">writeStream</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">WriteStream</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">FILENAME</span><span class="p">,</span>
+ <span class="p">{</span> <span class="nx">flags</span><span class="o">:</span> <span class="s1">&#39;w&#39;</span><span class="p">,</span> <span class="nx">encoding</span><span class="o">:</span> <span class="s1">&#39;utf8&#39;</span><span class="p">,</span> <span class="nx">mode</span><span class="o">:</span> <span class="mi">0666</span><span class="p">});</span>
+
+ <span class="k">if</span> <span class="p">(</span><span class="nx">preexisting</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">_load</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">OLD_FILENAME</span><span class="p">);</span>
+ <span class="p">}</span>
+<span class="p">}</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>This loads a database from disk.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DiskIO</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">_load</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">filepath</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>this.oldFd = fs.openSync(filepath, 'r');</p> </td> <td class="code"> <div class="highlight"><pre> </pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>CONTINUE</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">}</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>This will delete any pre-existing database files - for now it just moves them
+aside.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">DiskIO</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">deleteSync</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>First get the contents of the path.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">contents</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">path</span><span class="p">);</span>
+ <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;contents:&#39;</span><span class="p">,</span> <span class="nx">contents</span><span class="p">);</span>
+ <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">contents</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">if</span> <span class="p">(</span><span class="nx">contents</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">===</span> <span class="k">this</span><span class="p">.</span><span class="nx">FILENAME</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">fs</span><span class="p">.</span><span class="nx">renameSync</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">FILENAME</span><span class="p">,</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">FILENAME</span> <span class="o">+</span> <span class="s2">&quot;.deleteme&quot;</span><span class="p">);</span>
+ <span class="p">}</span>
+ <span class="k">if</span> <span class="p">(</span><span class="nx">contents</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">===</span> <span class="k">this</span><span class="p">.</span><span class="nx">OLD_FILENAME</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">fs</span><span class="p">.</span><span class="nx">renameSync</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">OLD_FILENAME</span><span class="p">,</span>
+ <span class="k">this</span><span class="p">.</span><span class="nx">path</span> <span class="o">+</span> <span class="s2">&quot;/&quot;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">OLD_FILENAME</span> <span class="o">+</span> <span class="s2">&quot;.deleteme&quot;</span><span class="p">);</span>
+ <span class="p">}</span>
+ <span class="p">}</span>
+<span class="p">}</span>
<span class="nx">DiskIO</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">outstandingWrites</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">fd</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span> <span class="c1">// FIXME: we need to call the callback only after the end.</span>
+ <span class="nx">callback</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span>
+ <span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ending</span> <span class="o">=</span> <span class="nx">callback</span><span class="p">;</span>
-<span class="p">}</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Export the symbols.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">DiskIO</span> <span class="o">=</span> <span class="nx">DiskIO</span><span class="p">;</span>
+<span class="p">}</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>Export the symbols.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">DiskIO</span> <span class="o">=</span> <span class="nx">DiskIO</span><span class="p">;</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
View
2 examples/create-database.js
@@ -22,7 +22,7 @@ db.registerConstructors(model.House, model.Person);
// use this. It's only used here so that we know this has created a brand new
// database.
db.deleteSync();
-process.exit(0);
+//process.exit(0);
// Open the database for business. Most once-per-process methods of DB are
// synchronous, as it's not really an issue and makes applications simpler.
View
6 lib/db.js
@@ -71,7 +71,7 @@ DB.prototype.openSync = function() {
DB.prototype.registerInstance = function(instance) {
var that = this;
- instance[this.UUID_TAG] = this.options.uuid();
+ instance[this.UUID_TAG] = this.uuid();
this.instances[instance[this.UUID_TAG]] = instance;
var store = {}; // the backing store for the instance data
@@ -113,8 +113,8 @@ DB.prototype.deleteSync = function() {
}
// Just a wrapper.
-DB.prototype.endSync = function() {
- this.io.endSync();
+DB.prototype.end = function(callback) {
+ this.io.end(callback);
}
// Export the symbols.
View
64 lib/disk-io.js
@@ -14,9 +14,19 @@ var codec = require('./swoj-codec')
function DiskIO(options) {
options = options || {};
- this.path = options.path || '/tmp/barricane.db';
+ this.path = options.path || '/tmp';
+ this.name = options.name || 'unnamed_db';
this.codec = options.codec || new codec.Codec(options.magic);
+ // Psuedo constants.
+ this.FILENAME = this.name + "."
+ + this.codec.defaultFileExtension + ".barricane-db";
+ this.OLD_FILENAME = this.LIVE_FILENAME + ".old";
+
+ //
+ this.fd = null; // The file descriptor for persistence.
+ this.oldFd = null; // The file descriptor for the old copy of the database.
+
this.writeStream = null;
// Writes must be counted, so we only close the file when all has been
@@ -28,31 +38,77 @@ function DiskIO(options) {
}
// This writes an object to disk.
-DiskIO.prototype.write = function (instance) {
+DiskIO.prototype.persist = function (instance) {
var that = this;
this.outstandingWrites++;
var serialised = this.codec.serialise(instance);
this.writeStream.write(serialised, function(err, result) {
that.outstandingWrites--;
if (that.outstandingWrites === 0 && that.ending) {
+ that.writeStream.end(); // FIXME: we need to call the callback only after the end.
that.ending(false, '');
}
});
};
+// This opens the DiskIO for use.
DiskIO.prototype.openSync = function() {
+ var preexisting = false;
+
+ // First get the contents of the path.
+ var contents = fs.readdirSync(this.path);
+
+ // If there's a pre-existing file, we move it to old then read in the
+ // contents later.
+ for (var i in contents) {
+ if (contents[i] === this.FILENAME) {
+ fs.renameSync(this.path + "/" + this.FILENAME,
+ this.path + "/" + this.OLD_FILENAME);
+ preexisting = true;
+ }
+ }
+
+ // Create a new file for persistence.
+ this.writeStream = fs.WriteStream(this.path + "/" + this.FILENAME,
+ { flags: 'w', encoding: 'utf8', mode: 0666});
+
+ if (preexisting) {
+ this._load(this.path + "/" + this.OLD_FILENAME);
+ }
+}
+
+// This loads a database from disk.
+DiskIO.prototype._load = function(filepath) {
+ //this.oldFd = fs.openSync(filepath, 'r');
+
+ // CONTINUE
}
-// This deletes any database files.
+
+// This will delete any pre-existing database files - for now it just moves them
+// aside.
DiskIO.prototype.deleteSync = function() {
// First get the contents of the path.
var contents = fs.readdirSync(this.path);
console.log('contents:', contents);
- // <-- CONTINUE
+ for (var i in contents) {
+ if (contents[i] === this.FILENAME) {
+ fs.renameSync(this.path + "/" + this.FILENAME,
+ this.path + "/" + this.FILENAME + ".deleteme");
+ }
+ if (contents[i] === this.OLD_FILENAME) {
+ fs.renameSync(this.path + "/" + this.OLD_FILENAME,
+ this.path + "/" + this.OLD_FILENAME + ".deleteme");
+ }
+ }
}
DiskIO.prototype.end = function(callback) {
+ if (this.outstandingWrites === 0) {
+ fd.end(); // FIXME: we need to call the callback only after the end.
+ callback(false, '');
+ }
this.ending = callback;
}

0 comments on commit ff7a77b

Please sign in to comment.