func DecodeBlockTKey(tk storage.TKey) (pt dvid.ChunkPoint3d, err error) { ibytes, err := tk.ClassBytes(keyBlock) if err != nil { return } var idx dvid.IndexZYX if err = idx.IndexFromBytes(ibytes); err != nil { return } pt = dvid.ChunkPoint3d(idx) return }
// DecodeTKey returns the components of a tile request based on an imagetile-specific key component. func DecodeTKey(tk storage.TKey) (tile dvid.ChunkPoint3d, plane dvid.DataShape, scale Scaling, err error) { if len(tk) < 21 { err = fmt.Errorf("imagetile-specific key component has too few bytes (%d)", len(tk)) return } plane, err = dvid.BytesToDataShape(tk[0:dvid.DataShapeBytes]) if err != nil { return } scale = Scaling(tk[dvid.DataShapeBytes]) var idx dvid.IndexZYX if err = idx.IndexFromBytes(tk[dvid.DataShapeBytes+2:]); err != nil { return } tile = dvid.ChunkPoint3d(idx) return }
// If a block of labels is deleted, the associated synapse elements should be changed to zero label elements. func (d *Data) deleteBlock(ctx *datastore.VersionedCtx, block labels.DeleteBlock, batcher storage.KeyValueBatcher) { // Get the synaptic elements for this block chunkPt := dvid.ChunkPoint3d(*block.Index) tk := NewBlockTKey(chunkPt) elems, err := getElements(ctx, tk) if err != nil { dvid.Errorf("err getting elements for block %s: %v\n", chunkPt, err) return } if len(elems) == 0 { return } blockSize := d.blockSize() batch := batcher.NewBatch(ctx) // Compute the strides (in bytes) bX := blockSize[0] * 8 bY := blockSize[1] * bX // Iterate through all element positions, finding corresponding label and storing elements. toDel := LabelPoints{} for _, elem := range elems { pt := elem.Pos.Point3dInChunk(blockSize) i := pt[2]*bY + pt[1]*bX + pt[0]*8 label := binary.LittleEndian.Uint64(block.Data[i : i+8]) toDel.add(label, elem.Pos) } // Delete any non-zero label elements from their respective label k/v. var delta DeltaModifyElements for label, pts := range toDel { tk := NewLabelTKey(label) elems, err := getElements(ctx, tk) if err != nil { dvid.Errorf("err getting elements for label %d: %v\n", label, err) return } save := false for _, pt := range pts { deleted, changed := elems.delete(pt) if changed { save = true delta.Del = append(delta.Del, ElementPos{Label: label, Kind: deleted.Kind, Pos: pt}) } } if save { if len(elems) == 0 { batch.Delete(tk) } else { val, err := json.Marshal(elems) if err != nil { dvid.Errorf("couldn't serialize annotation elements in instance %q: %v\n", d.DataName(), err) return } batch.Put(tk, val) } } } if err := batch.Commit(); err != nil { dvid.Criticalf("bad commit in annotations %q after delete block: %v\n", d.DataName(), err) return } // Notify any subscribers of label annotation changes. evt := datastore.SyncEvent{Data: d.DataUUID(), Event: ModifyElementsEvent} msg := datastore.SyncMessage{Event: ModifyElementsEvent, Version: ctx.VersionID(), Delta: delta} if err := datastore.NotifySubscribers(evt, msg); err != nil { dvid.Criticalf("unable to notify subscribers of event %s: %v\n", evt, err) } }
// If a block of labels is mutated, adjust any label that was either removed or added. func (d *Data) mutateBlock(ctx *datastore.VersionedCtx, block imageblk.MutatedBlock, batcher storage.KeyValueBatcher) { // Get the synaptic elements for this block chunkPt := dvid.ChunkPoint3d(*block.Index) tk := NewBlockTKey(chunkPt) elems, err := getElementsNR(ctx, tk) if err != nil { dvid.Errorf("err getting elements for block %s: %v\n", chunkPt, err) return } if len(elems) == 0 { return } blockSize := d.blockSize() batch := batcher.NewBatch(ctx) // Compute the strides (in bytes) bX := blockSize[0] * 8 bY := blockSize[1] * bX // Iterate through all element positions, finding corresponding label and storing elements. var delta DeltaModifyElements labels := make(map[uint64]struct{}) toAdd := LabelElements{} toDel := LabelPoints{} for _, elem := range elems { pt := elem.Pos.Point3dInChunk(blockSize) i := pt[2]*bY + pt[1]*bX + pt[0]*8 label := binary.LittleEndian.Uint64(block.Data[i : i+8]) var prev uint64 if len(block.Prev) != 0 { prev = binary.LittleEndian.Uint64(block.Prev[i : i+8]) } if label == prev { continue } if label != 0 { toAdd.add(label, elem) labels[label] = struct{}{} delta.Add = append(delta.Add, ElementPos{Label: label, Kind: elem.Kind, Pos: elem.Pos}) } if prev != 0 { toDel.add(prev, elem.Pos) labels[prev] = struct{}{} delta.Del = append(delta.Del, ElementPos{Label: prev, Kind: elem.Kind, Pos: elem.Pos}) } } // Modify any modified label k/v. for label := range labels { tk := NewLabelTKey(label) elems, err := getElementsNR(ctx, tk) if err != nil { dvid.Errorf("err getting elements for label %d: %v\n", label, err) return } additions, found := toAdd[label] if found { elems.add(additions) } deletions, found := toDel[label] if found { for _, pt := range deletions { elems.delete(pt) } } val, err := json.Marshal(elems) if err != nil { dvid.Errorf("couldn't serialize annotation elements in instance %q: %v\n", d.DataName(), err) return } batch.Put(tk, val) } if err := batch.Commit(); err != nil { dvid.Criticalf("bad commit in annotations %q after delete block: %v\n", d.DataName(), err) return } // Notify any subscribers of label annotation changes. evt := datastore.SyncEvent{Data: d.DataUUID(), Event: ModifyElementsEvent} msg := datastore.SyncMessage{Event: ModifyElementsEvent, Version: ctx.VersionID(), Delta: delta} if err := datastore.NotifySubscribers(evt, msg); err != nil { dvid.Criticalf("unable to notify subscribers of event %s: %v\n", evt, err) } }
// If a block of labels is ingested, adjust each label's synaptic element list. func (d *Data) ingestBlock(ctx *datastore.VersionedCtx, block imageblk.Block, batcher storage.KeyValueBatcher) { // Get the synaptic elements for this block chunkPt := dvid.ChunkPoint3d(*block.Index) tk := NewBlockTKey(chunkPt) elems, err := getElementsNR(ctx, tk) if err != nil { dvid.Errorf("err getting elements for block %s: %v\n", chunkPt, err) return } if len(elems) == 0 { return } blockSize := d.blockSize() batch := batcher.NewBatch(ctx) // Compute the strides (in bytes) bX := blockSize[0] * 8 bY := blockSize[1] * bX // Iterate through all element positions, finding corresponding label and storing elements. added := 0 toAdd := LabelElements{} for _, elem := range elems { pt := elem.Pos.Point3dInChunk(blockSize) i := (pt[2]*bY+pt[1])*bX + pt[0]*8 label := binary.LittleEndian.Uint64(block.Data[i : i+8]) if label != 0 { toAdd.add(label, elem) added++ } } // Add any non-zero label elements to their respective label k/v. var delta DeltaModifyElements delta.Add = make([]ElementPos, added) i := 0 for label, addElems := range toAdd { tk := NewLabelTKey(label) elems, err := getElementsNR(ctx, tk) if err != nil { dvid.Errorf("err getting elements for label %d: %v\n", label, err) return } elems.add(addElems) val, err := json.Marshal(elems) if err != nil { dvid.Errorf("couldn't serialize annotation elements in instance %q: %v\n", d.DataName(), err) return } batch.Put(tk, val) for _, addElem := range addElems { delta.Add[i] = ElementPos{Label: label, Kind: addElem.Kind, Pos: addElem.Pos} i++ } } if err := batch.Commit(); err != nil { dvid.Criticalf("bad commit in annotations %q after delete block: %v\n", d.DataName(), err) return } // Notify any subscribers of label annotation changes. evt := datastore.SyncEvent{Data: d.DataUUID(), Event: ModifyElementsEvent} msg := datastore.SyncMessage{Event: ModifyElementsEvent, Version: ctx.VersionID(), Delta: delta} if err := datastore.NotifySubscribers(evt, msg); err != nil { dvid.Criticalf("unable to notify subscribers of event %s: %v\n", evt, err) } }