// Delete removes a value with given key. func (db *LevelDB) Delete(ctx storage.Context, tk storage.TKey) error { if db == nil { return fmt.Errorf("Can't call Delete on nil LevelDB") } if ctx == nil { return fmt.Errorf("Received nil context in Delete()") } wo := db.options.WriteOptions var err error key := ctx.ConstructKey(tk) if !ctx.Versioned() { dvid.StartCgo() err = db.ldb.Delete(wo, key) dvid.StopCgo() } else { vctx, ok := ctx.(storage.VersionedCtx) if !ok { return fmt.Errorf("Non-versioned context that says it's versioned received in Delete(): %v", ctx) } tombstoneKey := vctx.TombstoneKey(tk) batch := db.NewBatch(vctx).(*goBatch) batch.WriteBatch.Delete(key) batch.WriteBatch.Put(tombstoneKey, dvid.EmptyValue()) if err = batch.Commit(); err != nil { dvid.Criticalf("Error on batch commit of Delete: %v\n", err) err = fmt.Errorf("Error on batch commit of Delete: %v", err) } } return err }
func (batch *goBatch) Delete(tk storage.TKey) { if batch == nil || batch.ctx == nil { dvid.Criticalf("Received nil batch or nil batch context in batch.Delete()\n") return } dvid.StartCgo() defer dvid.StopCgo() key := batch.ctx.ConstructKey(tk) if batch.vctx != nil { tombstone := batch.vctx.TombstoneKey(tk) // This will now have current version batch.WriteBatch.Put(tombstone, dvid.EmptyValue()) } batch.WriteBatch.Delete(key) }
func (d *Data) handleSizeEvent(in <-chan datastore.SyncMessage, done <-chan struct{}) { store, err := storage.SmallDataStore() if err != nil { dvid.Errorf("Data type labelvol had error initializing store: %v\n", err) return } batcher, ok := store.(storage.KeyValueBatcher) if !ok { dvid.Errorf("Data type labelvol requires batch-enabled store, which %q is not\n", store) return } for msg := range in { ctx := datastore.NewVersionedCtx(d, msg.Version) select { case <-done: return default: switch delta := msg.Delta.(type) { case labels.DeltaNewSize: batch := batcher.NewBatch(ctx) newKey := NewSizeLabelTKey(delta.Size, delta.Label) batch.Put(newKey, dvid.EmptyValue()) newKey = NewLabelSizeTKey(delta.Label, delta.Size) batch.Put(newKey, dvid.EmptyValue()) if err := batch.Commit(); err != nil { dvid.Errorf("Error on updating label sizes on %s: %v\n", ctx, err) } case labels.DeltaDeleteSize: if delta.OldKnown { batch := batcher.NewBatch(ctx) oldKey := NewSizeLabelTKey(delta.OldSize, delta.Label) batch.Delete(oldKey) oldKey = NewLabelSizeTKey(delta.Label, delta.OldSize) batch.Delete(oldKey) if err := batch.Commit(); err != nil { dvid.Errorf("Error on updating label sizes on %s: %v\n", ctx, err) } } else { // TODO -- Make transactional or force sequentially to label-specific goroutine begKey := NewLabelSizeTKey(delta.Label, 0) endKey := NewLabelSizeTKey(delta.Label, math.MaxUint64) keys, err := store.KeysInRange(ctx, begKey, endKey) if err != nil { dvid.Errorf("Unable to get size keys for label %d: %v\n", delta.Label, err) continue } if len(keys) != 1 { dvid.Errorf("Cannot modify size of label %d when no prior size recorded!", delta.Label) continue } // Modify label size label, oldSize, err := DecodeLabelSizeTKey(keys[0]) if label != delta.Label { dvid.Errorf("Requested size of label %d and got key for label %d!\n", delta.Label, label) continue } batch := batcher.NewBatch(ctx) oldKey := NewSizeLabelTKey(oldSize, delta.Label) batch.Delete(oldKey) oldKey = NewLabelSizeTKey(delta.Label, oldSize) batch.Delete(oldKey) if err := batch.Commit(); err != nil { dvid.Errorf("Error on updating label sizes on %s: %v\n", ctx, err) } } case labels.DeltaModSize: // TODO -- Make transactional or force sequentially to label-specific goroutine // Get old label size begKey := NewLabelSizeTKey(delta.Label, 0) endKey := NewLabelSizeTKey(delta.Label, math.MaxUint64) keys, err := store.KeysInRange(ctx, begKey, endKey) if err != nil { dvid.Errorf("Unable to get size keys for label %d: %v\n", delta.Label, err) continue } if len(keys) != 1 { dvid.Errorf("Cannot modify size of label %d when no prior size recorded!", delta.Label) continue } // Modify label size label, oldSize, err := DecodeLabelSizeTKey(keys[0]) if label != delta.Label { dvid.Errorf("Requested size of label %d and got key for label %d!\n", delta.Label, label) continue } // Assumes 63 bits is sufficient for any label size := int64(oldSize) size += delta.SizeChange newSize := uint64(size) // Delete old label size keys batch := batcher.NewBatch(ctx) oldKey := NewSizeLabelTKey(oldSize, label) batch.Delete(oldKey) oldKey = NewLabelSizeTKey(label, oldSize) batch.Delete(oldKey) // Add new one newKey := NewSizeLabelTKey(newSize, label) batch.Put(newKey, dvid.EmptyValue()) newKey = NewLabelSizeTKey(label, newSize) batch.Put(newKey, dvid.EmptyValue()) if err := batch.Commit(); err != nil { dvid.Errorf("Error on updating label sizes on %s: %v\n", ctx, err) } case labels.DeltaReplaceSize: batch := batcher.NewBatch(ctx) oldKey := NewSizeLabelTKey(delta.OldSize, delta.Label) batch.Delete(oldKey) oldKey = NewLabelSizeTKey(delta.Label, delta.OldSize) batch.Delete(oldKey) newKey := NewSizeLabelTKey(delta.NewSize, delta.Label) batch.Put(newKey, dvid.EmptyValue()) newKey = NewLabelSizeTKey(delta.Label, delta.NewSize) batch.Put(newKey, dvid.EmptyValue()) if err := batch.Commit(); err != nil { dvid.Errorf("Error on updating label sizes on %s: %v\n", ctx, err) } default: dvid.Criticalf("Cannot sync labelsz using unexpected delta: %v", msg) } } } }
// PutSpans saves a slice of spans representing an ROI into the datastore. // If the init parameter is true, all previous spans of this ROI are deleted before // writing these spans. func (d *Data) PutSpans(versionID dvid.VersionID, spans []dvid.Span, init bool) error { ctx := datastore.NewVersionedCtx(d, versionID) db, err := storage.SmallDataStore() if err != nil { return err } // Delete the old key/values if init { if err := d.Delete(ctx); err != nil { return err } } // Make sure our small data store can do batching. batcher, ok := db.(storage.KeyValueBatcher) if !ok { return fmt.Errorf("Unable to store ROI: small data store can't do batching!") } // We only want one PUT on given version for given data to prevent interleaved PUTs. putMutex := ctx.Mutex() putMutex.Lock() // Save new extents after finished. defer func() { err := datastore.SaveDataByVersion(ctx.VersionID(), d) if err != nil { dvid.Errorf("Error in trying to save repo on roi extent change: %v\n", err) } putMutex.Unlock() }() // Put the new key/values const BATCH_SIZE = 10000 batch := batcher.NewBatch(ctx) for i, span := range spans { if span[0] < d.MinZ { d.MinZ = span[0] } if span[0] > d.MaxZ { d.MaxZ = span[0] } if span[3] < span[2] { return fmt.Errorf("Got weird span %v. span[3] (X1) < span[2] (X0)", span) } index := indexRLE{ start: dvid.IndexZYX{span[2], span[1], span[0]}, span: uint32(span[3] - span[2] + 1), } tk := storage.NewTKey(keyROI, index.Bytes()) batch.Put(tk, dvid.EmptyValue()) if (i+1)%BATCH_SIZE == 0 { if err := batch.Commit(); err != nil { return fmt.Errorf("Error on batch PUT at span %d: %v\n", i, err) } batch = batcher.NewBatch(ctx) } } if len(spans)%BATCH_SIZE != 0 { if err := batch.Commit(); err != nil { return fmt.Errorf("Error on last batch PUT: %v\n", err) } } return nil }