Skip to content

Commit

Permalink
Merge branch readme into master.
Browse files Browse the repository at this point in the history
  • Loading branch information
flatheadmill committed Jun 24, 2013
2 parents d3a9da2 + b07d864 commit 4fae0d4
Showing 1 changed file with 106 additions and 16 deletions.
122 changes: 106 additions & 16 deletions README.md
Expand Up @@ -16,42 +16,44 @@ Read the [Docco](http://bigeasy.github.io/strata/)! Read the
Strata is part of a collection of database primitives that you can use to design
your own distributed databases for your Node.js applications.

Strata is a **concurrent**, **b‑tree** **primitive**, in
Strata is a **concurrent**, **b‑tree** **primitive**, in
**pure-JavaScript** for Node.js.

A **b‑tree** is a data structure used by databases to store records
organized in large pages on disk.

By **concurrent** I mean that multiple queries can make progress on a descent of
the b#8209;tree. Multple reads can all navigate the b#8209;tree
simultaneously, of course. Multple reads can also make progress in the presence
the b‑tree. Multiple reads can all navigate the b‑tree
simultaneously, of course. Multiple reads can also make progress in the presence
of a write, so long as they are not reading a page that is being written. This
is the equivalence to "threading" in other database engines, but evented for
Node.js.

Strata is a database **primitive**, it is not supposed to be used a as a general
purpose database by it's lonesome, but an interface to a b#8209;tree and it's
purpose database by it's lonesome, but an interface to a b‑tree and it's
concepts that you can use to create different types database strategies.

### Brace Yourself

The interface to Strata is *not* an API, it is a programmer's interface to
b#8209;tree concepts. It is easy to use, if you know how a b#8209;tree works,
b‑tree concepts. It is easy to use, if you know how a b‑tree works,
but please don't complain about encapsulation; it is not a database engine, it
is a b#8209;tree structure and the *details are supposed to be exposed*.
is a b‑tree structure and the *details are supposed to be exposed*.

The Strata b#8209;tree interface describes a b#8209;tree as a collection of
actors, not a collection of objects. A b#8209;tree isn't all about "pages."
The Strata b‑tree interface describes a b‑tree as a collection of
actors, not a collection of objects. A b‑tree isn't all about "pages."
It's about descending, navigating, appending, and balancing a tree. When you
read the code, you're going to find these people-named classes who do things.

Finally, Strata is an ancient project of mine, that began before anyone really
know how a Node.js library is supposed to look. I used closure based objects,
Finally, Strata is an ancient project of mine, that began before I really know
how a Node.js library is supposed to look, so I used closure based objects,
which is a way to go, but most noders use prototype based objects. That's what
I'd do I was to do it all again.
I'd do I was to do it all over again, or maybe not; because I like the way the
code turned out.

I'm going to cut this whinging in the final `README.md`. It's here to vent my
defensiveness and remind of who my audience is.
defensiveness and remind of who my audience is; people who are experimenting
with their own database structure for their own domain-specific database.

### A Note on Examples

Expand Down Expand Up @@ -85,9 +87,13 @@ Install from NPM.
npm install b-tree
```

## B-Tree Properties

TK: Unique keys, but duplicate keys are super easy to fake with a simple recipe.

## Creating a B-Tree

You must create the b#8209;tree object first, specifying the size of the inner
You must create the b‑tree object first, specifying the size of the inner
branch pages as a count of child pages, and the size of the leaf pages as a
count of stored records.

Expand All @@ -110,7 +116,7 @@ function openOrCreate (directory, callback) {
openOrCreate('/home/alan/strata', function (error, strata) {
if (error) throw error;

// Do something with an open b#8209;tree...
// Do something with an open b‑tree...
});
```

Expand All @@ -119,13 +125,15 @@ Properties to the constructor...
### `new Strata(location[, options])`.

Constructs a new b-tree that stores its files in the directory provided by
`location`. It does not open or close the b#8209;tree.
`location`. It does not open or close the b‑tree.

#### `options`

`new Strata()` takes an optional options object as its second argument; the
following properties are accepted:

* `extractor`: A function that extracts the key from the record.
* `comparator`: A function that is used to compare keys.
* `leafSize`: The maximum size in records of a leaf page before it is it split.
* `branchSize`: The maximum size in child pages of a branch page before it is
split.
Expand All @@ -142,7 +150,89 @@ Opens the b-tree.
Creates a new, empty b-tree. It will raise an exception if there is *anything*
in the location directory.

## Primitive Operations
## Searching and Editing

You search and edit the b‑ separate from editing it.

### Searching the B‑Tree

With Strata you either create read-only iterator, or a read/write mutator. The
mutator is a superset of the iterator so let's start there.

```javascript
function hasKey (strata, sought, callback) {
var check = validator(callback), found;

strata.iterator(sought, check(atLeaf));

function atLeaf (cursor) {
found = cursor.index >= 0;
cursor.unlock();
callback(null, found);
}
}

hasKey(strata, 'c', function (error, exists) {
if (error) throw error;
if (exists) console.log('I found it.');
});
```

In the above, we create a read-only `Cursor` using the `Strata.iterator`
function. That returns an iterator that holds a shared lock on the leaf page
that either contains the records for the given key, or else would contain the
record for the given key if it existed in the leaf page. The `Cursor` says that
the record is here, or it should go here.

If the `Cursor.index` property is zero or more, it is the index of the record in
the leaf page. If the `Cursor.index` property is less than zero, then it's
compliment is the index of where the record should go in the leaf page.

In the `hasKey` function above we simply return whether or not the record exists
based on the cursor index.

### Scanning the B‑Tree

```javascript
function range (strata, start, stop, callback) {
var check = validator(callback), found = [];

strata.iterator(start, check(atLeaf));

function atLeaf (cursor) {
fetch(cursor.index < 0 ? ~cursor.index : cursor.index);

function fetch (index) {
if (index < cursor.length) {
cursor.get(index, check(push));
} else {
cursor.next(check(advanced));
}
}

function push (record) {
if (record < stop) {
found.push(record);
fetch(index + 1);
} else {
done();
}
}

function advanced (success) {
if (success) done();
else fetch(0);
}

function done () {
cursor.unlock();
callback(null, found);
}
}
}

range(strata, 'c', 'i', function (error, found) {
if (error) throw error;
console.log(found);
});
```

0 comments on commit 4fae0d4

Please sign in to comment.