// Find the children of a given span id. func (store *dataStore) FindChildren(sid common.SpanId, lim int32) []common.SpanId { childIds := make([]common.SpanId, 0) var err error startIdx := store.getShardIndex(sid) idx := startIdx numShards := len(store.shards) for { if lim == 0 { break } shd := store.shards[idx] childIds, lim, err = shd.FindChildren(sid, childIds, lim) if err != nil { store.lg.Errorf("Shard(%s): FindChildren(%s) error: %s\n", shd.path, sid.String(), err.Error()) } idx++ if idx >= numShards { idx = 0 } if idx == startIdx { break } } return childIds }
// Find the child IDs of a given span ID. func (hcl *Client) FindChildren(sid common.SpanId, lim int) ([]common.SpanId, error) { buf, _, err := hcl.makeGetRequest(fmt.Sprintf("span/%s/children?lim=%d", sid.String(), lim)) if err != nil { return nil, err } var spanIds []common.SpanId err = json.Unmarshal(buf, &spanIds) if err != nil { return nil, errors.New(fmt.Sprintf("Error: error unmarshalling response "+ "body %s: %s", string(buf), err.Error())) } return spanIds, nil }
// Get information about a trace span. Returns nil, nil if the span was not found. func (hcl *Client) FindSpan(sid common.SpanId) (*common.Span, error) { buf, rc, err := hcl.makeGetRequest(fmt.Sprintf("span/%s", sid.String())) if err != nil { if rc == http.StatusNoContent { return nil, nil } return nil, err } var span common.Span err = json.Unmarshal(buf, &span) if err != nil { return nil, errors.New(fmt.Sprintf("Error unmarshalling response "+ "body %s: %s", string(buf), err.Error())) } return &span, nil }
func (shd *shard) FindSpan(sid common.SpanId) *common.Span { lg := shd.store.lg primaryKey := append([]byte{SPAN_ID_INDEX_PREFIX}, sid.Val()...) buf, err := shd.ldb.Get(shd.store.readOpts, primaryKey) if err != nil { if strings.Index(err.Error(), "NotFound:") != -1 { return nil } lg.Warnf("Shard(%s): FindSpan(%s) error: %s\n", shd.path, sid.String(), err.Error()) return nil } var span *common.Span span, err = shd.decodeSpan(sid, buf) if err != nil { lg.Errorf("Shard(%s): FindSpan(%s) decode error: %s\n", shd.path, sid.String(), err.Error()) return nil } return span }
// Fill in the entry in the 'next' array for a specific shard. func (src *source) populateNextFromShard(shardIdx int) { lg := src.store.lg var err error iter := src.iters[shardIdx] if iter == nil { lg.Debugf("Can't populate: No more entries in shard %d\n", shardIdx) return // There are no more entries in this shard. } if src.nexts[shardIdx] != nil { lg.Debugf("No need to populate shard %d\n", shardIdx) return // We already have a valid entry for this shard. } for { if !iter.Valid() { lg.Debugf("Can't populate: Iterator for shard %d is no longer valid.\n", shardIdx) break // Can't read past end of DB } src.numRead[shardIdx]++ key := iter.Key() if !bytes.HasPrefix(key, []byte{src.keyPrefix}) { lg.Debugf("Can't populate: Iterator for shard %d does not have prefix %s\n", shardIdx, string(src.keyPrefix)) break // Can't read past end of indexed section } var span *common.Span var sid common.SpanId if src.keyPrefix == SPAN_ID_INDEX_PREFIX { // The span id maps to the span itself. sid = common.SpanId(key[1:17]) span, err = src.store.shards[shardIdx].decodeSpan(sid, iter.Value()) if err != nil { lg.Debugf("Internal error decoding span %s in shard %d: %s\n", sid.String(), shardIdx, err.Error()) break } } else { // With a secondary index, we have to look up the span by id. sid = common.SpanId(key[9:25]) span = src.store.shards[shardIdx].FindSpan(sid) if span == nil { lg.Debugf("Internal error rehydrating span %s in shard %d\n", sid.String(), shardIdx) break } } if src.pred.Op.IsDescending() { iter.Prev() } else { iter.Next() } if src.pred.satisfiedBy(span) { lg.Debugf("Populated valid span %v from shard %d.\n", sid, shardIdx) src.nexts[shardIdx] = span // Found valid entry return } else { lg.Debugf("Span %s from shard %d does not satisfy the predicate.\n", sid.String(), shardIdx) if src.numRead[shardIdx] <= 1 && mayRequireOneSkip(src.pred.Op) { continue } // This and subsequent entries don't satisfy predicate break } } lg.Debugf("Closing iterator for shard %d.\n", shardIdx) iter.Close() src.iters[shardIdx] = nil }
// Fill in the entry in the 'next' array for a specific shard. func (src *source) populateNextFromShard(shardIdx int) { lg := src.store.lg var err error iter := src.iters[shardIdx] shdPath := src.shards[shardIdx].path if iter == nil { lg.Debugf("Can't populate: No more entries in shard %s\n", shdPath) return // There are no more entries in this shard. } if src.nexts[shardIdx] != nil { lg.Debugf("No need to populate shard %s\n", shdPath) return // We already have a valid entry for this shard. } for { if !iter.Valid() { lg.Debugf("Can't populate: Iterator for shard %s is no longer valid.\n", shdPath) break // Can't read past end of DB } src.numRead[shardIdx]++ key := iter.Key() if len(key) < 1 { lg.Warnf("Encountered invalid zero-byte key in shard %s.\n", shdPath) break } ret := src.checkKeyPrefix(key[0], iter) if ret == NOT_SATISFIED { break // Can't read past end of indexed section } else if ret == NOT_YET_SATISFIED { if src.pred.Op.IsDescending() { iter.Prev() } else { iter.Next() } continue // Try again because we are not yet at the indexed section. } var span *common.Span var sid common.SpanId if src.keyPrefix == SPAN_ID_INDEX_PREFIX { // The span id maps to the span itself. sid = common.SpanId(key[1:17]) span, err = src.shards[shardIdx].decodeSpan(sid, iter.Value()) if err != nil { if lg.DebugEnabled() { lg.Debugf("Internal error decoding span %s in shard %s: %s\n", sid.String(), shdPath, err.Error()) } break } } else { // With a secondary index, we have to look up the span by id. sid = common.SpanId(key[9:25]) span = src.shards[shardIdx].FindSpan(sid) if span == nil { if lg.DebugEnabled() { lg.Debugf("Internal error rehydrating span %s in shard %s\n", sid.String(), shdPath) } break } } if src.pred.Op.IsDescending() { iter.Prev() } else { iter.Next() } ret = src.pred.satisfiedBy(span) if ret == SATISFIED { if lg.DebugEnabled() { lg.Debugf("Populated valid span %v from shard %s.\n", sid, shdPath) } src.nexts[shardIdx] = span // Found valid entry return } if ret == NOT_SATISFIED { // This and subsequent entries don't satisfy predicate break } } lg.Debugf("Closing iterator for shard %s.\n", shdPath) iter.Close() src.iters[shardIdx] = nil }