Repository: incubator-htrace Updated Branches: refs/heads/master 83053c8be -> 56dd48b5a
HTRACE-107: Support for Greater Than operator in htraced Project: http://git-wip-us.apache.org/repos/asf/incubator-htrace/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-htrace/commit/2314ac28 Tree: http://git-wip-us.apache.org/repos/asf/incubator-htrace/tree/2314ac28 Diff: http://git-wip-us.apache.org/repos/asf/incubator-htrace/diff/2314ac28 Branch: refs/heads/master Commit: 2314ac28450404ace0b70783ea4e2985f14e09b1 Parents: 83053c8 Author: Abraham Elmahrek <[email protected]> Authored: Thu Feb 12 18:44:45 2015 -0800 Committer: Abraham Elmahrek <[email protected]> Committed: Thu Feb 12 18:44:45 2015 -0800 ---------------------------------------------------------------------- .../go/src/org/apache/htrace/common/query.go | 1 + .../src/org/apache/htrace/htraced/datastore.go | 33 +++++++++++--- .../org/apache/htrace/htraced/datastore_test.go | 45 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/2314ac28/htrace-core/src/go/src/org/apache/htrace/common/query.go ---------------------------------------------------------------------- diff --git a/htrace-core/src/go/src/org/apache/htrace/common/query.go b/htrace-core/src/go/src/org/apache/htrace/common/query.go index 0c909a1..b59cbbe 100644 --- a/htrace-core/src/go/src/org/apache/htrace/common/query.go +++ b/htrace-core/src/go/src/org/apache/htrace/common/query.go @@ -51,6 +51,7 @@ const ( EQUALS Op = "eq" LESS_THAN_OR_EQUALS Op = "le" GREATER_THAN_OR_EQUALS Op = "ge" + GREATER_THAN Op = "gt" ) func (op Op) IsDescending() bool { http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/2314ac28/htrace-core/src/go/src/org/apache/htrace/htraced/datastore.go ---------------------------------------------------------------------- diff --git a/htrace-core/src/go/src/org/apache/htrace/htraced/datastore.go b/htrace-core/src/go/src/org/apache/htrace/htraced/datastore.go index 523b7ab..a4233f4 100644 --- a/htrace-core/src/go/src/org/apache/htrace/htraced/datastore.go +++ b/htrace-core/src/go/src/org/apache/htrace/htraced/datastore.go @@ -520,7 +520,8 @@ func loadPredicateData(pred *common.Predicate) (*predicateData, error) { // Validate the predicate operation. switch pred.Op { - case common.EQUALS, common.LESS_THAN_OR_EQUALS, common.GREATER_THAN_OR_EQUALS: + case common.EQUALS, common.LESS_THAN_OR_EQUALS, + common.GREATER_THAN_OR_EQUALS, common.GREATER_THAN: break case common.CONTAINS: if p.fieldIsNumeric() { @@ -618,6 +619,8 @@ func (pred *predicateData) satisfiedBy(span *common.Span) bool { return intVal <= pred.intKey case common.GREATER_THAN_OR_EQUALS: return intVal >= pred.intKey + case common.GREATER_THAN: + return intVal > pred.intKey default: panic(fmt.Sprintf("unknown Op type %s should have been caught "+ "during normalization", pred.Op)) @@ -632,6 +635,8 @@ func (pred *predicateData) satisfiedBy(span *common.Span) bool { return strVal <= pred.strKey case common.GREATER_THAN_OR_EQUALS: return strVal >= pred.strKey + case common.GREATER_THAN: + return strVal > pred.strKey default: panic(fmt.Sprintf("unknown Op type %s should have been caught "+ "during normalization", pred.Op)) @@ -679,6 +684,25 @@ type source struct { keyPrefix byte } +// Return true if this operation may require skipping the first result we get back from leveldb. +func mayRequireOneSkip(op common.Op) bool { + switch op { + // When dealing with descending predicates, the first span we read might not satisfy + // the predicate, even though subsequent ones will. This is because the iter.Seek() + // function "moves the iterator the position of the key given or, if the key doesn't + // exist, the next key that does exist in the database." So if we're on that "next + // key" it will not satisfy the predicate, but the keys previous to it might. + case common.LESS_THAN_OR_EQUALS: + return true + // iter.Seek basically takes us to the key which is "greater than or equal to" some + // value. Since we want greater than (not greater than or equal to) we may have to + // skip the first key. + case common.GREATER_THAN: + return true + } + return false +} + // Fill in the entry in the 'next' array for a specific shard. func (src *source) populateNextFromShard(shardIdx int) { lg := src.store.lg @@ -737,12 +761,7 @@ func (src *source) populateNextFromShard(shardIdx int) { } else { lg.Debugf("Span %016x from shard %d does not satisfy the predicate.\n", sid, shardIdx) - if src.numRead[shardIdx] <= 1 && src.pred.Op.IsDescending() { - // When dealing with descending predicates, the first span we read might not satisfy - // the predicate, even though subsequent ones will. This is because the iter.Seek() - // function "moves the iterator the position of the key given or, if the key doesn't - // exist, the next key that does exist in the database." So if we're on that "next - // key" it will not satisfy the predicate, but the keys previous to it might. + if src.numRead[shardIdx] <= 1 && mayRequireOneSkip(src.pred.Op) { continue } // This and subsequent entries don't satisfy predicate http://git-wip-us.apache.org/repos/asf/incubator-htrace/blob/2314ac28/htrace-core/src/go/src/org/apache/htrace/htraced/datastore_test.go ---------------------------------------------------------------------- diff --git a/htrace-core/src/go/src/org/apache/htrace/htraced/datastore_test.go b/htrace-core/src/go/src/org/apache/htrace/htraced/datastore_test.go index 3330723..fd4bfb1 100644 --- a/htrace-core/src/go/src/org/apache/htrace/htraced/datastore_test.go +++ b/htrace-core/src/go/src/org/apache/htrace/htraced/datastore_test.go @@ -271,6 +271,51 @@ func TestQueries3(t *testing.T) { }, []common.Span{SIMPLE_TEST_SPANS[1], SIMPLE_TEST_SPANS[0]}) } +func TestQueries4(t *testing.T) { + t.Parallel() + htraceBld := &MiniHTracedBuilder{Name: "TestQueries4", + WrittenSpans: make(chan *common.Span, 100)} + ht, err := htraceBld.Build() + if err != nil { + panic(err) + } + defer ht.Close() + createSpans(SIMPLE_TEST_SPANS, ht.Store) + if ht.Store.GetStatistics().NumSpansWritten < uint64(len(SIMPLE_TEST_SPANS)) { + t.Fatal() + } + testQuery(t, ht, &common.Query{ + Predicates: []common.Predicate{ + common.Predicate{ + Op: common.GREATER_THAN, + Field: common.BEGIN_TIME, + Val: "125", + }, + }, + Lim: 5, + }, []common.Span{SIMPLE_TEST_SPANS[2]}) + testQuery(t, ht, &common.Query{ + Predicates: []common.Predicate{ + common.Predicate{ + Op: common.GREATER_THAN_OR_EQUALS, + Field: common.DESCRIPTION, + Val: "openFd", + }, + }, + Lim: 2, + }, []common.Span{SIMPLE_TEST_SPANS[1], SIMPLE_TEST_SPANS[2]}) + testQuery(t, ht, &common.Query{ + Predicates: []common.Predicate{ + common.Predicate{ + Op: common.GREATER_THAN, + Field: common.DESCRIPTION, + Val: "openFd", + }, + }, + Lim: 2, + }, []common.Span{SIMPLE_TEST_SPANS[2]}) +} + func BenchmarkDatastoreWrites(b *testing.B) { htraceBld := &MiniHTracedBuilder{Name: "BenchmarkDatastoreWrites", WrittenSpans: make(chan *common.Span, b.N)}
