func (d *Data) DeleteElement(ctx *datastore.VersionedCtx, pt dvid.Point3d) error { // Get from block key blockSize := d.blockSize() blockCoord := pt.Chunk(blockSize).(dvid.ChunkPoint3d) tk := NewBlockTKey(blockCoord) d.Lock() defer d.Unlock() elems, err := getElements(ctx, tk) if err != nil { return err } // Delete the given element deleted, _ := elems.delete(pt) if deleted == nil { return fmt.Errorf("Did not find element %s in datastore", pt) } // Put block key version without given element if err := putElements(ctx, tk, elems); err != nil { return err } // Alter all stored versions of this annotation using a batch. store, err := d.BackendStore() if err != nil { return err } batcher, ok := store.(storage.KeyValueBatcher) if !ok { return fmt.Errorf("Data type annotation requires batch-enabled store, which %q is not\n", store) } batch := batcher.NewBatch(ctx) // Delete in label key if err := d.deleteElementInLabel(ctx, batch, deleted.Pos); err != nil { return err } // Delete element in any tags if err := d.deleteElementInTags(ctx, batch, deleted.Pos, deleted.Tags); err != nil { return err } // Modify any reference in relationships if err := d.deleteElementInRelationships(ctx, batch, deleted.Pos, deleted.Rels); err != nil { return err } return batch.Commit() }
// move all reference to given element point in the related points in different blocks. // This is private method and assumes outer locking as well as current "from" block already being modified, // including relationships. func (d *Data) moveElementInRelationships(ctx *datastore.VersionedCtx, batch storage.Batch, from, to dvid.Point3d, rels []Relationship) error { blockSize := d.blockSize() fromBlockCoord := from.Chunk(blockSize).(dvid.ChunkPoint3d) // Get list of blocks with related points. relBlocks := make(map[dvid.IZYXString]struct{}) for _, rel := range rels { blockCoord := rel.To.Chunk(blockSize).(dvid.ChunkPoint3d) if blockCoord.Equals(fromBlockCoord) { continue // relationships are almoved in from block } relBlocks[blockCoord.ToIZYXString()] = struct{}{} } // Alter the moved points in those related blocks. for izyxstr := range relBlocks { blockCoord, err := izyxstr.ToChunkPoint3d() if err != nil { return err } tk := NewBlockTKey(blockCoord) elems, err := getElements(ctx, tk) if err != nil { return err } // Move element in related element. if _, changed := elems.move(from, to, false); !changed { dvid.Errorf("Unable to find moved element %s in related element @ block %s:\n%v\n", from, blockCoord, elems) continue } // Save the block elements. if err := putBatchElements(batch, tk, elems); err != nil { return err } } return nil }
func (d *Data) MoveElement(ctx *datastore.VersionedCtx, from, to dvid.Point3d) error { // Calc block keys blockSize := d.blockSize() fromCoord := from.Chunk(blockSize).(dvid.ChunkPoint3d) fromTk := NewBlockTKey(fromCoord) toCoord := to.Chunk(blockSize).(dvid.ChunkPoint3d) toTk := NewBlockTKey(toCoord) d.Lock() defer d.Unlock() // Alter all stored versions of this annotation using a batch. store, err := d.BackendStore() if err != nil { return err } batcher, ok := store.(storage.KeyValueBatcher) if !ok { return fmt.Errorf("Data type annotation requires batch-enabled store, which %q is not\n", store) } batch := batcher.NewBatch(ctx) // Handle from block fromElems, err := getElements(ctx, fromTk) if err != nil { return err } deleteElement := (bytes.Compare(fromTk, toTk) != 0) moved, _ := fromElems.move(from, to, deleteElement) if moved == nil { return fmt.Errorf("Did not find moved element %s in datastore", from) } dvid.Infof("moved element %v from %s -> %s\n", *moved, fromCoord, toCoord) if err := putBatchElements(batch, fromTk, fromElems); err != nil { return err } // If we've moved blocks, add the element in new place. if deleteElement { toElems, err := getElements(ctx, toTk) if err != nil { return err } toElems.add(Elements{*moved}) dvid.Infof("new %s value: %v\n", toCoord, toElems) if err := putBatchElements(batch, toTk, toElems); err != nil { return err } } if err := batch.Commit(); err != nil { return err } batch = batcher.NewBatch(ctx) // Move in label key if err := d.moveElementInLabels(ctx, batch, from, to, moved.ElementNR); err != nil { return err } // Move element in any tags if err := d.moveElementInTags(ctx, batch, from, to, moved.Tags); err != nil { return err } // Move any reference in relationships if err := d.moveElementInRelationships(ctx, batch, from, to, moved.Rels); err != nil { return err } return batch.Commit() }