func createRandomTestSpans(amount int) common.SpanSlice { rnd := rand.New(rand.NewSource(2)) allSpans := make(common.SpanSlice, amount) allSpans[0] = test.NewRandomSpan(rnd, allSpans[0:0]) for i := 1; i < amount; i++ { allSpans[i] = test.NewRandomSpan(rnd, allSpans[1:i]) } allSpans[1].SpanData.Parents = []common.SpanId{common.SpanId(allSpans[0].Id)} return allSpans }
func (shd *shard) decodeSpan(sid common.SpanId, buf []byte) (*common.Span, error) { r := bytes.NewBuffer(buf) decoder := gob.NewDecoder(r) data := common.SpanData{} err := decoder.Decode(&data) if err != nil { return nil, err } // Gob encoding translates empty slices to nil. Reverse this so that we're always dealing with // non-nil slices. if data.Parents == nil { data.Parents = []common.SpanId{} } return &common.Span{Id: common.SpanId(sid), SpanData: data}, nil }
func (shd *shard) decodeSpan(sid common.SpanId, buf []byte) (*common.Span, error) { r := bytes.NewBuffer(buf) mh := new(codec.MsgpackHandle) mh.WriteExt = true decoder := codec.NewDecoder(r, mh) data := common.SpanData{} err := decoder.Decode(&data) if err != nil { return nil, err } if data.Parents == nil { data.Parents = []common.SpanId{} } return &common.Span{Id: common.SpanId(sid), SpanData: data}, nil }
func (shd *shard) FindChildren(sid common.SpanId, childIds []common.SpanId, lim int32) ([]common.SpanId, int32, error) { searchKey := append([]byte{PARENT_ID_INDEX_PREFIX}, sid.Val()...) iter := shd.ldb.NewIterator(shd.store.readOpts) defer iter.Close() iter.Seek(searchKey) for { if !iter.Valid() { break } if lim == 0 { break } key := iter.Key() if !bytes.HasPrefix(key, searchKey) { break } id := common.SpanId(key[17:]) childIds = append(childIds, id) lim-- iter.Next() } return childIds, lim, 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] 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 }