diff --git a/datatype/labelmap/handlers.go b/datatype/labelmap/handlers.go index abb1dd86..3e5af0d9 100644 --- a/datatype/labelmap/handlers.go +++ b/datatype/labelmap/handlers.go @@ -433,6 +433,19 @@ func (d *Data) handleIndex(ctx *datastore.VersionedCtx, w http.ResponseWriter, r timedLog.Infof("HTTP %s index for label %d (%s)", r.Method, label, r.URL) } +func (d *Data) handleExistingLabels(ctx *datastore.VersionedCtx, w http.ResponseWriter, r *http.Request) { + // GET /node///existing-labels + + if strings.ToLower(r.Method) != "get" { + server.BadRequest(w, r, "only GET action allowed for /existing-labels endpoint") + return + } + + if err := d.writeExistingIndices(ctx, w, nil); err != nil { + dvid.Errorf("unable to write existing labels: %v", err) + } +} + func (d *Data) handleListLabels(ctx *datastore.VersionedCtx, w http.ResponseWriter, r *http.Request) { // GET /node///listlabels const MaxReturnedLabels = 10000000 diff --git a/datatype/labelmap/labelidx.go b/datatype/labelmap/labelidx.go index ae00a36b..f924dea8 100644 --- a/datatype/labelmap/labelidx.go +++ b/datatype/labelmap/labelidx.go @@ -1765,6 +1765,62 @@ func (d *Data) indexThread(f *os.File, mu *sync.Mutex, wg *sync.WaitGroup, chunk } } +// scan all label indices for the presence of its key, writing existing key's body id +// into a stream and/or setting it in an internal map. +func (d *Data) writeExistingIndices(ctx *datastore.VersionedCtx, w http.ResponseWriter, bodymap map[uint64]struct{}) error { + timedLog := dvid.NewTimeLog() + + store, err := datastore.GetOrderedKeyValueDB(d) + if err != nil { + return fmt.Errorf("problem getting store for data %q: %v", d.DataName(), err) + } + + minTKey := NewLabelIndexTKey(0) + maxTKey := NewLabelIndexTKey(math.MaxUint64) + keyChan := make(storage.KeyChan) + go func() { + store.SendKeysInRange(ctx, minTKey, maxTKey, keyChan) + close(keyChan) + }() + + if w != nil { + w.Header().Set("Content-type", "application/json") + fmt.Fprintf(w, "[") + } + + var numExist uint64 + for key := range keyChan { + if key != nil { + tkey, err := storage.TKeyFromKey(key) + if err != nil { + dvid.Errorf("Unable to get TKey from key %v for data %q: %v\n", key, d.DataName(), err) + continue + } + label, err := DecodeLabelIndexTKey(tkey) + if err != nil { + dvid.Errorf("Couldn't decode label index key %v for data %q\n", key, d.DataName()) + continue + } + if bodymap != nil { + bodymap[label] = struct{}{} + } + if w != nil { + if numExist > 0 { + fmt.Fprintf(w, ",") + } + fmt.Fprintf(w, "%d", label) + } + numExist++ + } + } + if w != nil { + fmt.Fprintf(w, "]") + } + + timedLog.Infof("Finished writing %d existing label indices.", numExist) + return nil +} + // scan all label indices in this labelmap instance, writing Blocks data into a given file func (d *Data) writeIndices(f *os.File, outPath string, v dvid.VersionID) { timedLog := dvid.NewTimeLog() diff --git a/datatype/labelmap/labelmap.go b/datatype/labelmap/labelmap.go index 82dafb87..e7eefabe 100644 --- a/datatype/labelmap/labelmap.go +++ b/datatype/labelmap/labelmap.go @@ -1484,6 +1484,15 @@ POST /node///index/