// Put key-value pairs. Note that it could be more efficient to use the Batcher // interface so you don't have to create and keep a slice of KeyValue. Some // databases like leveldb will copy on batch put anyway. func (db *BigTable) PutRange(ctx storage.Context, TKeyValue []storage.TKeyValue) error { if db == nil { return fmt.Errorf("Can't call PutRange() on nil BigTable") } if ctx == nil { return fmt.Errorf("Received nil context in PutRange()") } for _, tkeyvalue := range TKeyValue { unvKey, verKey, err := ctx.SplitKey(tkeyvalue.K) if err != nil { dvid.Errorf("Error in PutRange(): %v\n", err) } mut := api.NewMutation() mut.Set(familyName, encodeKey(verKey), 0, tkeyvalue.V) err = tbl.Apply(db.ctx, encodeKey(unvKey), mut) if err != nil { dvid.Errorf("Failed to Put value in PutRange()") } } return nil }
// Get returns a value given a key. func (db *BigTable) Get(ctx storage.Context, tk storage.TKey) ([]byte, error) { if db == nil { return nil, fmt.Errorf("Can't call Get() on nil BigTable") } if ctx == nil { return nil, fmt.Errorf("Received nil context in Get()") } unvKey, verKey, err := ctx.SplitKey(tk) if err != nil { dvid.Errorf("Error in Get(): %v\n", err) } r, err := tbl.ReadRow(db.ctx, encodeKey(unvKey)) //A missing row will return a zero-length map and a nil error if len(r) == 0 { return nil, err } if err != nil { return nil, err } value, err := getValue(r, verKey) if err != nil { return nil, err } return value, nil }
// KeysInRange returns a range of type-specific key components spanning (TkBeg, TkEnd). func (db *BigTable) KeysInRange(ctx storage.Context, TkBeg, TkEnd storage.TKey) ([]storage.TKey, error) { if db == nil { return nil, fmt.Errorf("Can't call KeysInRange() on nil BigTable") } if ctx == nil { return nil, fmt.Errorf("Received nil context in KeysInRange()") } tKeys := make([]storage.TKey, 0) unvKeyBeg, _, err := ctx.SplitKey(TkBeg) if err != nil { dvid.Errorf("Error in KeysInRange(): %v\n", err) } unvKeyEnd, _, err := ctx.SplitKey(TkEnd) if err != nil { dvid.Errorf("Error in KeysInRange(): %v\n", err) } rr := api.NewRange(encodeKey(unvKeyBeg), encodeKey(unvKeyEnd)) err = tbl.ReadRows(db.ctx, rr, func(r api.Row) bool { if len(r[familyName]) == 0 { dvid.Errorf("Error in KeysInRange(): row has no columns") return false } unvKeyRow, err := decodeKey(r.Key()) if err != nil { dvid.Errorf("Error in KeysInRange(): %v\n", err) return false } verKeyRow, err := decodeKey(r[familyName][0].Column) if err != nil { dvid.Errorf("Error in KeysInRange(): %v\n", err) return false } fullKey := storage.MergeKey(unvKeyRow, verKeyRow) tkey, err := storage.TKeyFromKey(fullKey) if err != nil { dvid.Errorf("Error in KeysInRange(): %v\n", err) return false } tKeys = append(tKeys, tkey) return true // keep going }, api.RowFilter(api.StripValueFilter())) return tKeys, err }
// GetRange returns a range of values spanning (TkBeg, kEnd) keys. func (db *BigTable) GetRange(ctx storage.Context, TkBeg, TkEnd storage.TKey) ([]*storage.TKeyValue, error) { if db == nil { return nil, fmt.Errorf("Can't call GetRange() on nil BigTable") } if ctx == nil { return nil, fmt.Errorf("Received nil context in GetRange()") } unvKeyBeg, _, err := ctx.SplitKey(TkBeg) if err != nil { dvid.Errorf("Error in GetRange(): %v\n", err) } unvKeyEnd, _, err := ctx.SplitKey(TkEnd) if err != nil { dvid.Errorf("Error in GetRange(): %v\n", err) } tKeyValues := make([]*storage.TKeyValue, 0) rr := api.NewRange(encodeKey(unvKeyBeg), encodeKey(unvKeyEnd)) err = tbl.ReadRows(db.ctx, rr, func(r api.Row) bool { unvKeyRow, err := decodeKey(r.Key()) if err != nil { dvid.Errorf("Error in GetRange() decodeKey(r.Key()): %v\n", err) return false } // dvid.Infof("GetRange() with row key= %v", r.Key()) for _, readItem := range r[familyName] { verKey, err := decodeKey(readItem.Column) if err != nil { dvid.Errorf("Error in GetRange() decodeKey(readItem.Column): %v\n", err) return false } fullKey := storage.MergeKey(unvKeyRow, verKey) // dvid.Infof("colum key= %v , timestamp = %v", verKey, readItem.Timestamp) tkey, err := storage.TKeyFromKey(fullKey) if err != nil { dvid.Errorf("Error in GetRange() storage.TKeyFromKey(fullKey): %v\n", err) return false } kv := storage.TKeyValue{tkey, readItem.Value} tKeyValues = append(tKeyValues, &kv) } return true // keep going }) return tKeyValues, err }
// Delete deletes a key-value pair so that subsequent Get on the key returns nil. func (db *BigTable) Delete(ctx storage.Context, tkey storage.TKey) error { if db == nil { return fmt.Errorf("Can't call Delete() on nil BigTable") } if ctx == nil { return fmt.Errorf("Received nil context in Delete()") } unvKey, verKey, err := ctx.SplitKey(tkey) if err != nil { dvid.Errorf("Error in Delete(): %v\n", err) } r, err := tbl.ReadRow(db.ctx, encodeKey(unvKey), api.RowFilter(api.StripValueFilter())) //A missing row will return a zero-length map and a nil error if len(r) == 0 { return fmt.Errorf("Error in Delete(): This unvKey doesn't exists") } if err != nil { return err } if len(r[familyName]) == 0 { return fmt.Errorf("Error in Delete(): This row is empty") } _, err = getValue(r, verKey) if err != nil { return fmt.Errorf("Error in Delete(): The version to be deleted doesn't exist") } mut := api.NewMutation() //There is only one version left, and is the one we are trying to delete\ //remove the whole row if len(r[familyName]) == 1 { mut.DeleteRow() } else { mut.DeleteCellsInColumn(familyName, encodeKey(verKey)) } err = tbl.Apply(db.ctx, encodeKey(unvKey), mut) if err != nil { return fmt.Errorf("Error in Delete(): %v\n", err) } return err }
// SendKeysInRange sends a range of full keys down a key channel. func (db *BigTable) SendKeysInRange(ctx storage.Context, TkBeg, TkEnd storage.TKey, ch storage.KeyChan) error { if db == nil { return fmt.Errorf("Can't call SendKeysInRange() on nil BigTable") } if ctx == nil { return fmt.Errorf("Received nil context in SendKeysInRange()") } unvKeyBeg, _, err := ctx.SplitKey(TkBeg) if err != nil { dvid.Errorf("Error in SendKeysInRange(): %v\n", err) } unvKeyEnd, _, err := ctx.SplitKey(TkEnd) if err != nil { dvid.Errorf("Error in SendKeysInRange(): %v\n", err) } rr := api.NewRange(encodeKey(unvKeyBeg), encodeKey(unvKeyEnd)) err = tbl.ReadRows(db.ctx, rr, func(r api.Row) bool { unvKeyRow, err := decodeKey(r.Key()) if err != nil { dvid.Errorf("Error in SendKeysInRange(): %v\n", err) return false } //I need the versioned key to merged it with the unversioned // and send it throu the channel for _, readItem := range r[familyName] { verKey, err := decodeKey(readItem.Column) if err != nil { dvid.Errorf("Error in SendKeysInRange(): %v\n", err) return false } fullKey := storage.MergeKey(unvKeyRow, verKey) ch <- fullKey } return true // keep going }, api.RowFilter(api.StripValueFilter())) return err }
// DeleteRange removes all key-value pairs with keys in the given range. // For all versions func (db *BigTable) DeleteRange(ctx storage.Context, TkBeg, TkEnd storage.TKey) error { if db == nil { return fmt.Errorf("Can't call DeleteRange() on nil BigTable") } if ctx == nil { return fmt.Errorf("Received nil context in DeleteRange()") } unvKeyBeg, _, err := ctx.SplitKey(TkBeg) if err != nil { return fmt.Errorf("Error in DeleteRange(): %v\n", err) } unvKeyEnd, _, err := ctx.SplitKey(TkEnd) if err != nil { return fmt.Errorf("Error in DeleteRange(): %v\n", err) } rr := api.NewRange(encodeKey(unvKeyBeg), encodeKey(unvKeyEnd)) err = tbl.ReadRows(db.ctx, rr, func(r api.Row) bool { unvKeyRow, err := decodeKey(r.Key()) if err != nil { dvid.Errorf("Error in DeleteRange(): %v\n", err) return false } mut := api.NewMutation() mut.DeleteRow() err = tbl.Apply(db.ctx, encodeKey(unvKeyRow), mut) if err != nil { dvid.Errorf("Failed to delete row in DeleteRange()") } return true // keep going }, api.RowFilter(api.StripValueFilter())) return err }
// Put writes a value with given key in a possibly versioned context. func (db *BigTable) Put(ctx storage.Context, tkey storage.TKey, value []byte) error { if db == nil { return fmt.Errorf("Can't call Put() on nil BigTable") } if ctx == nil { return fmt.Errorf("Received nil context in Put()") } unvKey, verKey, err := ctx.SplitKey(tkey) if err != nil { dvid.Errorf("Error in Put(): %v\n", err) } mut := api.NewMutation() // dvid.Infof("Putting value %s\n", string(value)) mut.Set(familyName, encodeKey(verKey), 0, value) err = tbl.Apply(db.ctx, encodeKey(unvKey), mut) if err != nil { return fmt.Errorf("Error in Put(): %v\n", err) } return err }
// DeleteAll removes all key-value pairs for the context. If allVersions is true, // then all versions of the data instance are deleted. func (db *BigTable) DeleteAll(ctx storage.Context, allVersions bool) error { if db == nil { return fmt.Errorf("Can't call DeleteAll() on nil BigTable") } if ctx == nil { return fmt.Errorf("Received nil context in DeleteAll()") } //Row range corresponde to all keys corresponding to this data instace. min, max := ctx.KeyRange() rr := api.NewRange(encodeKey(min), encodeKey(max)) err := tbl.ReadRows(db.ctx, rr, func(r api.Row) bool { unvKeyRow, err := decodeKey(r.Key()) if err != nil { dvid.Errorf("Error in DeleteAll(): %v\n", err) return false } if allVersions { mut := api.NewMutation() mut.DeleteRow() err := tbl.Apply(db.ctx, encodeKey(unvKeyRow), mut) if err != nil { dvid.Errorf("Failed to delete row") } } else { emptyTkey := make([]byte, 0) _, versionToDelete, err := ctx.SplitKey(emptyTkey) if err != nil { dvid.Errorf("Error in DeleteAll(): %v\n", err) return false } for _, readItem := range r[familyName] { verKey, err := decodeKey(readItem.Column) if err != nil { dvid.Errorf("Error in DeleteAll(): %v\n", err) return false } if bytes.Equal(verKey, versionToDelete) { mut := api.NewMutation() mut.DeleteCellsInColumn(familyName, encodeKey(verKey)) err := tbl.Apply(db.ctx, encodeKey(unvKeyRow), mut) if err != nil { dvid.Errorf("Failed to DeleteCellsInColumn in DeleteAll()") } return true // One I found the version I don't have to keep serching for it. } } } return true // keep going }, api.RowFilter(api.StripValueFilter())) return err }
// ProcessRange sends a range of type key-value pairs to type-specific chunk handlers, // allowing chunk processing to be concurrent with key-value sequential reads. // Since the chunks are typically sent during sequential read iteration, the // receiving function can be organized as a pool of chunk handling goroutines. // See datatype/imageblk.ProcessChunk() for an example. func (db *BigTable) ProcessRange(ctx storage.Context, TkBeg, TkEnd storage.TKey, op *storage.ChunkOp, f storage.ChunkFunc) error { if db == nil { return fmt.Errorf("Can't call ProcessRange() on nil BigTable") } if ctx == nil { return fmt.Errorf("Received nil context in ProcessRange()") } unvKeyBeg, verKey, err := ctx.SplitKey(TkBeg) if err != nil { dvid.Errorf("Error in ProcessRange(): %v\n", err) } unvKeyEnd, _, err := ctx.SplitKey(TkEnd) if err != nil { dvid.Errorf("Error in ProcessRange(): %v\n", err) } rr := api.NewRange(encodeKey(unvKeyBeg), encodeKey(unvKeyEnd)) err = tbl.ReadRows(db.ctx, rr, func(r api.Row) bool { if len(r[familyName]) == 0 { dvid.Errorf("Error in KeysInRange(): row has no columns") return false } unvKeyRow, err := decodeKey(r.Key()) if err != nil { dvid.Errorf("Error in ProcessRange(): %v\n", err) return false } verKeyRow, err := decodeKey(r[familyName][0].Column) if err != nil { dvid.Errorf("Error in ProcessRange(): %v\n", err) return false } fullKey := storage.MergeKey(unvKeyRow, verKeyRow) tkey, err := storage.TKeyFromKey(fullKey) if err != nil { dvid.Errorf("Error in ProcessRange(): %v\n", err) return false } if op.Wg != nil { op.Wg.Add(1) } value, err := getValue(r, verKey) if err != nil { dvid.Errorf("Error in ProcessRange(): %v\n", err) return false } tkv := storage.TKeyValue{tkey, value} chunk := &storage.Chunk{op, &tkv} if err := f(chunk); err != nil { dvid.Errorf("Error in ProcessRange(): %v\n", err) return false } return true // keep going }) return err }