failstore.go 3.18 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// Package failstore implements a datastore which can produce
// custom failures on operations by calling a user-provided
// error function.
package failstore

import (
	ds "github.com/ipfs/go-datastore"
	dsq "github.com/ipfs/go-datastore/query"
)

// Failstore is a datastore which fails according to a user-provided
// function.
type Failstore struct {
	child   ds.Datastore
	errfunc func(string) error
}

// NewFailstore creates a new datastore with the given error function.
// The efunc will be called with different strings depending on the
// datastore function: put, get, has, delete, query, batch, batch-put,
// batch-delete and batch-commit are the possible values.
func NewFailstore(c ds.Datastore, efunc func(string) error) *Failstore {
	return &Failstore{
		child:   c,
		errfunc: efunc,
	}
}

// Put puts a key/value into the datastore.
30
func (d *Failstore) Put(k ds.Key, val []byte) error {
31 32 33 34 35 36 37 38 39
	err := d.errfunc("put")
	if err != nil {
		return err
	}

	return d.child.Put(k, val)
}

// Get retrieves a value from the datastore.
40
func (d *Failstore) Get(k ds.Key) ([]byte, error) {
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
	err := d.errfunc("get")
	if err != nil {
		return nil, err
	}

	return d.child.Get(k)
}

// Has returns if the datastore contains a key/value.
func (d *Failstore) Has(k ds.Key) (bool, error) {
	err := d.errfunc("has")
	if err != nil {
		return false, err
	}

	return d.child.Has(k)
}

Steven Allen's avatar
Steven Allen committed
59 60 61 62 63 64 65 66 67 68
// GetSize returns the size of the value in the datastore, if present.
func (d *Failstore) GetSize(k ds.Key) (int, error) {
	err := d.errfunc("getsize")
	if err != nil {
		return -1, err
	}

	return d.child.GetSize(k)
}

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
// Delete removes a key/value from the datastore.
func (d *Failstore) Delete(k ds.Key) error {
	err := d.errfunc("delete")
	if err != nil {
		return err
	}

	return d.child.Delete(k)
}

// Query performs a query on the datastore.
func (d *Failstore) Query(q dsq.Query) (dsq.Results, error) {
	err := d.errfunc("query")
	if err != nil {
		return nil, err
	}

	return d.child.Query(q)
}

89 90 91 92 93 94 95 96
// DiskUsage implements the PersistentDatastore interface.
func (d *Failstore) DiskUsage() (uint64, error) {
	if err := d.errfunc("disk-usage"); err != nil {
		return 0, err
	}
	return ds.DiskUsage(d.child)
}

97 98 99 100 101
//  Close implements the Datastore interface
func (d *Failstore) Close() error {
	return d.child.Close()
}

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
// FailBatch implements batching operations on the Failstore.
type FailBatch struct {
	cb     ds.Batch
	dstore *Failstore
}

// Batch returns a new Batch Failstore.
func (d *Failstore) Batch() (ds.Batch, error) {
	if err := d.errfunc("batch"); err != nil {
		return nil, err
	}

	b, err := d.child.(ds.Batching).Batch()
	if err != nil {
		return nil, err
	}

	return &FailBatch{
		cb:     b,
		dstore: d,
	}, nil
}

// Put does a batch put.
126
func (b *FailBatch) Put(k ds.Key, val []byte) error {
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
	if err := b.dstore.errfunc("batch-put"); err != nil {
		return err
	}

	return b.cb.Put(k, val)
}

// Delete does a batch delete.
func (b *FailBatch) Delete(k ds.Key) error {
	if err := b.dstore.errfunc("batch-delete"); err != nil {
		return err
	}

	return b.cb.Delete(k)
}

// Commit commits all operations in the batch.
func (b *FailBatch) Commit() error {
	if err := b.dstore.errfunc("batch-commit"); err != nil {
		return err
	}

	return b.cb.Commit()
}