github.com/janelia-flyem/dvid@v1.0.0/datatype/labelvol/push.go (about) 1 package labelvol 2 3 import ( 4 "fmt" 5 6 "github.com/janelia-flyem/dvid/datastore" 7 "github.com/janelia-flyem/dvid/datatype/roi" 8 "github.com/janelia-flyem/dvid/dvid" 9 "github.com/janelia-flyem/dvid/storage" 10 ) 11 12 // PushData does a labelvol-specific push using optional ROI filters. 13 func (d *Data) PushData(p *datastore.PushSession) error { 14 return datastore.PushData(d, p) 15 } 16 17 // --- dvid.Filterer implementation ----- 18 19 // NewFilter returns a Filter for use with a push of key-value pairs. 20 func (d *Data) NewFilter(fs storage.FilterSpec) (storage.Filter, error) { 21 filter := &Filter{Data: d, fs: fs} 22 23 // Get associated labelblk. If none, we can't use roi filter so just do standard data send. 24 lblk, err := d.GetSyncedLabelblk() 25 if err != nil { 26 dvid.Infof("Unable to get synced labelblk for labelvol %q. Unable to do any ROI-based filtering.\n", d.DataName()) 27 return nil, nil 28 } 29 30 roiIterator, _, found, err := roi.NewIteratorBySpec(fs, lblk) 31 if err != nil { 32 return nil, err 33 } 34 if !found || roiIterator == nil { 35 dvid.Debugf("No ROI found so using generic data push for data %q.\n", d.DataName()) 36 return nil, nil 37 } 38 filter.it = roiIterator 39 40 return filter, nil 41 } 42 43 // --- dvid.Filter implementation ---- 44 45 type Filter struct { 46 *Data 47 fs storage.FilterSpec 48 it *roi.Iterator 49 curLabel uint64 50 } 51 52 func (f *Filter) Check(tkv *storage.TKeyValue) (skip bool, err error) { 53 if f.Data == nil { 54 return false, fmt.Errorf("bad filter %q: no data", f.fs) 55 } 56 if f.it == nil { 57 return true, nil 58 } 59 60 // Only filter label block RLE kv pairs. 61 class, err := tkv.K.Class() 62 if err != nil { 63 return true, err 64 } 65 if class != keyLabelBlockRLE { 66 return false, nil 67 } 68 69 // Check the label block against any ROI. 70 label, block, err := DecodeTKey(tkv.K) 71 if err != nil { 72 return true, fmt.Errorf("key (%v) cannot be decoded as labelvol key: %v", tkv.K, err) 73 } 74 indexZYX, err := block.IndexZYX() 75 if err != nil { 76 return true, fmt.Errorf("unable to convert labelvol block %s into IndexZYX", block) 77 } 78 if label != f.curLabel { 79 f.it.Reset() 80 f.curLabel = label 81 } 82 if !f.it.InsideFast(indexZYX) { 83 return true, nil 84 } 85 return false, nil 86 }