github.com/janelia-flyem/dvid@v1.0.0/datatype/labelmap/labelidx.go (about) 1 package labelmap 2 3 import ( 4 "bytes" 5 "compress/gzip" 6 "encoding/binary" 7 "encoding/json" 8 "fmt" 9 "io" 10 "math" 11 "net/http" 12 "os" 13 "sort" 14 "sync" 15 "sync/atomic" 16 17 pb "google.golang.org/protobuf/proto" 18 19 "github.com/coocood/freecache" 20 "github.com/janelia-flyem/dvid/datastore" 21 "github.com/janelia-flyem/dvid/datatype/common/labels" 22 "github.com/janelia-flyem/dvid/datatype/common/proto" 23 "github.com/janelia-flyem/dvid/dvid" 24 "github.com/janelia-flyem/dvid/server" 25 "github.com/janelia-flyem/dvid/storage" 26 lz4 "github.com/janelia-flyem/go/golz4-updated" 27 ) 28 29 const ( 30 numIndexShards = 64 31 ) 32 33 var ( 34 indexCache *freecache.Cache 35 indexMu [numIndexShards]sync.RWMutex 36 metaAttempts uint64 37 metaHits uint64 38 39 mutcache map[dvid.UUID]storage.OrderedKeyValueDB 40 ) 41 42 // Initialize establishes the in-memory labelmap and other supporting 43 // data systems if specified in the server configuration: 44 // - index caching if cache size is specified in the server config. 45 // - mutation cache for label indices if specified in server config. 46 func (d *Data) Initialize() { 47 numBytes := server.CacheSize("labelmap") 48 if indexCache == nil { 49 if numBytes > 0 { 50 indexCache = freecache.NewCache(numBytes) 51 mbs := numBytes >> 20 52 dvid.Infof("Created freecache of ~ %d MB for labelmap instances.\n", mbs) 53 } 54 } else if numBytes == 0 { 55 indexCache = nil 56 } else { 57 indexCache.Clear() 58 } 59 60 mutcachePath := server.MutcachePath(d.DataName()) 61 if mutcachePath != "" { 62 // Setup database support for mutation cache for this instance 63 engine := storage.GetEngine("badger") 64 var cfg dvid.Config 65 cfg.Set("path", mutcachePath) 66 store, _, err := engine.NewStore(dvid.StoreConfig{Config: cfg, Engine: "badger"}) 67 if err != nil { 68 dvid.Criticalf("can't initialize Badger: %v\n", err) 69 } else { 70 okvDB, ok := store.(storage.OrderedKeyValueDB) 71 if !ok { 72 dvid.Criticalf("can't get proper ordered keyvalue DB for mutation cache %q for data %q\n", mutcachePath, d.DataName()) 73 } else { 74 if mutcache == nil { 75 mutcache = make(map[dvid.UUID]storage.OrderedKeyValueDB) 76 } 77 mutcache[d.DataUUID()] = okvDB 78 } 79 } 80 } 81 82 ancestry, err := datastore.GetBranchVersions(d.RootUUID(), "") 83 if err != nil { 84 dvid.Criticalf("Unable to get ancestry of master branch: %v\n", err) 85 return 86 } 87 if len(ancestry) == 0 { 88 dvid.Infof("No versions in master branch -- not loading labelmap %q\n", d.DataName()) 89 return 90 } 91 masterLeafV, err := datastore.VersionFromUUID(ancestry[0]) 92 if err != nil { 93 dvid.Criticalf("Unable to get version ID from master leaf UUID %s: %v\n", ancestry[0], err) 94 } 95 if _, err := getMapping(d, masterLeafV); err != nil { 96 dvid.Criticalf("Unable to initialize in-memory labelmap for data %q: %v\n", d.DataName(), err) 97 } 98 } 99 100 func (d *Data) getMutcache(v dvid.VersionID, mutID uint64, label uint64) (*labels.Index, error) { 101 if mutcache == nil { 102 return nil, nil 103 } 104 db, found := mutcache[d.DataUUID()] 105 if !found { 106 return nil, nil 107 } 108 ctx := datastore.NewVersionedCtx(d, v) 109 tkey1 := newMutcacheKey(label, mutID) 110 tkey2 := newMutcacheKey(label, 0) 111 var idx *labels.Index 112 db.ProcessRange(ctx, tkey1, tkey2, nil, func(chunk *storage.Chunk) error { 113 label, curMutID, err := decodeMutcacheKey(chunk.K) 114 if err != nil { 115 return err 116 } 117 idx = new(labels.Index) 118 if err := pb.Unmarshal(chunk.V, idx); err != nil { 119 return err 120 } 121 dvid.Infof("Mutcache label %d mutid %d > %d\n", label, mutID, curMutID) 122 return fmt.Errorf("found mutcache") 123 }) 124 return idx, nil 125 } 126 127 func (d *Data) addMutcache(v dvid.VersionID, mutID uint64, indices ...*labels.Index) error { 128 if mutcache == nil { 129 return nil 130 } 131 db, found := mutcache[d.DataUUID()] 132 if !found { 133 return nil 134 } 135 ctx := datastore.NewVersionedCtx(d, v) 136 for _, idx := range indices { 137 tkey := newMutcacheKey(idx.Label, mutID) 138 idxBytes, err := pb.Marshal(idx) 139 if err != nil { 140 return fmt.Errorf("unable to marshal index for label %d before caching: %v", idx.Label, err) 141 } 142 if err := db.Put(ctx, tkey, idxBytes); err != nil { 143 return err 144 } 145 } 146 return nil 147 } 148 149 // indexKey is a three tuple (instance id, version, label) 150 type indexKey struct { 151 data dvid.Data 152 version dvid.VersionID 153 label uint64 154 } 155 156 func (k indexKey) Bytes() []byte { 157 b := make([]byte, 16) 158 copy(b[0:4], k.data.InstanceID().Bytes()) 159 copy(b[4:8], k.version.Bytes()) 160 binary.LittleEndian.PutUint64(b[8:16], k.label) 161 return b 162 } 163 164 func (k indexKey) VersionedCtx() *datastore.VersionedCtx { 165 return datastore.NewVersionedCtx(k.data, k.version) 166 } 167 168 // TODO -- allow check of the cache as well. 169 func (d *Data) labelIndexExists(v dvid.VersionID, label uint64) (bool, error) { 170 ctx := datastore.NewVersionedCtx(d, v) 171 store, err := datastore.GetKeyValueDB(d) 172 if err != nil { 173 return false, err 174 } 175 return store.Exists(ctx, NewLabelIndexTKey(label)) 176 } 177 178 // returns nil if no Meta is found. 179 // should only call getCachedLabelIndex external to this file. 180 func getLabelIndex(ctx *datastore.VersionedCtx, label uint64) (*labels.Index, error) { 181 // timedLog := dvid.NewTimeLog() 182 store, err := datastore.GetKeyValueDB(ctx.Data()) 183 if err != nil { 184 return nil, err 185 } 186 compressed, err := store.Get(ctx, NewLabelIndexTKey(label)) 187 if err != nil { 188 return nil, err 189 } 190 if len(compressed) == 0 { 191 // timedLog.Infof("retrieved empty index for label %d", label) 192 return nil, nil 193 } 194 val, _, err := dvid.DeserializeData(compressed, true) 195 if err != nil { 196 return nil, err 197 } 198 199 idx := new(labels.Index) 200 if err := pb.Unmarshal(val, idx); err != nil { 201 return nil, err 202 } 203 if idx.Label == 0 { 204 idx.Label = label 205 } 206 // timedLog.Infof("retrieved label %d index with %d blocks", label, len(idx.Blocks)) 207 return idx, nil 208 } 209 210 func getLabelIndexCompressed(store storage.KeyValueGetter, ctx *datastore.VersionedCtx, label uint64) ([]byte, error) { 211 compressed, err := store.Get(ctx, NewLabelIndexTKey(label)) 212 if err != nil { 213 return nil, err 214 } 215 if len(compressed) == 0 { 216 // timedLog.Infof("retrieved empty index for label %d", label) 217 return nil, nil 218 } 219 return compressed, nil 220 } 221 222 func getProtoLabelIndices(ctx *datastore.VersionedCtx, dataIn []byte) (numLabels int, dataOut []byte, err error) { 223 var labelList []uint64 224 if err = json.Unmarshal(dataIn, &labelList); err != nil { 225 err = fmt.Errorf("expected JSON label list: %v", err) 226 return 227 } 228 numLabels = len(labelList) 229 if numLabels > 50000 { 230 err = fmt.Errorf("only 50,000 label indices can be returned at a time, %d given", len(labelList)) 231 return 232 } 233 var indices proto.LabelIndices 234 indices.Indices = make([]*proto.LabelIndex, len(labelList)) 235 for i, label := range labelList { 236 var idx *labels.Index 237 if idx, err = getLabelIndex(ctx, label); err != nil { 238 err = fmt.Errorf("could not get label %d index in position %d: %v", label, i, err) 239 return 240 } 241 if idx != nil { 242 indices.Indices[i] = &(idx.LabelIndex) 243 } else { 244 index := proto.LabelIndex{ 245 Label: label, 246 } 247 indices.Indices[i] = &index 248 } 249 } 250 if dataOut, err = pb.Marshal(&indices); err != nil { 251 err = fmt.Errorf("could not serialize %d label indices: %v", len(labelList), err) 252 } 253 return 254 } 255 256 // batch mode put/delete using protobuf indices without caching 257 func putProtoLabelIndices(ctx *datastore.VersionedCtx, dataIn []byte) (numAdded, numDeleted int, err error) { 258 data := ctx.Data() 259 var store storage.KeyValueDB 260 if store, err = datastore.GetKeyValueDB(data); err != nil { 261 err = fmt.Errorf("data %q had error getting KeyValue store: %v", data.DataName(), err) 262 return 263 } 264 indices := new(proto.LabelIndices) 265 if err = pb.Unmarshal(dataIn, indices); err != nil { 266 return 267 } 268 var maxLabel uint64 269 for i, protoIdx := range indices.Indices { 270 if protoIdx == nil { 271 err = fmt.Errorf("indices included a nil index in position %d", i) 272 return 273 } 274 if protoIdx.Label == 0 { 275 err = fmt.Errorf("index %d had label 0, which is a reserved label", i) 276 return 277 } 278 if len(protoIdx.Blocks) == 0 { 279 if err = deleteLabelIndex(ctx, protoIdx.Label); err != nil { 280 return 281 } 282 numDeleted++ 283 continue 284 } 285 numAdded++ 286 idx := labels.Index{LabelIndex: *protoIdx} 287 if err = putLabelIndex(store, ctx, data, &idx); err != nil { 288 return 289 } 290 if idx.Label > maxLabel { 291 maxLabel = idx.Label 292 } 293 } 294 // handle updating the max label 295 d, ok := data.(*Data) 296 if !ok { 297 err = fmt.Errorf("unable to update max label during PUT label index due to bad data ptr for %q", data.DataName()) 298 return 299 } 300 _, err = d.updateMaxLabel(ctx.VersionID(), maxLabel) 301 return 302 } 303 304 // puts label index and doesn't calc max label 305 // Note: should only call putCachedLabelIndex external to this file so recent changes get cached. 306 func putLabelIndex(store storage.KeyValueDB, ctx *datastore.VersionedCtx, data dvid.Data, idx *labels.Index) error { 307 tk := NewLabelIndexTKey(idx.Label) 308 serialization, err := pb.Marshal(idx) 309 if err != nil { 310 return fmt.Errorf("error trying to serialize index for label set %d, data %q: %v", idx.Label, data.DataName(), err) 311 } 312 compressFormat, _ := dvid.NewCompression(dvid.LZ4, dvid.DefaultCompression) 313 compressed, err := dvid.SerializeData(serialization, compressFormat, dvid.NoChecksum) 314 if err != nil { 315 return fmt.Errorf("error trying to LZ4 compress label %d indexing in data %q", idx.Label, data.DataName()) 316 } 317 if err := store.Put(ctx, tk, compressed); err != nil { 318 return fmt.Errorf("unable to store indices for label %d, data %s: %v", idx.Label, data.DataName(), err) 319 } 320 return err 321 } 322 323 // puts label index and stores max label. 324 // Note: should only call putCachedLabelIndex external to this file so recent changes get cached. 325 func putLabelIndexAndMax(ctx *datastore.VersionedCtx, idx *labels.Index) error { 326 // timedLog := dvid.NewTimeLog() 327 store, err := datastore.GetOrderedKeyValueDB(ctx.Data()) 328 if err != nil { 329 return fmt.Errorf("data %q PutLabelMeta had error initializing store: %v", ctx.Data().DataName(), err) 330 } 331 332 tk := NewLabelIndexTKey(idx.Label) 333 serialization, err := pb.Marshal(idx) 334 if err != nil { 335 return fmt.Errorf("error trying to serialize index for label set %d, data %q: %v", idx.Label, ctx.Data().DataName(), err) 336 } 337 compressFormat, _ := dvid.NewCompression(dvid.LZ4, dvid.DefaultCompression) 338 compressed, err := dvid.SerializeData(serialization, compressFormat, dvid.NoChecksum) 339 if err != nil { 340 return fmt.Errorf("error trying to LZ4 compress label %d indexing in data %q", idx.Label, ctx.Data().DataName()) 341 } 342 if err := store.Put(ctx, tk, compressed); err != nil { 343 return fmt.Errorf("unable to store indices for label %d, data %s: %v", idx.Label, ctx.Data().DataName(), err) 344 } 345 d, ok := ctx.Data().(*Data) 346 if !ok { 347 return fmt.Errorf("Unable to update max label during PUT label index due to bad data ptr") 348 } 349 _, err = d.updateMaxLabel(ctx.VersionID(), idx.Label) 350 351 // timedLog.Infof("stored label %d index with %d blocks", idx.Label, len(idx.Blocks)) 352 return err 353 } 354 355 func deleteLabelIndex(ctx *datastore.VersionedCtx, label uint64) error { 356 store, err := datastore.GetOrderedKeyValueDB(ctx.Data()) 357 if err != nil { 358 return fmt.Errorf("data %q delete label set index had error initializing store: %v", ctx.Data().DataName(), err) 359 } 360 361 tk := NewLabelIndexTKey(label) 362 if err := store.Delete(ctx, tk); err != nil { 363 return fmt.Errorf("unable to delete indices for label %d, data %s: %v", label, ctx.Data().DataName(), err) 364 } 365 return nil 366 } 367 368 // only returns error if we can't get index from storage, not if we can't get it from cache 369 func getCachedLabelIndex(d dvid.Data, v dvid.VersionID, label uint64) (*labels.Index, error) { 370 atomic.AddUint64(&metaAttempts, 1) 371 k := indexKey{data: d, version: v, label: label} 372 373 var err error 374 var idxBytes []byte 375 if indexCache != nil { 376 idxBytes, err = indexCache.Get(k.Bytes()) 377 if err != nil && err != freecache.ErrNotFound { 378 dvid.Errorf("cache get of index for label %d failed due to error: %v\n", label, err) 379 idxBytes = nil 380 } 381 } 382 var idx *labels.Index 383 if idxBytes != nil { 384 idx = new(labels.Index) 385 if err = pb.Unmarshal(idxBytes, idx); err != nil { 386 return nil, err 387 } 388 atomic.AddUint64(&metaHits, 1) 389 return idx, nil 390 } 391 idx, err = getLabelIndex(k.VersionedCtx(), label) 392 if err != nil { 393 return nil, err 394 } 395 if idx == nil { 396 return nil, nil 397 } 398 if indexCache != nil { 399 idxBytes, err := pb.Marshal(idx) 400 if err != nil { 401 dvid.Errorf("unable to marshal label %d index for %q: %v\n", label, d.DataName(), err) 402 } else if err := indexCache.Set(k.Bytes(), idxBytes, 0); err != nil { 403 dvid.Errorf("unable to set label %d index cache for %q: %v\n", label, d.DataName(), err) 404 } 405 } 406 if idx.Label != label { 407 dvid.Criticalf("label index for data %q, label %d has internal label value %d\n", d.DataName(), label, idx.Label) 408 idx.Label = label 409 } 410 return idx, nil 411 } 412 413 // only returns error if we can't persist index, not if we can't cache 414 func putCachedLabelIndex(d dvid.Data, v dvid.VersionID, idx *labels.Index) error { 415 ctx := datastore.NewVersionedCtx(d, v) 416 if err := putLabelIndexAndMax(ctx, idx); err != nil { 417 return err 418 } 419 if indexCache != nil { 420 idxBytes, err := pb.Marshal(idx) 421 if err != nil { 422 dvid.Errorf("unable to marshal index for label %d before caching: %v\n", idx.Label, err) 423 return nil 424 } 425 k := indexKey{data: d, version: v, label: idx.Label}.Bytes() 426 if err = indexCache.Set(k, idxBytes, 0); err != nil { 427 dvid.Errorf("unable to cache index for label %d: %v\n", idx.Label, err) 428 } 429 } 430 return nil 431 } 432 433 func deleteCachedLabelIndex(d dvid.Data, v dvid.VersionID, label uint64) error { 434 ctx := datastore.NewVersionedCtx(d, v) 435 if err := deleteLabelIndex(ctx, label); err != nil { 436 return err 437 } 438 if indexCache != nil { 439 k := indexKey{data: d, version: v, label: label}.Bytes() 440 indexCache.Del(k) 441 } 442 return nil 443 } 444 445 //////////////////////// 446 // 447 448 /////////////////////////////////////////////////////////////////////////// 449 // The following public functions are concurrency-safe and support caching. 450 451 // GetSupervoxels returns the set of supervoxel ids that compose the given label. 452 // Used in other datatypes private interfaces (e.g., tarsupervoxels) and generally useful 453 // for other packages. 454 func (d *Data) GetSupervoxels(v dvid.VersionID, label uint64) (labels.Set, error) { 455 idx, err := GetLabelIndex(d, v, label, false) 456 if err != nil { 457 return nil, err 458 } 459 if idx == nil || len(idx.Blocks) == 0 { 460 return nil, err 461 } 462 return idx.GetSupervoxels(), nil 463 } 464 465 // GetLabelIndex gets label set index data from storage for a given data instance and version. 466 // If isSupervoxel is true, the label is interpreted as a supervoxel and the label set index 467 // containing the given supervoxel is returned. Concurrency-safe access and supports caching. 468 // If a label has been mapped to another, a nil Index is returned. 469 func GetLabelIndex(d dvid.Data, v dvid.VersionID, label uint64, isSupervoxel bool) (*labels.Index, error) { 470 if isSupervoxel { 471 mapping, err := getMapping(d, v) 472 if err != nil { 473 return nil, err 474 } 475 if mapping != nil { 476 if mapped, found := mapping.MappedLabel(v, label); found { 477 if mapped == 0 { 478 return nil, fmt.Errorf("cannot get label for supervoxel %d, which has been split and doesn't exist anymore", label) 479 } 480 label = mapped 481 } 482 } 483 } 484 485 shard := label % numIndexShards 486 indexMu[shard].RLock() 487 idx, err := getCachedLabelIndex(d, v, label) 488 indexMu[shard].RUnlock() 489 return idx, err 490 } 491 492 // GetSupervoxelBlocks gets the blocks corresponding to a supervoxel id. 493 func GetSupervoxelBlocks(d dvid.Data, v dvid.VersionID, supervoxel uint64) (dvid.IZYXSlice, error) { 494 idx, err := GetLabelIndex(d, v, supervoxel, true) 495 if err != nil { 496 return nil, err 497 } 498 if idx == nil { 499 return nil, nil 500 } 501 var blocks dvid.IZYXSlice 502 for zyx, svc := range idx.Blocks { 503 if svc != nil && svc.Counts != nil { 504 sz, found := svc.Counts[supervoxel] 505 if found && sz > 0 { 506 blocks = append(blocks, labels.BlockIndexToIZYXString(zyx)) 507 } 508 } 509 } 510 return blocks, nil 511 } 512 513 // GetLabelSize returns the # of voxels in the given label. If isSupervoxel = true, the given 514 // label is interpreted as a supervoxel id and the size is of a supervoxel. If a label doesn't 515 // exist, a zero (not error) is returned. 516 func GetLabelSize(d dvid.Data, v dvid.VersionID, label uint64, isSupervoxel bool) (uint64, error) { 517 idx, err := GetLabelIndex(d, v, label, isSupervoxel) 518 if err != nil { 519 return 0, err 520 } 521 if idx == nil { 522 return 0, nil 523 } 524 if isSupervoxel { 525 return idx.GetSupervoxelCount(label), nil 526 } 527 return idx.NumVoxels(), nil 528 } 529 530 func getSupervoxelSizes(d dvid.Data, v dvid.VersionID, supervoxels []uint64) ([]uint64, error) { 531 svmap, err := getMapping(d, v) 532 if err != nil { 533 return nil, fmt.Errorf("couldn't get mapping for data %q, version %d: %v", d.DataName(), v, err) 534 } 535 labelsets := make(map[uint64][]uint64) // maps labels -> set of supervoxels in it. 536 labels, _, err := svmap.MappedLabels(v, supervoxels) 537 if err != nil { 538 return nil, err 539 } 540 for i, label := range labels { 541 labelsets[label] = append(labelsets[label], supervoxels[i]) 542 } 543 544 sizemap := make(map[uint64]uint64, len(supervoxels)) 545 for label, svlist := range labelsets { 546 idx, err := GetLabelIndex(d, v, label, false) 547 if err != nil { 548 return nil, err 549 } 550 if idx == nil { 551 for _, sv := range svlist { 552 sizemap[sv] = 0 553 } 554 } else { 555 svcounts := idx.GetSupervoxelCounts() 556 for _, sv := range svlist { 557 sizemap[sv] = svcounts[sv] 558 } 559 } 560 } 561 sizes := make([]uint64, len(supervoxels)) 562 for i, sv := range supervoxels { 563 sizes[i] = sizemap[sv] 564 } 565 return sizes, nil 566 } 567 568 // GetLabelSizes returns the # of voxels in the given labels. If isSupervoxel = true, the given 569 // labels are interpreted as supervoxel ids and the sizes are of a supervoxel. If a label doesn't 570 // exist, a zero (not error) is returned. 571 func GetLabelSizes(d dvid.Data, v dvid.VersionID, labels []uint64, isSupervoxel bool) (sizes []uint64, err error) { 572 if isSupervoxel { 573 return getSupervoxelSizes(d, v, labels) 574 } 575 sizes = make([]uint64, len(labels)) 576 for i, label := range labels { 577 idx, err := GetLabelIndex(d, v, label, false) 578 if err != nil { 579 return nil, err 580 } 581 if idx == nil { 582 sizes[i] = 0 583 } else { 584 sizes[i] = idx.NumVoxels() 585 } 586 } 587 return sizes, nil 588 } 589 590 // GetBoundedIndex gets bounded label index data from storage for a given data instance. 591 func GetBoundedIndex(d dvid.Data, v dvid.VersionID, label uint64, bounds dvid.Bounds, isSupervoxel bool) (*labels.Index, error) { 592 idx, err := GetLabelIndex(d, v, label, isSupervoxel) 593 if err != nil { 594 return nil, err 595 } 596 if idx == nil { 597 return nil, nil 598 } 599 if bounds.Block != nil && bounds.Block.IsSet() { 600 if err = idx.FitToBounds(bounds.Block); err != nil { 601 return nil, err 602 } 603 } 604 return idx, nil 605 } 606 607 // DeleteLabelIndex deletes the index for a given label set. 608 func DeleteLabelIndex(d dvid.Data, v dvid.VersionID, label uint64) error { 609 shard := label % numIndexShards 610 indexMu[shard].Lock() 611 err := deleteCachedLabelIndex(d, v, label) 612 indexMu[shard].Unlock() 613 return err 614 } 615 616 // PutLabelIndex persists a label index data for a given data instance and 617 // version. If the given index is nil, the index is deleted. Concurrency-safe 618 // and supports caching. 619 func PutLabelIndex(d dvid.Data, v dvid.VersionID, label uint64, idx *labels.Index) error { 620 if idx == nil { 621 return DeleteLabelIndex(d, v, label) 622 } 623 shard := label % numIndexShards 624 indexMu[shard].Lock() 625 idx.Label = label 626 err := putCachedLabelIndex(d, v, idx) 627 indexMu[shard].Unlock() 628 return err 629 } 630 631 type proximityJSON struct { 632 Block dvid.ChunkPoint3d 633 Distance int 634 } 635 636 // TODO: Flesh out this stub for /proximity endpoint. 637 func (d *Data) getProximity(ctx *datastore.VersionedCtx, idx1, idx2 *labels.Index) (jsonBytes []byte, err error) { 638 // Find all blocks shared by the two indices 639 640 // For each intersecting block, determine distance between labels and add to output. 641 return 642 } 643 644 // CleaveIndex modifies the label index to remove specified supervoxels and create another 645 // label index for this cleaved body. 646 func (d *Data) cleaveIndex(v dvid.VersionID, op labels.CleaveOp, info dvid.ModInfo) (cleavedSize, remainSize uint64, err error) { 647 shard := op.Target % numIndexShards 648 indexMu[shard].Lock() 649 defer indexMu[shard].Unlock() 650 651 var idx *labels.Index 652 if idx, err = getCachedLabelIndex(d, v, op.Target); err != nil { 653 return 654 } 655 if idx == nil { 656 err = fmt.Errorf("cannot cleave non-existent label %d", op.Target) 657 return 658 } 659 idx.LastMutId = op.MutID 660 idx.LastModUser = info.User 661 idx.LastModTime = info.Time 662 idx.LastModApp = info.App 663 664 if err := d.addMutcache(v, op.MutID, idx); err != nil { 665 dvid.Criticalf("unable to add cleaved mutid %d index %d: %v\n", op.MutID, op.Target, err) 666 } 667 668 supervoxels := idx.GetSupervoxels() 669 for _, supervoxel := range op.CleavedSupervoxels { 670 if _, found := supervoxels[supervoxel]; !found { 671 err = fmt.Errorf("cannot cleave supervoxel %d, which does not exist in label %d", supervoxel, op.Target) 672 return 673 } 674 delete(supervoxels, supervoxel) 675 } 676 if len(supervoxels) == 0 { 677 err = fmt.Errorf("cannot cleave all supervoxels from the label %d", op.Target) 678 return 679 } 680 681 // create a new label index to contain the cleaved supervoxels. 682 // we don't have to worry about mutex here because it's a new index. 683 var cidx *labels.Index 684 cleavedSize, remainSize, cidx = idx.Cleave(op.CleavedLabel, op.CleavedSupervoxels) 685 cidx.LastMutId = op.MutID 686 cidx.LastModUser = info.User 687 cidx.LastModTime = info.Time 688 cidx.LastModApp = info.App 689 if err = putCachedLabelIndex(d, v, cidx); err != nil { 690 return 691 } 692 err = putCachedLabelIndex(d, v, idx) 693 return 694 } 695 696 // ChangeLabelIndex applies changes to a label's index and then stores the result. 697 // Supervoxel size changes for blocks should be passed into the function. The passed 698 // SupervoxelDelta can contain more supervoxels than the label index. 699 func ChangeLabelIndex(d dvid.Data, v dvid.VersionID, label uint64, delta labels.SupervoxelChanges) error { 700 shard := label % numIndexShards 701 indexMu[shard].Lock() 702 defer indexMu[shard].Unlock() 703 704 idx, err := getCachedLabelIndex(d, v, label) 705 if err != nil { 706 return err 707 } 708 if idx == nil { 709 idx = new(labels.Index) 710 idx.Label = label 711 } 712 713 if err := idx.ModifyBlocks(label, delta); err != nil { 714 return err 715 } 716 717 if len(idx.Blocks) == 0 { 718 return deleteCachedLabelIndex(d, v, label) 719 } 720 return putCachedLabelIndex(d, v, idx) 721 } 722 723 // getMergedIndex gets index data for all labels in a set with possible bounds. 724 func (d *Data) getMergedIndex(v dvid.VersionID, mutID uint64, lbls labels.Set, bounds dvid.Bounds) (*labels.Index, error) { 725 if len(lbls) == 0 { 726 return nil, nil 727 } 728 idx := new(labels.Index) 729 for label := range lbls { 730 idx2, err := GetLabelIndex(d, v, label, false) 731 if err != nil { 732 return nil, err 733 } 734 if err := d.addMutcache(v, mutID, idx2); err != nil { 735 dvid.Criticalf("unable to add merge mutid %d index %d: %v\n", mutID, label, err) 736 } 737 if bounds.Block != nil && bounds.Block.IsSet() { 738 if err := idx2.FitToBounds(bounds.Block); err != nil { 739 return nil, err 740 } 741 } 742 if err := idx.Add(idx2); err != nil { 743 return nil, err 744 } 745 } 746 return idx, nil 747 } 748 749 // given supervoxels with given mapping and whether they were actually in in-memory SVMap, check 750 // label indices to see if supervoxels really are present in assigned bodies. 751 func (d *Data) verifyMappings(ctx *datastore.VersionedCtx, supervoxels, mapped []uint64, found []bool) (verified []uint64, err error) { 752 numSupervoxels := len(supervoxels) 753 if numSupervoxels != len(mapped) { 754 return nil, fmt.Errorf("length of supervoxels list (%d) not equal to length of provided mappings (%d)", numSupervoxels, len(mapped)) 755 } 756 if numSupervoxels != len(found) { 757 return nil, fmt.Errorf("length of supervoxels list (%d) not equal to length of provided found mappings (%d)", numSupervoxels, len(found)) 758 } 759 bodySupervoxels := make(map[uint64]labels.Set) 760 for i, supervoxel := range supervoxels { 761 if supervoxel != 0 && !found[i] { // we are uncertain whether this is a real or implicit supervoxel that may not exist 762 bodysvs, bodyfound := bodySupervoxels[mapped[i]] 763 if !bodyfound { 764 bodysvs = labels.Set{supervoxel: struct{}{}} 765 } else { 766 bodysvs[supervoxel] = struct{}{} 767 } 768 bodySupervoxels[mapped[i]] = bodysvs 769 } 770 } 771 772 wasVerified := make(map[uint64]bool, numSupervoxels) 773 for label, bodysvs := range bodySupervoxels { 774 shard := label % numIndexShards 775 indexMu[shard].RLock() 776 idx, err := getCachedLabelIndex(d, ctx.VersionID(), label) 777 indexMu[shard].RUnlock() 778 if err != nil { 779 return nil, err 780 } 781 svpresent := idx.SupervoxelsPresent(bodysvs) 782 for supervoxel, present := range svpresent { 783 wasVerified[supervoxel] = present 784 } 785 } 786 787 verified = make([]uint64, numSupervoxels) 788 for i, label := range mapped { 789 if found[i] || wasVerified[supervoxels[i]] { 790 verified[i] = label 791 } else { 792 verified[i] = 0 793 } 794 } 795 return 796 } 797 798 // computes supervoxel split on a label index, returning the split index and the slice of blocks 799 // that were modified. 800 func (d *Data) splitSupervoxelIndex(v dvid.VersionID, info dvid.ModInfo, op labels.SplitSupervoxelOp, idx *labels.Index) (dvid.IZYXSlice, error) { 801 idx.LastMutId = op.MutID 802 idx.LastModUser = info.User 803 idx.LastModTime = info.Time 804 idx.LastModApp = info.App 805 806 // modify the index to reflect old supervoxel -> two new supervoxels. 807 var svblocks dvid.IZYXSlice 808 for zyx, svc := range idx.Blocks { 809 origNumVoxels, found := svc.Counts[op.Supervoxel] 810 if found { // split supervoxel is in this block 811 delete(svc.Counts, op.Supervoxel) 812 izyx := labels.BlockIndexToIZYXString(zyx) 813 svblocks = append(svblocks, izyx) 814 rles, found := op.Split[izyx] 815 if found { // part of split 816 splitNumVoxels, _ := rles.Stats() 817 svc.Counts[op.SplitSupervoxel] = uint32(splitNumVoxels) 818 if splitNumVoxels > uint64(origNumVoxels) { 819 return nil, fmt.Errorf("tried to split %d voxels from supervoxel %d, but label index only has %d voxels", splitNumVoxels, op.Supervoxel, origNumVoxels) 820 } 821 if splitNumVoxels != uint64(origNumVoxels) { 822 svc.Counts[op.RemainSupervoxel] = origNumVoxels - uint32(splitNumVoxels) 823 } 824 } else { // part of remainder 825 svc.Counts[op.RemainSupervoxel] = origNumVoxels 826 } 827 } 828 } 829 return svblocks, nil 830 } 831 832 // SplitIndex modifies the split label's index and creates a new index for the split portion. 833 func (d *Data) splitIndex(v dvid.VersionID, info dvid.ModInfo, op labels.SplitOp, idx *labels.Index, splitMap dvid.BlockRLEs, blockSplits blockSplitsMap) error { 834 idx.LastMutId = op.MutID 835 idx.LastModUser = info.User 836 idx.LastModTime = info.Time 837 idx.LastModApp = info.App 838 839 sidx := new(labels.Index) 840 sidx.LastMutId = op.MutID 841 sidx.LastModUser = info.User 842 sidx.LastModTime = info.Time 843 sidx.LastModApp = info.App 844 sidx.Label = op.NewLabel 845 sidx.Blocks = make(map[uint64]*proto.SVCount, len(blockSplits)) 846 847 for zyx, indexsvc := range idx.Blocks { 848 splitCount, inSplitBlock := blockSplits[zyx] 849 var splitsvc *proto.SVCount 850 if inSplitBlock { 851 splitsvc = new(proto.SVCount) 852 splitsvc.Counts = make(map[uint64]uint32, len(splitCount)) 853 } 854 for supervoxel, svOrigCount := range indexsvc.Counts { 855 var svWasSplit bool 856 var svSplitCount labels.SVSplitCount 857 if inSplitBlock { 858 svSplitCount, svWasSplit = splitCount[supervoxel] 859 if svWasSplit { 860 if svSplitCount.Voxels > svOrigCount { 861 return fmt.Errorf("block %s had %d voxels written over supervoxel %d in label %d split yet this supervoxel only had %d voxels from index", labels.BlockIndexToIZYXString(zyx), svSplitCount.Voxels, supervoxel, op.Target, svOrigCount) 862 } 863 splitsvc.Counts[svSplitCount.Split] = svSplitCount.Voxels 864 if svOrigCount > svSplitCount.Voxels { 865 indexsvc.Counts[svSplitCount.Remain] = svOrigCount - svSplitCount.Voxels 866 } 867 delete(indexsvc.Counts, supervoxel) 868 } 869 } 870 if !svWasSplit { 871 // see if split anywhere 872 svsplit, found := op.SplitMap[supervoxel] 873 if found { 874 indexsvc.Counts[svsplit.Remain] = svOrigCount 875 delete(indexsvc.Counts, supervoxel) 876 } 877 } 878 } 879 if inSplitBlock { 880 sidx.Blocks[zyx] = splitsvc 881 } 882 if len(indexsvc.Counts) == 0 { 883 delete(idx.Blocks, zyx) 884 } 885 } 886 887 if err := putCachedLabelIndex(d, v, idx); err != nil { 888 return fmt.Errorf("modify split index for data %q, label %d: %v", d.DataName(), op.Target, err) 889 } 890 if err := putCachedLabelIndex(d, v, sidx); err != nil { 891 return fmt.Errorf("create new split index for data %q, label %d: %v", d.DataName(), op.NewLabel, err) 892 } 893 return nil 894 } 895 896 /////////////////////////////////////// 897 898 // block-level analysis of mutation to get supervoxel changes in a block. accumulates data for 899 // a given mutation into a map per mutation which will then be flushed for each supervoxel meta 900 // k/v pair at end of mutation. 901 func (d *Data) handleBlockMutate(v dvid.VersionID, ch chan blockChange, mut MutatedBlock) { 902 if !d.IndexedLabels { 903 return 904 } 905 bc := blockChange{ 906 bcoord: mut.BCoord, 907 } 908 if d.IndexedLabels { 909 // if mut.Prev == nil { 910 // dvid.Infof("block mutate %s has no previous block\n", mut.Prev) 911 // } else { 912 // dvid.Infof("block mutate %s: prev labels %v\n", mut.BCoord, mut.Prev.Labels) 913 // } 914 bc.delta = mut.Data.CalcNumLabels(mut.Prev) 915 } 916 ch <- bc 917 } 918 919 // block-level analysis of label ingest to do indexing 920 func (d *Data) handleBlockIndexing(v dvid.VersionID, ch chan blockChange, mut IngestedBlock) { 921 if !d.IndexedLabels { 922 return 923 } 924 bc := blockChange{ 925 bcoord: mut.BCoord, 926 } 927 if d.IndexedLabels { 928 bc.delta = mut.Data.CalcNumLabels(nil) 929 } 930 ch <- bc 931 } 932 933 // Goroutines accepts block-level changes and segregates all changes by supervoxel, and then 934 // sends supervoxel-specific changes to concurrency-handling label indexing functions. 935 936 type blockChange struct { 937 bcoord dvid.IZYXString 938 delta map[uint64]int32 939 } 940 941 // goroutine(s) that aggregates supervoxel changes across blocks for one mutation, then calls 942 // mutex-guarded label index mutation routine. 943 func (d *Data) aggregateBlockChanges(v dvid.VersionID, svmap *VCache, ch <-chan blockChange) { 944 mappedVersions := svmap.getMappedVersionsDist(v) 945 labelset := make(labels.Set) 946 svChanges := make(labels.SupervoxelChanges) 947 var maxLabel uint64 948 for change := range ch { 949 for supervoxel, delta := range change.delta { 950 blockChanges, found := svChanges[supervoxel] 951 if !found { 952 blockChanges = make(map[dvid.IZYXString]int32) 953 svChanges[supervoxel] = blockChanges 954 } 955 blockChanges[change.bcoord] += delta 956 if supervoxel > maxLabel { 957 maxLabel = supervoxel 958 } 959 label, _ := svmap.mapLabel(supervoxel, mappedVersions) 960 labelset[label] = struct{}{} 961 } 962 } 963 go func() { 964 if _, err := d.updateMaxLabel(v, maxLabel); err != nil { 965 dvid.Errorf("max label change during block aggregation for %q: %v\n", d.DataName(), err) 966 } 967 }() 968 if d.IndexedLabels { 969 for label := range labelset { 970 if err := ChangeLabelIndex(d, v, label, svChanges); err != nil { 971 dvid.Errorf("indexing label %d: %v\n", label, err) 972 } 973 } 974 } 975 } 976 977 type labelBlock struct { 978 index dvid.IZYXString 979 data []byte 980 } 981 982 type rleResult struct { 983 runs uint32 984 serialization []byte 985 } 986 987 // goroutine to process retrieved label data and generate RLEs, could be sharded by block coordinate 988 func (d *Data) processBlocksToRLEs(lbls labels.Set, bounds dvid.Bounds, in chan labelBlock, out chan rleResult) { 989 for { 990 lb, more := <-in 991 if !more { 992 return 993 } 994 var result rleResult 995 data, _, err := dvid.DeserializeData(lb.data, true) 996 if err != nil { 997 dvid.Errorf("could not deserialize %d bytes in block %s: %v\n", len(lb.data), lb.index, err) 998 out <- result 999 continue 1000 } 1001 var block labels.Block 1002 if err := block.UnmarshalBinary(data); err != nil { 1003 dvid.Errorf("unable to unmarshal label block %s: %v\n", lb.index, err) 1004 } 1005 blockData, _ := block.MakeLabelVolume() 1006 1007 var newRuns uint32 1008 var serialization []byte 1009 if bounds.Exact && bounds.Voxel.IsSet() { 1010 serialization, newRuns, err = d.addBoundedRLEs(lb.index, blockData, lbls, bounds.Voxel) 1011 } else { 1012 serialization, newRuns, err = d.addRLEs(lb.index, blockData, lbls) 1013 } 1014 if err != nil { 1015 dvid.Errorf("could not process %d bytes in block %s to create RLEs: %v\n", len(blockData), lb.index, err) 1016 } else { 1017 result = rleResult{runs: newRuns, serialization: serialization} 1018 } 1019 out <- result 1020 } 1021 } 1022 1023 func writeRLE(w io.Writer, start dvid.Point3d, run int32) error { 1024 rle := dvid.NewRLE(start, run) 1025 serialization, err := rle.MarshalBinary() 1026 if err != nil { 1027 return err 1028 } 1029 if _, err := w.Write(serialization); err != nil { 1030 return err 1031 } 1032 return nil 1033 } 1034 1035 // Scan a block and construct RLEs that will be serialized and added to the given buffer. 1036 func (d *Data) addRLEs(izyx dvid.IZYXString, data []byte, lbls labels.Set) (serialization []byte, newRuns uint32, err error) { 1037 if len(data) != int(d.BlockSize().Prod())*8 { 1038 err = fmt.Errorf("deserialized label block %d bytes, not uint64 size times %d block elements", 1039 len(data), d.BlockSize().Prod()) 1040 return 1041 } 1042 var indexZYX dvid.IndexZYX 1043 indexZYX, err = izyx.IndexZYX() 1044 if err != nil { 1045 return 1046 } 1047 firstPt := indexZYX.MinPoint(d.BlockSize()) 1048 lastPt := indexZYX.MaxPoint(d.BlockSize()) 1049 1050 var label uint64 1051 var spanStart dvid.Point3d 1052 var z, y, x, spanRun int32 1053 start := 0 1054 buf := new(bytes.Buffer) 1055 for z = firstPt.Value(2); z <= lastPt.Value(2); z++ { 1056 for y = firstPt.Value(1); y <= lastPt.Value(1); y++ { 1057 for x = firstPt.Value(0); x <= lastPt.Value(0); x++ { 1058 label = binary.LittleEndian.Uint64(data[start : start+8]) 1059 start += 8 1060 1061 // If we are in labels of interest, start or extend run. 1062 inSpan := false 1063 if label != 0 { 1064 _, inSpan = lbls[label] 1065 } 1066 if inSpan { 1067 spanRun++ 1068 if spanRun == 1 { 1069 spanStart = dvid.Point3d{x, y, z} 1070 } 1071 } else { 1072 if spanRun > 0 { 1073 newRuns++ 1074 if err = writeRLE(buf, spanStart, spanRun); err != nil { 1075 return 1076 } 1077 } 1078 spanRun = 0 1079 } 1080 } 1081 // Force break of any runs when we finish x scan. 1082 if spanRun > 0 { 1083 if err = writeRLE(buf, spanStart, spanRun); err != nil { 1084 return 1085 } 1086 newRuns++ 1087 spanRun = 0 1088 } 1089 } 1090 } 1091 serialization = buf.Bytes() 1092 return 1093 } 1094 1095 // Scan a block and construct bounded RLEs that will be serialized and added to the given buffer. 1096 func (d *Data) addBoundedRLEs(izyx dvid.IZYXString, data []byte, lbls labels.Set, bounds *dvid.OptionalBounds) (serialization []byte, newRuns uint32, err error) { 1097 if len(data) != int(d.BlockSize().Prod())*8 { 1098 err = fmt.Errorf("deserialized label block %d bytes, not uint64 size times %d block elements", 1099 len(data), d.BlockSize().Prod()) 1100 return 1101 } 1102 var indexZYX dvid.IndexZYX 1103 indexZYX, err = izyx.IndexZYX() 1104 if err != nil { 1105 return 1106 } 1107 firstPt := indexZYX.MinPoint(d.BlockSize()) 1108 lastPt := indexZYX.MaxPoint(d.BlockSize()) 1109 1110 var label uint64 1111 var spanStart dvid.Point3d 1112 var z, y, x, spanRun int32 1113 start := 0 1114 buf := new(bytes.Buffer) 1115 yskip := int(d.BlockSize().Value(0) * 8) 1116 zskip := int(d.BlockSize().Value(1)) * yskip 1117 for z = firstPt.Value(2); z <= lastPt.Value(2); z++ { 1118 if bounds.OutsideZ(z) { 1119 start += zskip 1120 continue 1121 } 1122 for y = firstPt.Value(1); y <= lastPt.Value(1); y++ { 1123 if bounds.OutsideY(y) { 1124 start += yskip 1125 continue 1126 } 1127 for x = firstPt.Value(0); x <= lastPt.Value(0); x++ { 1128 label = binary.LittleEndian.Uint64(data[start : start+8]) 1129 start += 8 1130 1131 // If we are in labels of interest, start or extend run. 1132 inSpan := false 1133 if label != 0 { 1134 _, inSpan = lbls[label] 1135 if inSpan && bounds.OutsideX(x) { 1136 inSpan = false 1137 } 1138 } 1139 if inSpan { 1140 spanRun++ 1141 if spanRun == 1 { 1142 spanStart = dvid.Point3d{x, y, z} 1143 } 1144 } else { 1145 if spanRun > 0 { 1146 newRuns++ 1147 if err = writeRLE(buf, spanStart, spanRun); err != nil { 1148 return 1149 } 1150 } 1151 spanRun = 0 1152 } 1153 } 1154 // Force break of any runs when we finish x scan. 1155 if spanRun > 0 { 1156 if err = writeRLE(buf, spanStart, spanRun); err != nil { 1157 return 1158 } 1159 newRuns++ 1160 spanRun = 0 1161 } 1162 } 1163 } 1164 serialization = buf.Bytes() 1165 return 1166 } 1167 1168 // FoundSparseVol returns true if a sparse volume is found for the given label 1169 // within the given bounds. 1170 func (d *Data) FoundSparseVol(ctx *datastore.VersionedCtx, label uint64, bounds dvid.Bounds, isSupervoxel bool) (bool, error) { 1171 idx, err := GetBoundedIndex(d, ctx.VersionID(), label, bounds, isSupervoxel) 1172 if err != nil { 1173 return false, err 1174 } 1175 1176 if idx != nil && len(idx.Blocks) > 0 { 1177 return true, nil 1178 } 1179 return false, nil 1180 } 1181 1182 // encapsulates all we need to know about blocks & supervoxels within scaled, bounded labels 1183 type labelBlockMetadata struct { 1184 label uint64 1185 scale uint8 1186 bounds dvid.Bounds 1187 supervoxels labels.Set 1188 sortedBlocks dvid.IZYXSlice 1189 } 1190 1191 // use label index to return supervoxels and sorted blocks that meet criteria of scale and bounds 1192 func (d *Data) constrainLabelIndex(ctx *datastore.VersionedCtx, label uint64, scale uint8, bounds dvid.Bounds, isSupervoxel bool) (blockMeta *labelBlockMetadata, exists bool, err error) { 1193 blockMeta = &labelBlockMetadata{label: label, scale: scale, bounds: bounds} 1194 var idx *labels.Index 1195 if idx, err = GetLabelIndex(d, ctx.VersionID(), label, isSupervoxel); err != nil { 1196 return 1197 } 1198 if idx == nil || len(idx.Blocks) == 0 { 1199 exists = false 1200 return 1201 } 1202 blockMeta.supervoxels = idx.GetSupervoxels() 1203 var supervoxel uint64 1204 if isSupervoxel { 1205 supervoxel = label 1206 if _, exists = blockMeta.supervoxels[supervoxel]; !exists { 1207 return 1208 } 1209 blockMeta.supervoxels = labels.Set{supervoxel: struct{}{}} 1210 } 1211 1212 if blockMeta.sortedBlocks, err = idx.GetProcessedBlockIndices(scale, bounds, supervoxel); err != nil { 1213 return 1214 } 1215 if len(blockMeta.sortedBlocks) == 0 { // if no blocks are within bounds, regardless of scale 1216 exists = false 1217 return 1218 } 1219 sort.Sort(blockMeta.sortedBlocks) 1220 exists = true 1221 return 1222 } 1223 1224 // writeBinaryBlocks does a streaming write of an encoded sparse volume given a label. 1225 // It returns a bool whether the label exists even if there's no data at the given scale and bounds. 1226 func (d *Data) writeBinaryBlocks(ctx *datastore.VersionedCtx, blockMeta *labelBlockMetadata, compression string, w io.Writer) error { 1227 store, err := datastore.GetOrderedKeyValueDB(d) 1228 if err != nil { 1229 return err 1230 } 1231 op := labels.NewOutputOp(w) 1232 go labels.WriteBinaryBlocks(blockMeta.label, blockMeta.supervoxels, op, blockMeta.bounds) 1233 var preErr error 1234 for _, izyx := range blockMeta.sortedBlocks { 1235 tk := NewBlockTKeyByCoord(blockMeta.scale, izyx) 1236 data, err := store.Get(ctx, tk) 1237 if err != nil { 1238 preErr = err 1239 break 1240 } 1241 if data == nil { 1242 preErr = fmt.Errorf("expected block %s @ scale %d to have key-value, but found none", izyx, blockMeta.scale) 1243 break 1244 } 1245 blockData, _, err := dvid.DeserializeData(data, true) 1246 if err != nil { 1247 preErr = err 1248 break 1249 } 1250 var block labels.Block 1251 if err := block.UnmarshalBinary(blockData); err != nil { 1252 preErr = err 1253 break 1254 } 1255 pb := labels.PositionedBlock{ 1256 Block: block, 1257 BCoord: izyx, 1258 } 1259 op.Process(&pb) 1260 } 1261 if err = op.Finish(); err != nil { 1262 return err 1263 } 1264 1265 dvid.Infof("labelmap %q label %d consisting of %d supervoxels: streamed %d blocks within bounds\n", 1266 d.DataName(), blockMeta.label, len(blockMeta.supervoxels), len(blockMeta.sortedBlocks)) 1267 return preErr 1268 } 1269 1270 // writeStreamingRLE does a streaming write of an encoded sparse volume given a label. 1271 // It returns a bool whether the label was found in the given bounds and any error. 1272 func (d *Data) writeStreamingRLE(ctx *datastore.VersionedCtx, blockMeta *labelBlockMetadata, compression string, w io.Writer) error { 1273 store, err := datastore.GetOrderedKeyValueDB(d) 1274 if err != nil { 1275 return err 1276 } 1277 op := labels.NewOutputOp(w) 1278 go labels.WriteRLEs(blockMeta.supervoxels, op, blockMeta.bounds) 1279 for _, izyx := range blockMeta.sortedBlocks { 1280 tk := NewBlockTKeyByCoord(blockMeta.scale, izyx) 1281 data, err := store.Get(ctx, tk) 1282 if err != nil { 1283 return err 1284 } 1285 blockData, _, err := dvid.DeserializeData(data, true) 1286 if err != nil { 1287 return err 1288 } 1289 var block labels.Block 1290 if err := block.UnmarshalBinary(blockData); err != nil { 1291 return err 1292 } 1293 pb := labels.PositionedBlock{ 1294 Block: block, 1295 BCoord: izyx, 1296 } 1297 op.Process(&pb) 1298 } 1299 if err = op.Finish(); err != nil { 1300 return err 1301 } 1302 1303 dvid.Infof("labelmap %q label %d consisting of %d supervoxels: streamed %d blocks within bounds\n", 1304 d.DataName(), blockMeta.label, len(blockMeta.supervoxels), len(blockMeta.sortedBlocks)) 1305 return nil 1306 } 1307 1308 // Write legacy RLEs to writer. Body can exist but have no data if scale is too low-res. 1309 // 1310 // The encoding has the following format where integers are little endian: 1311 // 1312 // byte Payload descriptor: 1313 // Bit 0 (LSB) - 8-bit grayscale 1314 // Bit 1 - 16-bit grayscale 1315 // Bit 2 - 16-bit normal 1316 // ... 1317 // uint8 Number of dimensions 1318 // uint8 Dimension of run (typically 0 = X) 1319 // byte Reserved (to be used later) 1320 // uint32 0 1321 // uint32 # Spans 1322 // Repeating unit of: 1323 // int32 Coordinate of run start (dimension 0) 1324 // int32 Coordinate of run start (dimension 1) 1325 // int32 Coordinate of run start (dimension 2) 1326 // int32 Length of run 1327 // bytes Optional payload dependent on first byte descriptor 1328 func (d *Data) writeLegacyRLE(ctx *datastore.VersionedCtx, blockMeta *labelBlockMetadata, compression string, w io.Writer) error { 1329 buf := new(bytes.Buffer) 1330 buf.WriteByte(dvid.EncodingBinary) 1331 binary.Write(buf, binary.LittleEndian, uint8(3)) // # of dimensions 1332 binary.Write(buf, binary.LittleEndian, byte(0)) // dimension of run (X = 0) 1333 buf.WriteByte(byte(0)) // reserved for later 1334 binary.Write(buf, binary.LittleEndian, uint32(0)) // Placeholder for # voxels 1335 binary.Write(buf, binary.LittleEndian, uint32(0)) // Placeholder for # spans 1336 1337 store, err := datastore.GetOrderedKeyValueDB(d) 1338 if err != nil { 1339 return err 1340 } 1341 op := labels.NewOutputOp(buf) 1342 go labels.WriteRLEs(blockMeta.supervoxels, op, blockMeta.bounds) 1343 var numEmpty int 1344 for _, izyx := range blockMeta.sortedBlocks { 1345 tk := NewBlockTKeyByCoord(blockMeta.scale, izyx) 1346 data, err := store.Get(ctx, tk) 1347 if err != nil { 1348 return err 1349 } 1350 if len(data) == 0 { 1351 numEmpty++ 1352 if numEmpty < 10 { 1353 dvid.Errorf("Block %s included in blocks for labels %s but has no data (%d times)... skipping.\n", 1354 izyx, blockMeta.supervoxels, numEmpty) 1355 } else if numEmpty == 10 { 1356 dvid.Errorf("Over %d blocks included in blocks with no data. Halting error stream.\n", numEmpty) 1357 } 1358 continue 1359 } 1360 blockData, _, err := dvid.DeserializeData(data, true) 1361 if err != nil { 1362 return err 1363 } 1364 var block labels.Block 1365 if err = block.UnmarshalBinary(blockData); err != nil { 1366 return err 1367 } 1368 pb := labels.PositionedBlock{ 1369 Block: block, 1370 BCoord: izyx, 1371 } 1372 op.Process(&pb) 1373 } 1374 if numEmpty < len(blockMeta.sortedBlocks) { 1375 if err := op.Finish(); err != nil { 1376 return err 1377 } 1378 } 1379 1380 serialization := buf.Bytes() 1381 if len(serialization) == 0 { 1382 return nil 1383 } 1384 numRuns := uint32(len(serialization)-12) >> 4 1385 if numRuns == 0 { 1386 return nil 1387 } 1388 1389 binary.LittleEndian.PutUint32(serialization[8:12], numRuns) 1390 dvid.Infof("label %d: sending %d blocks within bounds excluding %d empty blocks, %d runs, serialized %d bytes\n", 1391 blockMeta.label, len(blockMeta.sortedBlocks), numEmpty, numRuns, len(serialization)) 1392 1393 switch compression { 1394 case "": 1395 _, err = w.Write(serialization) 1396 case "lz4": 1397 compressed := make([]byte, lz4.CompressBound(serialization)) 1398 var n, outSize int 1399 if outSize, err = lz4.Compress(serialization, compressed); err != nil { 1400 return err 1401 } 1402 compressed = compressed[:outSize] 1403 n, err = w.Write(compressed) 1404 if n != outSize { 1405 err = fmt.Errorf("only able to write %d of %d lz4 compressed bytes", n, outSize) 1406 } 1407 case "gzip": 1408 gw := gzip.NewWriter(w) 1409 if _, err = gw.Write(serialization); err != nil { 1410 return err 1411 } 1412 err = gw.Close() 1413 default: 1414 err = fmt.Errorf("unknown compression type %q", compression) 1415 } 1416 return err 1417 } 1418 1419 // GetSparseCoarseVol returns an encoded sparse volume given a label. This will return nil slice 1420 // if the given label was not found. The encoding has the following format where integers are 1421 // little endian and blocks are returned in sorted ZYX order (small Z first): 1422 // 1423 // byte Set to 0 1424 // uint8 Number of dimensions 1425 // uint8 Dimension of run (typically 0 = X) 1426 // byte Reserved (to be used later) 1427 // uint32 # Blocks [TODO. 0 for now] 1428 // uint32 # Spans 1429 // Repeating unit of: 1430 // int32 Block coordinate of run start (dimension 0) 1431 // int32 Block coordinate of run start (dimension 1) 1432 // int32 Block coordinate of run start (dimension 2) 1433 // int32 Length of run 1434 func (d *Data) GetSparseCoarseVol(ctx *datastore.VersionedCtx, label uint64, bounds dvid.Bounds, isSupervoxel bool) ([]byte, error) { 1435 idx, err := GetLabelIndex(d, ctx.VersionID(), label, isSupervoxel) 1436 if err != nil { 1437 return nil, err 1438 } 1439 if idx == nil || len(idx.Blocks) == 0 { 1440 return nil, nil 1441 } 1442 var supervoxel uint64 1443 if isSupervoxel { 1444 supervoxel = label 1445 idx, err = idx.LimitToSupervoxel(supervoxel) 1446 if err != nil { 1447 return nil, err 1448 } 1449 if idx == nil { 1450 return nil, nil 1451 } 1452 } 1453 blocks, err := idx.GetProcessedBlockIndices(0, bounds, supervoxel) 1454 if err != nil { 1455 return nil, err 1456 } 1457 sort.Sort(blocks) 1458 1459 // Create the sparse volume header 1460 buf := new(bytes.Buffer) 1461 buf.WriteByte(dvid.EncodingBinary) 1462 binary.Write(buf, binary.LittleEndian, uint8(3)) // # of dimensions 1463 binary.Write(buf, binary.LittleEndian, byte(0)) // dimension of run (X = 0) 1464 buf.WriteByte(byte(0)) // reserved for later 1465 binary.Write(buf, binary.LittleEndian, uint32(0)) // Placeholder for # voxels 1466 binary.Write(buf, binary.LittleEndian, uint32(0)) // Placeholder for # spans 1467 1468 spans, err := blocks.WriteSerializedRLEs(buf) 1469 if err != nil { 1470 return nil, err 1471 } 1472 serialization := buf.Bytes() 1473 binary.LittleEndian.PutUint32(serialization[8:12], spans) // Placeholder for # spans 1474 1475 return serialization, nil 1476 } 1477 1478 // WriteSparseCoarseVols returns a stream of sparse volumes with blocks of the given label 1479 // in encoded RLE format: 1480 // 1481 // uint64 label 1482 // <coarse sparse vol as given below> 1483 // 1484 // uint64 label 1485 // <coarse sparse vol as given below> 1486 // 1487 // ... 1488 // 1489 // The coarse sparse vol has the following format where integers are little endian and the order 1490 // of data is exactly as specified below: 1491 // 1492 // int32 # Spans 1493 // Repeating unit of: 1494 // int32 Block coordinate of run start (dimension 0) 1495 // int32 Block coordinate of run start (dimension 1) 1496 // int32 Block coordinate of run start (dimension 2) 1497 // int32 Length of run 1498 func (d *Data) WriteSparseCoarseVols(ctx *datastore.VersionedCtx, w io.Writer, begLabel, endLabel uint64, bounds dvid.Bounds) error { 1499 1500 store, err := datastore.GetOrderedKeyValueDB(d) 1501 if err != nil { 1502 return err 1503 } 1504 begTKey := NewLabelIndexTKey(begLabel) 1505 endTKey := NewLabelIndexTKey(endLabel) 1506 1507 err = store.ProcessRange(ctx, begTKey, endTKey, &storage.ChunkOp{}, func(c *storage.Chunk) error { 1508 if c == nil || c.TKeyValue == nil { 1509 return nil 1510 } 1511 kv := c.TKeyValue 1512 if kv.V == nil { 1513 return nil 1514 } 1515 label, err := DecodeLabelIndexTKey(kv.K) 1516 if err != nil { 1517 return err 1518 } 1519 val, _, err := dvid.DeserializeData(kv.V, true) 1520 if err != nil { 1521 return err 1522 } 1523 var idx labels.Index 1524 if len(val) != 0 { 1525 if err := pb.Unmarshal(val, &idx); err != nil { 1526 return err 1527 } 1528 blocks, err := idx.GetProcessedBlockIndices(0, bounds, 0) 1529 if err != nil { 1530 return err 1531 } 1532 sort.Sort(blocks) 1533 buf := new(bytes.Buffer) 1534 spans, err := blocks.WriteSerializedRLEs(buf) 1535 if err != nil { 1536 return err 1537 } 1538 binary.Write(w, binary.LittleEndian, label) 1539 binary.Write(w, binary.LittleEndian, int32(spans)) 1540 w.Write(buf.Bytes()) 1541 } 1542 return nil 1543 }) 1544 return err 1545 } 1546 1547 func (d *Data) countThread(f *os.File, mu *sync.Mutex, wg *sync.WaitGroup, chunkCh chan *storage.Chunk) { 1548 for c := range chunkCh { 1549 scale, idx, err := DecodeBlockTKey(c.K) 1550 if err != nil { 1551 dvid.Errorf("Couldn't decode label block key %v for data %q\n", c.K, d.DataName()) 1552 wg.Done() 1553 continue 1554 } 1555 if scale != 0 { 1556 dvid.Errorf("Counts had unexpected error: getting scale %d blocks\n", scale) 1557 wg.Done() 1558 continue 1559 } 1560 var data []byte 1561 data, _, err = dvid.DeserializeData(c.V, true) 1562 if err != nil { 1563 dvid.Errorf("Unable to deserialize block %s in data %q: %v\n", idx, d.DataName(), err) 1564 wg.Done() 1565 continue 1566 } 1567 var block labels.Block 1568 if err := block.UnmarshalBinary(data); err != nil { 1569 dvid.Errorf("Unable to unmarshal Block %s in data %q: %v\n", idx, d.DataName(), err) 1570 wg.Done() 1571 continue 1572 } 1573 counts := block.CalcNumLabels(nil) 1574 for supervoxel, count := range counts { 1575 bx, by, bz := idx.Unpack() 1576 line := fmt.Sprintf("%d %d %d %d %d\n", supervoxel, bz, by, bx, count) 1577 mu.Lock() 1578 _, err := f.WriteString(line) 1579 mu.Unlock() 1580 if err != nil { 1581 dvid.Errorf("Unable to write data for block %s, data %q: %v\n", idx, d.DataName(), err) 1582 break 1583 } 1584 } 1585 wg.Done() 1586 } 1587 } 1588 1589 // scan all label blocks in this labelmap instance, writing supervoxel counts into a given file 1590 func (d *Data) writeSVCounts(f *os.File, outPath string, v dvid.VersionID) { 1591 timedLog := dvid.NewTimeLog() 1592 1593 // Start the counting goroutine 1594 mu := new(sync.Mutex) 1595 wg := new(sync.WaitGroup) 1596 chunkCh := make(chan *storage.Chunk, 100) 1597 for i := 0; i < 100; i++ { 1598 go d.countThread(f, mu, wg, chunkCh) 1599 } 1600 1601 // Iterate through all label blocks and count them. 1602 chunkOp := &storage.ChunkOp{Wg: wg} 1603 1604 store, err := datastore.GetOrderedKeyValueDB(d) 1605 if err != nil { 1606 dvid.Errorf("problem getting store for data %q: %v\n", d.DataName(), err) 1607 return 1608 } 1609 ctx := datastore.NewVersionedCtx(d, v) 1610 begTKey := NewBlockTKeyByCoord(0, dvid.MinIndexZYX.ToIZYXString()) 1611 endTKey := NewBlockTKeyByCoord(0, dvid.MaxIndexZYX.ToIZYXString()) 1612 var numBlocks uint64 1613 err = store.ProcessRange(ctx, begTKey, endTKey, chunkOp, func(c *storage.Chunk) error { 1614 if c == nil { 1615 wg.Done() 1616 return fmt.Errorf("received nil chunk in count for data %q", d.DataName()) 1617 } 1618 if c.V == nil { 1619 wg.Done() 1620 return nil 1621 } 1622 numBlocks++ 1623 if numBlocks%10000 == 0 { 1624 timedLog.Infof("Now counting block %d with chunk channel at %d", numBlocks, len(chunkCh)) 1625 } 1626 chunkCh <- c 1627 return nil 1628 }) 1629 if err != nil { 1630 dvid.Errorf("problem during process range: %v\n", err) 1631 } 1632 close(chunkCh) 1633 wg.Wait() 1634 if err = f.Close(); err != nil { 1635 dvid.Errorf("problem closing file %q: %v\n", outPath, err) 1636 } 1637 timedLog.Infof("Finished counting supervoxels in %d blocks and sent to output file %q", numBlocks, outPath) 1638 } 1639 1640 func (d *Data) writeFileMappings(f *os.File, outPath string, v dvid.VersionID) { 1641 if err := d.writeMappings(f, v, false); err != nil { 1642 dvid.Errorf("error writing mapping to file %q: %v\n", outPath, err) 1643 return 1644 } 1645 if err := f.Close(); err != nil { 1646 dvid.Errorf("problem closing file %q: %v\n", outPath, err) 1647 } 1648 } 1649 1650 func (d *Data) writeMappings(w io.Writer, v dvid.VersionID, binaryFormat bool) error { 1651 timedLog := dvid.NewTimeLog() 1652 1653 vc, err := getMapping(d, v) 1654 if err != nil { 1655 return fmt.Errorf("unable to retrieve mappings for data %q, version %d: %v", d.DataName(), v, err) 1656 } 1657 if !vc.mapUsed { 1658 dvid.Infof("no mappings found for data %q\n", d.DataName()) 1659 return nil 1660 } 1661 numMappings, err := vc.writeMappings(w, v, binaryFormat) 1662 1663 timedLog.Infof("Wrote %d mappings: err = %v", numMappings, err) 1664 return err 1665 } 1666 1667 // Streams labels and optionally # voxels for the label to the http.ResponseWriter. 1668 func (d *Data) listLabels(ctx *datastore.VersionedCtx, start, number uint64, countVoxels bool, w http.ResponseWriter) (numLabels uint64, err error) { 1669 if number == 0 { 1670 return 1671 } 1672 var store storage.OrderedKeyValueDB 1673 store, err = datastore.GetOrderedKeyValueDB(d) 1674 if err != nil { 1675 return 0, fmt.Errorf("problem getting store for data %q: %v", d.DataName(), err) 1676 } 1677 begTKey := NewLabelIndexTKey(start) 1678 endTKey := NewLabelIndexTKey(math.MaxUint64) 1679 haltFakeErr := fmt.Errorf("terminate range query") 1680 err = store.ProcessRange(ctx, begTKey, endTKey, nil, func(c *storage.Chunk) error { 1681 if c == nil || c.V == nil || len(c.V) == 0 { 1682 return nil 1683 } 1684 numLabels++ 1685 label, err := DecodeLabelIndexTKey(c.K) 1686 if err != nil { 1687 return err 1688 } 1689 if err = binary.Write(w, binary.LittleEndian, label); err != nil { 1690 return err 1691 } 1692 if countVoxels { 1693 var data []byte 1694 data, _, err = dvid.DeserializeData(c.V, true) 1695 if err != nil { 1696 return err 1697 } 1698 idx := new(labels.Index) 1699 if err := pb.Unmarshal(data, idx); err != nil { 1700 return err 1701 } 1702 var numVoxels uint64 1703 for _, svc := range idx.Blocks { 1704 if svc != nil && len(svc.Counts) != 0 { 1705 for _, count := range svc.Counts { 1706 numVoxels += uint64(count) 1707 } 1708 } 1709 } 1710 if err = binary.Write(w, binary.LittleEndian, numVoxels); err != nil { 1711 return err 1712 } 1713 } 1714 if numLabels == number { 1715 return haltFakeErr 1716 } 1717 return nil 1718 }) 1719 if err == haltFakeErr { 1720 err = nil 1721 } 1722 return 1723 } 1724 1725 func (d *Data) indexThread(f *os.File, mu *sync.Mutex, wg *sync.WaitGroup, chunkCh chan *storage.Chunk) { 1726 for c := range chunkCh { 1727 label, err := DecodeLabelIndexTKey(c.K) 1728 if err != nil { 1729 dvid.Errorf("Couldn't decode label index key %v for data %q\n", c.K, d.DataName()) 1730 wg.Done() 1731 continue 1732 } 1733 var data []byte 1734 data, _, err = dvid.DeserializeData(c.V, true) 1735 if err != nil { 1736 dvid.Errorf("Unable to deserialize label index %d in data %q: %v\n", label, d.DataName(), err) 1737 wg.Done() 1738 continue 1739 } 1740 idx := new(labels.Index) 1741 if err := pb.Unmarshal(data, idx); err != nil { 1742 dvid.Errorf("Unable to unmarshal label index %d in data %q: %v\n", label, d.DataName(), err) 1743 wg.Done() 1744 continue 1745 } 1746 if idx.Label == 0 { 1747 idx.Label = label 1748 } 1749 for zyx, svc := range idx.Blocks { 1750 bx, by, bz := labels.DecodeBlockIndex(zyx) 1751 if svc != nil && len(svc.Counts) != 0 { 1752 for supervoxel, count := range svc.Counts { 1753 line := fmt.Sprintf("%d %d %d %d %d %d\n", idx.Label, supervoxel, bz, by, bx, count) 1754 mu.Lock() 1755 _, err := f.WriteString(line) 1756 mu.Unlock() 1757 if err != nil { 1758 dvid.Errorf("Unable to write label index %d line, data %q: %v\n", idx.Label, d.DataName(), err) 1759 break 1760 } 1761 } 1762 } 1763 } 1764 wg.Done() 1765 } 1766 } 1767 1768 // scan all label indices in this labelmap instance, writing Blocks data into a given file 1769 func (d *Data) writeIndices(f *os.File, outPath string, v dvid.VersionID) { 1770 timedLog := dvid.NewTimeLog() 1771 1772 // Start the counting goroutine 1773 mu := new(sync.Mutex) 1774 wg := new(sync.WaitGroup) 1775 chunkCh := make(chan *storage.Chunk, 100) 1776 for i := 0; i < 100; i++ { 1777 go d.indexThread(f, mu, wg, chunkCh) 1778 } 1779 1780 // Iterate through all label blocks and count them. 1781 chunkOp := &storage.ChunkOp{Wg: wg} 1782 1783 store, err := datastore.GetOrderedKeyValueDB(d) 1784 if err != nil { 1785 dvid.Errorf("problem getting store for data %q: %v\n", d.DataName(), err) 1786 return 1787 } 1788 ctx := datastore.NewVersionedCtx(d, v) 1789 begTKey := NewLabelIndexTKey(0) 1790 endTKey := NewLabelIndexTKey(math.MaxUint64) 1791 var numIndices uint64 1792 err = store.ProcessRange(ctx, begTKey, endTKey, chunkOp, func(c *storage.Chunk) error { 1793 if c == nil { 1794 wg.Done() 1795 return fmt.Errorf("received nil chunk in dump index for data %q", d.DataName()) 1796 } 1797 if c.V == nil { 1798 wg.Done() 1799 return nil 1800 } 1801 numIndices++ 1802 if numIndices%10000 == 0 { 1803 timedLog.Infof("Now dumping label index %d with chunk channel at %d", numIndices, len(chunkCh)) 1804 } 1805 chunkCh <- c 1806 return nil 1807 }) 1808 if err != nil { 1809 dvid.Errorf("problem during process range: %v\n", err) 1810 } 1811 close(chunkCh) 1812 wg.Wait() 1813 if err = f.Close(); err != nil { 1814 dvid.Errorf("problem closing file %q: %v\n", outPath, err) 1815 } 1816 timedLog.Infof("Finished dumping %d label indices to output file %q", numIndices, outPath) 1817 }