Commit bffc5fdb authored by Steven Allen's avatar Steven Allen

doc(mount): fix and improve documentation

parent d009ffbd
...@@ -18,11 +18,18 @@ var ( ...@@ -18,11 +18,18 @@ var (
ErrNoMount = errors.New("no datastore mounted for this key") ErrNoMount = errors.New("no datastore mounted for this key")
) )
// Mount defines a datastore mount. It mounts the given datastore at the given
// prefix.
type Mount struct { type Mount struct {
Prefix ds.Key Prefix ds.Key
Datastore ds.Datastore Datastore ds.Datastore
} }
// New creates a new mount datstore from the given mounts. See the documentation
// on Datastore for details.
//
// The order of the mounts does not matter, they will be applied most specific
// to least specific.
func New(mounts []Mount) *Datastore { func New(mounts []Mount) *Datastore {
// make a copy so we're sure it doesn't mutate // make a copy so we're sure it doesn't mutate
m := make([]Mount, len(mounts)) m := make([]Mount, len(mounts))
...@@ -31,12 +38,36 @@ func New(mounts []Mount) *Datastore { ...@@ -31,12 +38,36 @@ func New(mounts []Mount) *Datastore {
return &Datastore{mounts: m} return &Datastore{mounts: m}
} }
// Datastore is a mount datastore. In this datastore, keys live under the most
// specific mounted sub-datastore. That is, given sub-datastores mounted under:
//
// * /
// * /foo
// * /foo/bar
//
// Keys would be written as follows:
//
// * /foo, /foobar, /baz would all live under /.
// * /foo/baz, /foo/bar, etc. would live under /foo.
// * /foo/bar/baz would live under /foo/bar.
//
// Additionally, even if the datastore mounted at / contains the key /foo/thing,
// the datastore mounted at /foo would mask this value in get, deletes, and
// query results.
//
// Finally, if no root (/) mount is provided, operations on keys living outside
// all of the provided mounts will behave as follows:
//
// * Get - Returns datastore.ErrNotFound.
// * Query - Returns no results.
// * Put - Returns ErrNoMount.
type Datastore struct { type Datastore struct {
mounts []Mount mounts []Mount
} }
var _ ds.Datastore = (*Datastore)(nil) var _ ds.Datastore = (*Datastore)(nil)
// lookup looks up the datastore in which the given key lives.
func (d *Datastore) lookup(key ds.Key) (ds.Datastore, ds.Key, ds.Key) { func (d *Datastore) lookup(key ds.Key) (ds.Datastore, ds.Key, ds.Key) {
for _, m := range d.mounts { for _, m := range d.mounts {
if m.Prefix.IsAncestorOf(key) { if m.Prefix.IsAncestorOf(key) {
...@@ -147,16 +178,32 @@ func (h *querySet) next() (query.Result, bool) { ...@@ -147,16 +178,32 @@ func (h *querySet) next() (query.Result, bool) {
return next, true return next, true
} }
// lookupAll returns all mounts that might contain keys that are descendant of <key> // lookupAll returns all mounts that might contain keys that are strict
// descendants of <key>. It will not return mounts that match key exactly.
// //
// Matching: /ao/e // Specifically, this function will return three slices:
// //
// / B /ao/e // * The matching datastores.
// /a/ not matching // * The prefixes where each matching datastore has been mounted.
// /ao/ B /e // * The prefix within these datastores at which descendants of the passed key
// /ao/e/ A / // live. If the mounted datastore is fully contained within the given key,
// /ao/e/uh/ A / // this will be /.
// /aoe/ not matching //
// By example, given the datastores:
//
// * / - root
// * /foo -
// * /bar
// * /foo/bar
//
// This function function will behave as follows:
//
// * key -> ([mountpoints], [rests]) # comment
// * / -> ([/, /foo, /bar, /foo/bar], [/, /, /, /]) # all datastores
// * /foo -> ([/foo, /foo/bar], [/, /]) # all datastores under /foo
// * /foo/bar -> ([/foo/bar], [/]) # /foo/bar
// * /bar/foo -> ([/bar], [/foo]) # the datastore mounted at /bar, rest is /foo
// * /ba -> ([/], [/]) # the root; only full components are matched.
func (d *Datastore) lookupAll(key ds.Key) (dst []ds.Datastore, mountpoint, rest []ds.Key) { func (d *Datastore) lookupAll(key ds.Key) (dst []ds.Datastore, mountpoint, rest []ds.Key) {
for _, m := range d.mounts { for _, m := range d.mounts {
if m.Prefix.IsDescendantOf(key) { if m.Prefix.IsDescendantOf(key) {
...@@ -179,6 +226,10 @@ func (d *Datastore) lookupAll(key ds.Key) (dst []ds.Datastore, mountpoint, rest ...@@ -179,6 +226,10 @@ func (d *Datastore) lookupAll(key ds.Key) (dst []ds.Datastore, mountpoint, rest
return dst, mountpoint, rest return dst, mountpoint, rest
} }
// Put puts the given value into the datastore at the given key.
//
// Returns ErrNoMount if there no datastores are mounted at the appropriate
// prefix for the given key.
func (d *Datastore) Put(key ds.Key, value []byte) error { func (d *Datastore) Put(key ds.Key, value []byte) error {
cds, _, k := d.lookup(key) cds, _, k := d.lookup(key)
if cds == nil { if cds == nil {
...@@ -201,6 +252,7 @@ func (d *Datastore) Sync(prefix ds.Key) error { ...@@ -201,6 +252,7 @@ func (d *Datastore) Sync(prefix ds.Key) error {
return nil return nil
} }
// Get returns the value associated with the key from the appropriate datastore.
func (d *Datastore) Get(key ds.Key) (value []byte, err error) { func (d *Datastore) Get(key ds.Key) (value []byte, err error) {
cds, _, k := d.lookup(key) cds, _, k := d.lookup(key)
if cds == nil { if cds == nil {
...@@ -209,6 +261,8 @@ func (d *Datastore) Get(key ds.Key) (value []byte, err error) { ...@@ -209,6 +261,8 @@ func (d *Datastore) Get(key ds.Key) (value []byte, err error) {
return cds.Get(k) return cds.Get(k)
} }
// Has returns the true if there exists a value associated with key in the
// appropriate datastore.
func (d *Datastore) Has(key ds.Key) (exists bool, err error) { func (d *Datastore) Has(key ds.Key) (exists bool, err error) {
cds, _, k := d.lookup(key) cds, _, k := d.lookup(key)
if cds == nil { if cds == nil {
...@@ -217,6 +271,8 @@ func (d *Datastore) Has(key ds.Key) (exists bool, err error) { ...@@ -217,6 +271,8 @@ func (d *Datastore) Has(key ds.Key) (exists bool, err error) {
return cds.Has(k) return cds.Has(k)
} }
// Get returns the size of the value associated with the key in the appropriate
// datastore.
func (d *Datastore) GetSize(key ds.Key) (size int, err error) { func (d *Datastore) GetSize(key ds.Key) (size int, err error) {
cds, _, k := d.lookup(key) cds, _, k := d.lookup(key)
if cds == nil { if cds == nil {
...@@ -225,6 +281,10 @@ func (d *Datastore) GetSize(key ds.Key) (size int, err error) { ...@@ -225,6 +281,10 @@ func (d *Datastore) GetSize(key ds.Key) (size int, err error) {
return cds.GetSize(k) return cds.GetSize(k)
} }
// Delete deletes the value associated with the key in the appropriate
// datastore.
//
// Delete returns no error if there is no value associated with the given key.
func (d *Datastore) Delete(key ds.Key) error { func (d *Datastore) Delete(key ds.Key) error {
cds, _, k := d.lookup(key) cds, _, k := d.lookup(key)
if cds == nil { if cds == nil {
...@@ -233,6 +293,11 @@ func (d *Datastore) Delete(key ds.Key) error { ...@@ -233,6 +293,11 @@ func (d *Datastore) Delete(key ds.Key) error {
return cds.Delete(k) return cds.Delete(k)
} }
// Query queries the appropriate mounted datastores, merging the results
// according to the given orders.
//
// If a query prefix is specified, Query will avoid querying datastores mounted
// outside that prefix.
func (d *Datastore) Query(master query.Query) (query.Results, error) { func (d *Datastore) Query(master query.Query) (query.Results, error) {
childQuery := query.Query{ childQuery := query.Query{
Prefix: master.Prefix, Prefix: master.Prefix,
...@@ -288,6 +353,7 @@ func (d *Datastore) Query(master query.Query) (query.Results, error) { ...@@ -288,6 +353,7 @@ func (d *Datastore) Query(master query.Query) (query.Results, error) {
return qr, nil return qr, nil
} }
// Close closes all mounted datastores.
func (d *Datastore) Close() error { func (d *Datastore) Close() error {
for _, d := range d.mounts { for _, d := range d.mounts {
err := d.Datastore.Close() err := d.Datastore.Close()
...@@ -319,6 +385,7 @@ type mountBatch struct { ...@@ -319,6 +385,7 @@ type mountBatch struct {
d *Datastore d *Datastore
} }
// Batch returns a batch that operates over all mounted datastores.
func (d *Datastore) Batch() (ds.Batch, error) { func (d *Datastore) Batch() (ds.Batch, error) {
return &mountBatch{ return &mountBatch{
mounts: make(map[string]ds.Batch), mounts: make(map[string]ds.Batch),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment