1package datastore 2 3import ( 4 "log" 5 6 dsq "github.com/ipfs/go-datastore/query" 7) 8 9// Here are some basic datastore implementations. 10 11// MapDatastore uses a standard Go map for internal storage. 12type MapDatastore struct { 13 values map[Key][]byte 14} 15 16// NewMapDatastore constructs a MapDatastore. It is _not_ thread-safe by 17// default, wrap using sync.MutexWrap if you need thread safety (the answer here 18// is usually yes). 19func NewMapDatastore() (d *MapDatastore) { 20 return &MapDatastore{ 21 values: make(map[Key][]byte), 22 } 23} 24 25// Put implements Datastore.Put 26func (d *MapDatastore) Put(key Key, value []byte) (err error) { 27 d.values[key] = value 28 return nil 29} 30 31// Sync implements Datastore.Sync 32func (d *MapDatastore) Sync(prefix Key) error { 33 return nil 34} 35 36// Get implements Datastore.Get 37func (d *MapDatastore) Get(key Key) (value []byte, err error) { 38 val, found := d.values[key] 39 if !found { 40 return nil, ErrNotFound 41 } 42 return val, nil 43} 44 45// Has implements Datastore.Has 46func (d *MapDatastore) Has(key Key) (exists bool, err error) { 47 _, found := d.values[key] 48 return found, nil 49} 50 51// GetSize implements Datastore.GetSize 52func (d *MapDatastore) GetSize(key Key) (size int, err error) { 53 if v, found := d.values[key]; found { 54 return len(v), nil 55 } 56 return -1, ErrNotFound 57} 58 59// Delete implements Datastore.Delete 60func (d *MapDatastore) Delete(key Key) (err error) { 61 delete(d.values, key) 62 return nil 63} 64 65// Query implements Datastore.Query 66func (d *MapDatastore) Query(q dsq.Query) (dsq.Results, error) { 67 re := make([]dsq.Entry, 0, len(d.values)) 68 for k, v := range d.values { 69 e := dsq.Entry{Key: k.String(), Size: len(v)} 70 if !q.KeysOnly { 71 e.Value = v 72 } 73 re = append(re, e) 74 } 75 r := dsq.ResultsWithEntries(q, re) 76 r = dsq.NaiveQueryApply(q, r) 77 return r, nil 78} 79 80func (d *MapDatastore) Batch() (Batch, error) { 81 return NewBasicBatch(d), nil 82} 83 84func (d *MapDatastore) Close() error { 85 return nil 86} 87 88// NullDatastore stores nothing, but conforms to the API. 89// Useful to test with. 90type NullDatastore struct { 91} 92 93// NewNullDatastore constructs a null datastoe 94func NewNullDatastore() *NullDatastore { 95 return &NullDatastore{} 96} 97 98// Put implements Datastore.Put 99func (d *NullDatastore) Put(key Key, value []byte) (err error) { 100 return nil 101} 102 103// Sync implements Datastore.Sync 104func (d *NullDatastore) Sync(prefix Key) error { 105 return nil 106} 107 108// Get implements Datastore.Get 109func (d *NullDatastore) Get(key Key) (value []byte, err error) { 110 return nil, ErrNotFound 111} 112 113// Has implements Datastore.Has 114func (d *NullDatastore) Has(key Key) (exists bool, err error) { 115 return false, nil 116} 117 118// Has implements Datastore.GetSize 119func (d *NullDatastore) GetSize(key Key) (size int, err error) { 120 return -1, ErrNotFound 121} 122 123// Delete implements Datastore.Delete 124func (d *NullDatastore) Delete(key Key) (err error) { 125 return nil 126} 127 128// Query implements Datastore.Query 129func (d *NullDatastore) Query(q dsq.Query) (dsq.Results, error) { 130 return dsq.ResultsWithEntries(q, nil), nil 131} 132 133func (d *NullDatastore) Batch() (Batch, error) { 134 return NewBasicBatch(d), nil 135} 136 137func (d *NullDatastore) Close() error { 138 return nil 139} 140 141// LogDatastore logs all accesses through the datastore. 142type LogDatastore struct { 143 Name string 144 child Datastore 145} 146 147// Shim is a datastore which has a child. 148type Shim interface { 149 Datastore 150 151 Children() []Datastore 152} 153 154// NewLogDatastore constructs a log datastore. 155func NewLogDatastore(ds Datastore, name string) *LogDatastore { 156 if len(name) < 1 { 157 name = "LogDatastore" 158 } 159 return &LogDatastore{Name: name, child: ds} 160} 161 162// Children implements Shim 163func (d *LogDatastore) Children() []Datastore { 164 return []Datastore{d.child} 165} 166 167// Put implements Datastore.Put 168func (d *LogDatastore) Put(key Key, value []byte) (err error) { 169 log.Printf("%s: Put %s\n", d.Name, key) 170 // log.Printf("%s: Put %s ```%s```", d.Name, key, value) 171 return d.child.Put(key, value) 172} 173 174// Sync implements Datastore.Sync 175func (d *LogDatastore) Sync(prefix Key) error { 176 log.Printf("%s: Sync %s\n", d.Name, prefix) 177 return d.child.Sync(prefix) 178} 179 180// Get implements Datastore.Get 181func (d *LogDatastore) Get(key Key) (value []byte, err error) { 182 log.Printf("%s: Get %s\n", d.Name, key) 183 return d.child.Get(key) 184} 185 186// Has implements Datastore.Has 187func (d *LogDatastore) Has(key Key) (exists bool, err error) { 188 log.Printf("%s: Has %s\n", d.Name, key) 189 return d.child.Has(key) 190} 191 192// GetSize implements Datastore.GetSize 193func (d *LogDatastore) GetSize(key Key) (size int, err error) { 194 log.Printf("%s: GetSize %s\n", d.Name, key) 195 return d.child.GetSize(key) 196} 197 198// Delete implements Datastore.Delete 199func (d *LogDatastore) Delete(key Key) (err error) { 200 log.Printf("%s: Delete %s\n", d.Name, key) 201 return d.child.Delete(key) 202} 203 204// DiskUsage implements the PersistentDatastore interface. 205func (d *LogDatastore) DiskUsage() (uint64, error) { 206 log.Printf("%s: DiskUsage\n", d.Name) 207 return DiskUsage(d.child) 208} 209 210// Query implements Datastore.Query 211func (d *LogDatastore) Query(q dsq.Query) (dsq.Results, error) { 212 log.Printf("%s: Query\n", d.Name) 213 log.Printf("%s: q.Prefix: %s\n", d.Name, q.Prefix) 214 log.Printf("%s: q.KeysOnly: %v\n", d.Name, q.KeysOnly) 215 log.Printf("%s: q.Filters: %d\n", d.Name, len(q.Filters)) 216 log.Printf("%s: q.Orders: %d\n", d.Name, len(q.Orders)) 217 log.Printf("%s: q.Offset: %d\n", d.Name, q.Offset) 218 219 return d.child.Query(q) 220} 221 222// LogBatch logs all accesses through the batch. 223type LogBatch struct { 224 Name string 225 child Batch 226} 227 228func (d *LogDatastore) Batch() (Batch, error) { 229 log.Printf("%s: Batch\n", d.Name) 230 if bds, ok := d.child.(Batching); ok { 231 b, err := bds.Batch() 232 233 if err != nil { 234 return nil, err 235 } 236 return &LogBatch{ 237 Name: d.Name, 238 child: b, 239 }, nil 240 } 241 return nil, ErrBatchUnsupported 242} 243 244// Put implements Batch.Put 245func (d *LogBatch) Put(key Key, value []byte) (err error) { 246 log.Printf("%s: BatchPut %s\n", d.Name, key) 247 // log.Printf("%s: Put %s ```%s```", d.Name, key, value) 248 return d.child.Put(key, value) 249} 250 251// Delete implements Batch.Delete 252func (d *LogBatch) Delete(key Key) (err error) { 253 log.Printf("%s: BatchDelete %s\n", d.Name, key) 254 return d.child.Delete(key) 255} 256 257// Commit implements Batch.Commit 258func (d *LogBatch) Commit() (err error) { 259 log.Printf("%s: BatchCommit\n", d.Name) 260 return d.child.Commit() 261} 262 263func (d *LogDatastore) Close() error { 264 log.Printf("%s: Close\n", d.Name) 265 return d.child.Close() 266} 267 268func (d *LogDatastore) Check() error { 269 if c, ok := d.child.(CheckedDatastore); ok { 270 return c.Check() 271 } 272 return nil 273} 274 275func (d *LogDatastore) Scrub() error { 276 if c, ok := d.child.(ScrubbedDatastore); ok { 277 return c.Scrub() 278 } 279 return nil 280} 281 282func (d *LogDatastore) CollectGarbage() error { 283 if c, ok := d.child.(GCDatastore); ok { 284 return c.CollectGarbage() 285 } 286 return nil 287} 288