// makes sure that no relationships are returned since they could be out of date.
func getElementsNR(ctx *datastore.VersionedCtx, tk storage.TKey) (ElementsNR, error) {
store, err := ctx.GetOrderedKeyValueDB()
if err != nil {
return nil, err
}
val, err := store.Get(ctx, tk)
if err != nil {
return nil, err
}
if val == nil {
return nil, nil
}
var elems ElementsNR
if err := json.Unmarshal(val, &elems); err != nil {
return nil, err
}
return elems, nil
}
func (d *Data) mutateBlock(ctx *datastore.VersionedCtx, block imageblk.MutatedBlock, batcher storage.KeyValueBatcher) {
// Iterate through previous and current labels, detecting set of previous labels and RLEs for current labels.
blockBytes := len(block.Data)
if blockBytes != int(d.BlockSize.Prod())*8 {
dvid.Criticalf("Deserialized label block %d bytes, not uint64 size times %d block elements\n",
blockBytes, d.BlockSize.Prod())
return
}
labelRLEs := make(map[uint64]dvid.RLEs, 10)
labelDiff := make(map[uint64]bool, 10)
firstPt := block.Index.MinPoint(d.BlockSize)
lastPt := block.Index.MaxPoint(d.BlockSize)
var curStart dvid.Point3d
var voxelLabel, curLabel, maxLabel uint64
var z, y, x, curRun int32
start := 0
for z = firstPt.Value(2); z <= lastPt.Value(2); z++ {
for y = firstPt.Value(1); y <= lastPt.Value(1); y++ {
for x = firstPt.Value(0); x <= lastPt.Value(0); x++ {
var pastLabel uint64
if block.Prev == nil || len(block.Prev) == 0 {
pastLabel = 0
} else {
pastLabel = binary.LittleEndian.Uint64(block.Prev[start : start+8])
}
voxelLabel = binary.LittleEndian.Uint64(block.Data[start : start+8])
if maxLabel < voxelLabel {
maxLabel = voxelLabel
}
if pastLabel != 0 {
if pastLabel != voxelLabel {
labelDiff[pastLabel] = true
} else {
_, found := labelDiff[pastLabel]
if !found {
labelDiff[pastLabel] = false
}
}
}
start += 8
// If we hit background or have switched label, save old run and start new one.
if voxelLabel == 0 || voxelLabel != curLabel {
// Save old run
if curRun > 0 {
labelRLEs[curLabel] = append(labelRLEs[curLabel], dvid.NewRLE(curStart, curRun))
}
// Start new one if not zero label.
if voxelLabel != 0 {
curStart = dvid.Point3d{x, y, z}
curRun = 1
} else {
curRun = 0
}
curLabel = voxelLabel
} else {
curRun++
}
}
// Force break of any runs when we finish x scan.
if curRun > 0 {
labelRLEs[curLabel] = append(labelRLEs[curLabel], dvid.NewRLE(curStart, curRun))
curLabel = 0
curRun = 0
}
}
}
// If a previous label has no change with current label RLE, then delete the label RLE since no changes
// are necessary. Else if previous label is not present in current label RLEs, delete labelvol.
var deletes []storage.TKey
blockStr := block.Index.ToIZYXString()
for label, diff := range labelDiff {
_, found := labelRLEs[label]
if diff && !found {
// mark previous label's RLEs for deletion
tk := NewTKey(label, blockStr)
deletes = append(deletes, tk)
} else if !diff && found {
// delete current label's RLEs because there's no difference with past RLE
delete(labelRLEs, label)
}
}
if len(deletes) > 0 {
batch := batcher.NewBatch(ctx)
for _, tk := range deletes {
batch.Delete(tk)
}
if err := batch.Commit(); err != nil {
dvid.Errorf("batch commit on deleting previous labels' labelvols: %v\n", err)
}
}
// Store the RLEs for each label in this block that are new or modified.
if len(labelRLEs) > 0 {
batch := batcher.NewBatch(ctx)
for label, rles := range labelRLEs {
tk := NewTKey(label, blockStr)
//.........这里部分代码省略.........
开发者ID:tartavull,项目名称:dvid,代码行数:101,代码来源:sync.go
示例11: deleteBlock
// 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)
}
}
开发者ID:tartavull,项目名称:dvid,代码行数:72,代码来源:sync.go
示例12: ingestBlock
// Note that this does not delete any removed labels in the block since we only get the CURRENT block
// and not PAST blocks. To allow mutation of label blocks, not just ingestion, we need another function.
func (d *Data) ingestBlock(ctx *datastore.VersionedCtx, block imageblk.Block, batcher storage.KeyValueBatcher) {
// Iterate through this block of labels and create RLEs for each label.
blockBytes := len(block.Data)
if blockBytes != int(d.BlockSize.Prod())*8 {
dvid.Criticalf("Deserialized label block %d bytes, not uint64 size times %d block elements\n",
blockBytes, d.BlockSize.Prod())
return
}
labelRLEs := make(map[uint64]dvid.RLEs, 10)
firstPt := block.Index.MinPoint(d.BlockSize)
lastPt := block.Index.MaxPoint(d.BlockSize)
var curStart dvid.Point3d
var voxelLabel, curLabel, maxLabel uint64
var z, y, x, curRun int32
start := 0
for z = firstPt.Value(2); z <= lastPt.Value(2); z++ {
for y = firstPt.Value(1); y <= lastPt.Value(1); y++ {
for x = firstPt.Value(0); x <= lastPt.Value(0); x++ {
voxelLabel = binary.LittleEndian.Uint64(block.Data[start : start+8])
if maxLabel < voxelLabel {
maxLabel = voxelLabel
}
start += 8
// If we hit background or have switched label, save old run and start new one.
if voxelLabel == 0 || voxelLabel != curLabel {
// Save old run
if curRun > 0 {
labelRLEs[curLabel] = append(labelRLEs[curLabel], dvid.NewRLE(curStart, curRun))
}
// Start new one if not zero label.
if voxelLabel != 0 {
curStart = dvid.Point3d{x, y, z}
curRun = 1
} else {
curRun = 0
}
curLabel = voxelLabel
} else {
curRun++
}
}
// Force break of any runs when we finish x scan.
if curRun > 0 {
labelRLEs[curLabel] = append(labelRLEs[curLabel], dvid.NewRLE(curStart, curRun))
curLabel = 0
curRun = 0
}
}
}
// Store the RLEs for each label in this block.
if maxLabel > 0 {
batch := batcher.NewBatch(ctx)
blockStr := block.Index.ToIZYXString()
for label, rles := range labelRLEs {
tk := NewTKey(label, blockStr)
rleBytes, err := rles.MarshalBinary()
if err != nil {
dvid.Errorf("Bad encoding labelvol keys for label %d: %v\n", label, err)
return
}
batch.Put(tk, rleBytes)
}
// compare-and-set MaxLabel and batch commit
d.casMaxLabel(batch, ctx.VersionID(), maxLabel)
}
}
开发者ID:jwohlwend,项目名称:dvid,代码行数:72,代码来源:sync.go
示例13: ServeHTTP
// ServeHTTP handles all incoming HTTP requests for this data.
func (d *Data) ServeHTTP(uuid dvid.UUID, ctx *datastore.VersionedCtx, w http.ResponseWriter, r *http.Request) {
timedLog := dvid.NewTimeLog()
// Get the action (GET, POST)
action := strings.ToLower(r.Method)
switch action {
case "get":
case "post":
default:
server.BadRequest(w, r, "Can only handle GET or POST HTTP verbs")
return
}
// Break URL request into arguments
url := r.URL.Path[len(server.WebAPIPath):]
parts := strings.Split(url, "/")
if len(parts[len(parts)-1]) == 0 {
parts = parts[:len(parts)-1]
}
// Get query strings and possible roi
var roiptr *ROI
queryValues := r.URL.Query()
roiname := dvid.InstanceName(queryValues.Get("roi"))
if len(roiname) != 0 {
roiptr = new(ROI)
attenuationStr := queryValues.Get("attenuation")
if len(attenuationStr) != 0 {
attenuation, err := strconv.Atoi(attenuationStr)
if err != nil {
server.BadRequest(w, r, err)
return
}
if attenuation < 1 || attenuation > 7 {
server.BadRequest(w, r, "Attenuation should be from 1 to 7 (divides by 2^n)")
return
}
roiptr.attenuation = uint8(attenuation)
}
}
// Handle POST on data -> setting of configuration
if len(parts) == 3 && action == "put" {
fmt.Printf("Setting configuration of data '%s'\n", d.DataName())
config, err := server.DecodeJSON(r)
if err != nil {
server.BadRequest(w, r, err)
return
}
if err := d.ModifyConfig(config); err != nil {
server.BadRequest(w, r, err)
return
}
if err := datastore.SaveDataByUUID(uuid, d); err != nil {
server.BadRequest(w, r, err)
return
}
fmt.Fprintf(w, "Changed '%s' based on received configuration:\n%s\n", d.DataName(), config)
return
}
if len(parts) < 4 {
server.BadRequest(w, r, "Incomplete API request")
return
}
// Process help and info.
switch parts[3] {
case "help":
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintln(w, d.Help())
return
case "metadata":
jsonStr, err := d.NdDataMetadata()
if err != nil {
server.BadRequest(w, r, err)
return
}
w.Header().Set("Content-Type", "application/vnd.dvid-nd-data+json")
fmt.Fprintln(w, jsonStr)
return
case "info":
jsonBytes, err := d.MarshalJSON()
if err != nil {
server.BadRequest(w, r, err)
return
}
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, string(jsonBytes))
return
case "rawkey":
// GET <api URL>/node/<UUID>/<data name>/rawkey?x=<block x>&y=<block y>&z=<block z>
if len(parts) != 4 {
server.BadRequest(w, r, "rawkey endpoint should be followed by query strings (x, y, and z) giving block coord")
return
}
//.........这里部分代码省略.........
请发表评论