func (p preparer) Prepare(n string, f FixtureFactory) (t test.TemporaryDirectory) { t = test.NewTemporaryDirectory(n, p.tester) persistence, err := leveldb.NewLevelDBPersistence(leveldb.LevelDBOptions{ Path: t.Path(), CacheSizeBytes: cacheCapacity, }) if err != nil { defer t.Close() p.tester.Fatal(err) } defer persistence.Close() for f.HasNext() { key, value := f.Next() switch v := value.(type) { case proto.Message: err = persistence.Put(key, v) case []byte: err = persistence.PutRaw(key, v) default: panic("illegal value type") } if err != nil { defer t.Close() p.tester.Fatal(err) } } return }
// NewLevelDBFingerprintMetricIndex returns a LevelDBFingerprintMetricIndex // object ready to use. func NewLevelDBFingerprintMetricIndex(o leveldb.LevelDBOptions) (*LevelDBFingerprintMetricIndex, error) { s, err := leveldb.NewLevelDBPersistence(o) if err != nil { return nil, err } return &LevelDBFingerprintMetricIndex{ LevelDBPersistence: s, }, nil }
// NewLevelDBMetricMembershipIndex returns a LevelDBMetricMembershipIndex object // ready to use. func NewLevelDBMetricMembershipIndex(o leveldb.LevelDBOptions) (*LevelDBMetricMembershipIndex, error) { s, err := leveldb.NewLevelDBPersistence(o) if err != nil { return nil, err } return &LevelDBMetricMembershipIndex{ LevelDBPersistence: s, }, nil }
// NewLevelDBLabelNameLabelValuesIndex returns a LevelDBLabelNameLabelValuesIndex // ready to use. func NewLevelDBLabelNameLabelValuesIndex(o leveldb.LevelDBOptions) (*LevelDBLabelNameLabelValuesIndex, error) { s, err := leveldb.NewLevelDBPersistence(o) if err != nil { return nil, err } return &LevelDBLabelNameLabelValuesIndex{ LevelDBPersistence: s, }, nil }
// NewLevelDBCurationRemarker returns a LevelDBCurationRemarker ready to use. func NewLevelDBCurationRemarker(o leveldb.LevelDBOptions) (*LevelDBCurationRemarker, error) { s, err := leveldb.NewLevelDBPersistence(o) if err != nil { return nil, err } return &LevelDBCurationRemarker{ LevelDBPersistence: s, }, nil }
func NewLevelDBMembershipIndex(storageRoot string, cacheCapacity, bitsPerBloomFilterEncoded int) (i *LevelDBMembershipIndex, err error) { leveldbPersistence, err := leveldb.NewLevelDBPersistence(storageRoot, cacheCapacity, bitsPerBloomFilterEncoded) if err != nil { return } i = &LevelDBMembershipIndex{ persistence: leveldbPersistence, } return }
func (p preparer) Prepare(n string, f FixtureFactory) (t test.TemporaryDirectory) { t = test.NewTemporaryDirectory(n, p.tester) persistence, err := leveldb.NewLevelDBPersistence(t.Path(), cacheCapacity, bitsPerBloomFilterEncoded) if err != nil { defer t.Close() p.tester.Fatal(err) } defer persistence.Close() for f.HasNext() { key, value := f.Next() err = persistence.Put(key, value) if err != nil { defer t.Close() p.tester.Fatal(err) } } return }
func TestCuratorCompactionProcessor(t *testing.T) { scenarios := []struct { in in out out }{ { in: in{ processor: NewCompactionProcessor(&CompactionProcessorOptions{ MinimumGroupSize: 5, MaximumMutationPoolBatch: 15, }), ignoreYoungerThan: 1 * time.Hour, groupSize: 5, curationStates: fixture.Pairs{ curationState{ fingerprint: "0001-A-1-Z", ignoreYoungerThan: 1 * time.Hour, lastCurated: testInstant.Add(-1 * 30 * time.Minute), processor: NewCompactionProcessor(&CompactionProcessorOptions{ MinimumGroupSize: 5, MaximumMutationPoolBatch: 15, }), }, curationState{ fingerprint: "0002-A-2-Z", ignoreYoungerThan: 1 * time.Hour, lastCurated: testInstant.Add(-1 * 90 * time.Minute), processor: NewCompactionProcessor(&CompactionProcessorOptions{ MinimumGroupSize: 5, MaximumMutationPoolBatch: 15, }), }, // This rule should effectively be ignored. curationState{ fingerprint: "0002-A-2-Z", processor: NewCompactionProcessor(&CompactionProcessorOptions{ MinimumGroupSize: 2, MaximumMutationPoolBatch: 15, }), ignoreYoungerThan: 30 * time.Minute, lastCurated: testInstant.Add(-1 * 90 * time.Minute), }, }, watermarkStates: fixture.Pairs{ watermarkState{ fingerprint: "0001-A-1-Z", lastAppended: testInstant.Add(-1 * 15 * time.Minute), }, watermarkState{ fingerprint: "0002-A-2-Z", lastAppended: testInstant.Add(-1 * 15 * time.Minute), }, }, sampleGroups: fixture.Pairs{ sampleGroup{ fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 90 * time.Minute), Value: 0, }, { Timestamp: testInstant.Add(-1 * 85 * time.Minute), Value: 1, }, { Timestamp: testInstant.Add(-1 * 80 * time.Minute), Value: 2, }, { Timestamp: testInstant.Add(-1 * 75 * time.Minute), Value: 3, }, { Timestamp: testInstant.Add(-1 * 70 * time.Minute), Value: 4, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 65 * time.Minute), Value: 0.25, }, { Timestamp: testInstant.Add(-1 * 60 * time.Minute), Value: 1.25, }, { Timestamp: testInstant.Add(-1 * 55 * time.Minute), Value: 2.25, }, { Timestamp: testInstant.Add(-1 * 50 * time.Minute), Value: 3.25, }, { Timestamp: testInstant.Add(-1 * 45 * time.Minute), Value: 4.25, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 40 * time.Minute), Value: 0.50, }, { Timestamp: testInstant.Add(-1 * 35 * time.Minute), Value: 1.50, }, { Timestamp: testInstant.Add(-1 * 30 * time.Minute), Value: 2.50, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 25 * time.Minute), Value: 0.75, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 20 * time.Minute), Value: -2, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 15 * time.Minute), Value: -3, }, }, }, sampleGroup{ // Moved into Block 1 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 90 * time.Minute), Value: 0, }, }, }, sampleGroup{ // Moved into Block 1 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 89 * time.Minute), Value: 1, }, }, }, sampleGroup{ // Moved into Block 1 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 88 * time.Minute), Value: 2, }, }, }, sampleGroup{ // Moved into Block 1 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 87 * time.Minute), Value: 3, }, }, }, sampleGroup{ // Moved into Block 1 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 86 * time.Minute), Value: 4, }, }, }, sampleGroup{ // Moved into Block 2 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 85 * time.Minute), Value: 5, }, }, }, sampleGroup{ // Moved into Block 2 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 84 * time.Minute), Value: 6, }, }, }, sampleGroup{ // Moved into Block 2 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 83 * time.Minute), Value: 7, }, }, }, sampleGroup{ // Moved into Block 2 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 82 * time.Minute), Value: 8, }, }, }, sampleGroup{ // Moved into Block 2 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 81 * time.Minute), Value: 9, }, }, }, sampleGroup{ // Moved into Block 3 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 80 * time.Minute), Value: 10, }, }, }, sampleGroup{ // Moved into Block 3 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 79 * time.Minute), Value: 11, }, }, }, sampleGroup{ // Moved into Block 3 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 78 * time.Minute), Value: 12, }, }, }, sampleGroup{ // Moved into Block 3 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 77 * time.Minute), Value: 13, }, }, }, sampleGroup{ // Moved into Blocks 3 and 4 and 5 fingerprint: "0002-A-2-Z", values: metric.Values{ { // Block 3 Timestamp: testInstant.Add(-1 * 76 * time.Minute), Value: 14, }, { // Block 4 Timestamp: testInstant.Add(-1 * 75 * time.Minute), Value: 15, }, { // Block 4 Timestamp: testInstant.Add(-1 * 74 * time.Minute), Value: 16, }, { // Block 4 Timestamp: testInstant.Add(-1 * 73 * time.Minute), Value: 17, }, { // Block 4 Timestamp: testInstant.Add(-1 * 72 * time.Minute), Value: 18, }, { // Block 4 Timestamp: testInstant.Add(-1 * 71 * time.Minute), Value: 19, }, { // Block 5 Timestamp: testInstant.Add(-1 * 70 * time.Minute), Value: 20, }, }, }, sampleGroup{ // Moved into Block 5 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 69 * time.Minute), Value: 21, }, }, }, sampleGroup{ // Moved into Block 5 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 68 * time.Minute), Value: 22, }, }, }, sampleGroup{ // Moved into Block 5 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 67 * time.Minute), Value: 23, }, }, }, sampleGroup{ // Moved into Block 5 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 66 * time.Minute), Value: 24, }, }, }, sampleGroup{ // Moved into Block 6 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 65 * time.Minute), Value: 25, }, }, }, sampleGroup{ // Moved into Block 6 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 64 * time.Minute), Value: 26, }, }, }, sampleGroup{ // Moved into Block 6 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 63 * time.Minute), Value: 27, }, }, }, sampleGroup{ // Moved into Block 6 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 62 * time.Minute), Value: 28, }, }, }, sampleGroup{ // Moved into Block 6 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 61 * time.Minute), Value: 29, }, }, }, sampleGroup{ // Moved into Block 7 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 60 * time.Minute), Value: 30, }, }, }, }, }, out: out{ curationStates: []curationState{ { fingerprint: "0001-A-1-Z", ignoreYoungerThan: time.Hour, lastCurated: testInstant.Add(-1 * 30 * time.Minute), processor: NewCompactionProcessor(&CompactionProcessorOptions{ MinimumGroupSize: 5, MaximumMutationPoolBatch: 15, }), }, { fingerprint: "0002-A-2-Z", ignoreYoungerThan: 30 * time.Minute, lastCurated: testInstant.Add(-1 * 90 * time.Minute), processor: NewCompactionProcessor(&CompactionProcessorOptions{ MinimumGroupSize: 2, MaximumMutationPoolBatch: 15, }), }, { fingerprint: "0002-A-2-Z", ignoreYoungerThan: time.Hour, lastCurated: testInstant.Add(-1 * 60 * time.Minute), processor: NewCompactionProcessor(&CompactionProcessorOptions{ MinimumGroupSize: 5, MaximumMutationPoolBatch: 15, }), }, }, sampleGroups: []sampleGroup{ { fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 90 * time.Minute), Value: 0, }, { Timestamp: testInstant.Add(-1 * 85 * time.Minute), Value: 1, }, { Timestamp: testInstant.Add(-1 * 80 * time.Minute), Value: 2, }, { Timestamp: testInstant.Add(-1 * 75 * time.Minute), Value: 3, }, { Timestamp: testInstant.Add(-1 * 70 * time.Minute), Value: 4, }, }, }, { fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 65 * time.Minute), Value: 0.25, }, { Timestamp: testInstant.Add(-1 * 60 * time.Minute), Value: 1.25, }, { Timestamp: testInstant.Add(-1 * 55 * time.Minute), Value: 2.25, }, { Timestamp: testInstant.Add(-1 * 50 * time.Minute), Value: 3.25, }, { Timestamp: testInstant.Add(-1 * 45 * time.Minute), Value: 4.25, }, }, }, { fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 40 * time.Minute), Value: 0.50, }, { Timestamp: testInstant.Add(-1 * 35 * time.Minute), Value: 1.50, }, { Timestamp: testInstant.Add(-1 * 30 * time.Minute), Value: 2.50, }, }, }, { fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 25 * time.Minute), Value: 0.75, }, }, }, { fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 20 * time.Minute), Value: -2, }, }, }, { fingerprint: "0001-A-1-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 15 * time.Minute), Value: -3, }, }, }, { // Block 1 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 90 * time.Minute), Value: 0, }, { Timestamp: testInstant.Add(-1 * 89 * time.Minute), Value: 1, }, { Timestamp: testInstant.Add(-1 * 88 * time.Minute), Value: 2, }, { Timestamp: testInstant.Add(-1 * 87 * time.Minute), Value: 3, }, { Timestamp: testInstant.Add(-1 * 86 * time.Minute), Value: 4, }, }, }, { // Block 2 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 85 * time.Minute), Value: 5, }, { Timestamp: testInstant.Add(-1 * 84 * time.Minute), Value: 6, }, { Timestamp: testInstant.Add(-1 * 83 * time.Minute), Value: 7, }, { Timestamp: testInstant.Add(-1 * 82 * time.Minute), Value: 8, }, { Timestamp: testInstant.Add(-1 * 81 * time.Minute), Value: 9, }, }, }, { // Block 3 fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 80 * time.Minute), Value: 10, }, { Timestamp: testInstant.Add(-1 * 79 * time.Minute), Value: 11, }, { Timestamp: testInstant.Add(-1 * 78 * time.Minute), Value: 12, }, { Timestamp: testInstant.Add(-1 * 77 * time.Minute), Value: 13, }, { Timestamp: testInstant.Add(-1 * 76 * time.Minute), Value: 14, }, }, }, { fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 75 * time.Minute), Value: 15, }, { Timestamp: testInstant.Add(-1 * 74 * time.Minute), Value: 16, }, { Timestamp: testInstant.Add(-1 * 73 * time.Minute), Value: 17, }, { Timestamp: testInstant.Add(-1 * 72 * time.Minute), Value: 18, }, { Timestamp: testInstant.Add(-1 * 71 * time.Minute), Value: 19, }, }, }, { fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 70 * time.Minute), Value: 20, }, { Timestamp: testInstant.Add(-1 * 69 * time.Minute), Value: 21, }, { Timestamp: testInstant.Add(-1 * 68 * time.Minute), Value: 22, }, { Timestamp: testInstant.Add(-1 * 67 * time.Minute), Value: 23, }, { Timestamp: testInstant.Add(-1 * 66 * time.Minute), Value: 24, }, }, }, { fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 65 * time.Minute), Value: 25, }, { Timestamp: testInstant.Add(-1 * 64 * time.Minute), Value: 26, }, { Timestamp: testInstant.Add(-1 * 63 * time.Minute), Value: 27, }, { Timestamp: testInstant.Add(-1 * 62 * time.Minute), Value: 28, }, { Timestamp: testInstant.Add(-1 * 61 * time.Minute), Value: 29, }, }, }, { fingerprint: "0002-A-2-Z", values: metric.Values{ { Timestamp: testInstant.Add(-1 * 60 * time.Minute), Value: 30, }, }, }, }, }, }, } for i, scenario := range scenarios { curatorDirectory := fixture.NewPreparer(t).Prepare("curator", fixture.NewCassetteFactory(scenario.in.curationStates)) defer curatorDirectory.Close() watermarkDirectory := fixture.NewPreparer(t).Prepare("watermark", fixture.NewCassetteFactory(scenario.in.watermarkStates)) defer watermarkDirectory.Close() sampleDirectory := fixture.NewPreparer(t).Prepare("sample", fixture.NewCassetteFactory(scenario.in.sampleGroups)) defer sampleDirectory.Close() curatorStates, err := NewLevelDBCurationRemarker( leveldb.LevelDBOptions{ Path: curatorDirectory.Path(), }, ) if err != nil { t.Fatal(err) } watermarkStates, err := NewLevelDBHighWatermarker( leveldb.LevelDBOptions{ Path: watermarkDirectory.Path(), }, ) if err != nil { t.Fatal(err) } defer watermarkStates.Close() samples, err := leveldb.NewLevelDBPersistence(leveldb.LevelDBOptions{ Path: sampleDirectory.Path(), }) if err != nil { t.Fatal(err) } defer samples.Close() updates := &noopUpdater{} stop := make(chan struct{}) defer close(stop) c := NewCurator(&CuratorOptions{ Stop: stop, }) defer c.Close() err = c.Run(scenario.in.ignoreYoungerThan, testInstant, scenario.in.processor, curatorStates, samples, watermarkStates, updates) if err != nil { t.Fatal(err) } iterator, err := curatorStates.LevelDBPersistence.NewIterator(true) if err != nil { t.Fatal(err) } defer iterator.Close() for j, expected := range scenario.out.curationStates { switch j { case 0: if !iterator.SeekToFirst() { t.Fatalf("%d.%d. could not seek to beginning.", i, j) } default: if !iterator.Next() { t.Fatalf("%d.%d. could not seek to next.", i, j) } } curationKeyDto := &dto.CurationKey{} err = iterator.Key(curationKeyDto) if err != nil { t.Fatalf("%d.%d. could not unmarshal: %s", i, j, err) } actualKey := &curationKey{} actualKey.load(curationKeyDto) actualValue, present, err := curatorStates.Get(actualKey) if !present { t.Fatalf("%d.%d. could not get key-value pair %s", i, j, actualKey) } if err != nil { t.Fatalf("%d.%d. could not get key-value pair %s", i, j, err) } expectedFingerprint := &clientmodel.Fingerprint{} expectedFingerprint.LoadFromString(expected.fingerprint) expectedKey := &curationKey{ Fingerprint: expectedFingerprint, IgnoreYoungerThan: expected.ignoreYoungerThan, ProcessorMessageRaw: expected.processor.Signature(), ProcessorMessageTypeName: expected.processor.Name(), } if !actualKey.Equal(expectedKey) { t.Fatalf("%d.%d. expected %s, got %s", i, j, expectedKey, actualKey) } if !actualValue.Equal(expected.lastCurated) { t.Fatalf("%d.%d. expected %s, got %s", i, j, expected.lastCurated, actualValue) } } iterator, err = samples.NewIterator(true) if err != nil { t.Fatal(err) } defer iterator.Close() for j, expected := range scenario.out.sampleGroups { switch j { case 0: if !iterator.SeekToFirst() { t.Fatalf("%d.%d. could not seek to beginning.", i, j) } default: if !iterator.Next() { t.Fatalf("%d.%d. could not seek to next, expected %s", i, j, expected) } } sampleKey, err := extractSampleKey(iterator) if err != nil { t.Fatalf("%d.%d. error %s", i, j, err) } sampleValues := unmarshalValues(iterator.RawValue(), nil) expectedFingerprint := &clientmodel.Fingerprint{} expectedFingerprint.LoadFromString(expected.fingerprint) if !expectedFingerprint.Equal(sampleKey.Fingerprint) { t.Fatalf("%d.%d. expected fingerprint %s, got %s", i, j, expected.fingerprint, sampleKey.Fingerprint) } if int(sampleKey.SampleCount) != len(expected.values) { t.Fatalf("%d.%d. expected %d values, got %d", i, j, len(expected.values), sampleKey.SampleCount) } if len(sampleValues) != len(expected.values) { t.Fatalf("%d.%d. expected %d values, got %d", i, j, len(expected.values), len(sampleValues)) } if !sampleKey.FirstTimestamp.Equal(expected.values[0].Timestamp) { t.Fatalf("%d.%d. expected %s, got %s", i, j, expected.values[0].Timestamp, sampleKey.FirstTimestamp) } for k, actualValue := range sampleValues { if expected.values[k].Value != actualValue.Value { t.Fatalf("%d.%d.%d. expected %v, got %v", i, j, k, expected.values[k].Value, actualValue.Value) } if !expected.values[k].Timestamp.Equal(actualValue.Timestamp) { t.Fatalf("%d.%d.%d. expected %s, got %s", i, j, k, expected.values[k].Timestamp, actualValue.Timestamp) } } if !sampleKey.LastTimestamp.Equal(expected.values[len(expected.values)-1].Timestamp) { fmt.Println("last", sampleValues[len(expected.values)-1].Value, expected.values[len(expected.values)-1].Value) t.Errorf("%d.%d. expected %s, got %s", i, j, expected.values[len(expected.values)-1].Timestamp, sampleKey.LastTimestamp) } } } }
func NewLevelDBMetricPersistence(baseDirectory string) (persistence *LevelDBMetricPersistence, err error) { errorChannel := make(chan error, 6) emission := &LevelDBMetricPersistence{} var subsystemOpeners = []struct { name string opener leveldbOpener }{ { "Label Names and Value Pairs by Fingerprint", func() { var err error emission.fingerprintToMetrics, err = leveldb.NewLevelDBPersistence(baseDirectory+"/label_name_and_value_pairs_by_fingerprint", *fingerprintsToLabelPairCacheSize, 10) errorChannel <- err }, }, { "Samples by Fingerprint", func() { var err error emission.metricSamples, err = leveldb.NewLevelDBPersistence(baseDirectory+"/samples_by_fingerprint", *samplesByFingerprintCacheSize, 10) errorChannel <- err }, }, { "High Watermarks by Fingerprint", func() { var err error emission.metricHighWatermarks, err = leveldb.NewLevelDBPersistence(baseDirectory+"/high_watermarks_by_fingerprint", *highWatermarkCacheSize, 10) errorChannel <- err }, }, { "Fingerprints by Label Name", func() { var err error emission.labelNameToFingerprints, err = leveldb.NewLevelDBPersistence(baseDirectory+"/fingerprints_by_label_name", *labelNameToFingerprintsCacheSize, 10) errorChannel <- err }, }, { "Fingerprints by Label Name and Value Pair", func() { var err error emission.labelSetToFingerprints, err = leveldb.NewLevelDBPersistence(baseDirectory+"/fingerprints_by_label_name_and_value_pair", *labelPairToFingerprintsCacheSize, 10) errorChannel <- err }, }, { "Metric Membership Index", func() { var err error emission.metricMembershipIndex, err = index.NewLevelDBMembershipIndex(baseDirectory+"/metric_membership_index", *metricMembershipIndexCacheSize, 10) errorChannel <- err }, }, } for _, subsystem := range subsystemOpeners { opener := subsystem.opener go opener() } for i := 0; i < cap(errorChannel); i++ { err = <-errorChannel if err != nil { log.Printf("Could not open a LevelDBPersistence storage container: %q\n", err) return } } persistence = emission return }
func TestCurator(t *testing.T) { var ( scenarios = []struct { in in }{ { in: in{ recencyThreshold: 1 * time.Hour, groupSize: 5, curationStates: fixture.Pairs{ curationState{ fingerprint: "0001-A-1-Z", groupSize: 5, recencyThreshold: 1 * time.Hour, lastCurated: testInstant.Add(-1 * 30 * time.Minute), }, curationState{ fingerprint: "0002-A-2-Z", groupSize: 5, recencyThreshold: 1 * time.Hour, lastCurated: testInstant.Add(-1 * 90 * time.Minute), }, // This rule should effectively be ignored. curationState{ fingerprint: "0002-A-2-Z", groupSize: 2, recencyThreshold: 30 * time.Minute, lastCurated: testInstant.Add(-1 * 90 * time.Minute), }, }, watermarkStates: fixture.Pairs{ watermarkState{ fingerprint: "0001-A-1-Z", lastAppended: testInstant.Add(-1 * 15 * time.Minute), }, watermarkState{ fingerprint: "0002-A-2-Z", lastAppended: testInstant.Add(-1 * 15 * time.Minute), }, }, sampleGroups: fixture.Pairs{ sampleGroup{ fingerprint: "0001-A-1-Z", values: []sample{ { time: testInstant.Add(-1 * 90 * time.Minute), value: 0, }, { time: testInstant.Add(-1 * 85 * time.Minute), value: 1, }, { time: testInstant.Add(-1 * 80 * time.Minute), value: 2, }, { time: testInstant.Add(-1 * 75 * time.Minute), value: 3, }, { time: testInstant.Add(-1 * 70 * time.Minute), value: 4, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: []sample{ { time: testInstant.Add(-1 * 65 * time.Minute), value: 0, }, { time: testInstant.Add(-1 * 60 * time.Minute), value: 1, }, { time: testInstant.Add(-1 * 55 * time.Minute), value: 2, }, { time: testInstant.Add(-1 * 50 * time.Minute), value: 3, }, { time: testInstant.Add(-1 * 45 * time.Minute), value: 4, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: []sample{ { time: testInstant.Add(-1 * 40 * time.Minute), value: 0, }, { time: testInstant.Add(-1 * 35 * time.Minute), value: 1, }, { time: testInstant.Add(-1 * 30 * time.Minute), value: 2, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: []sample{ { time: testInstant.Add(-1 * 25 * time.Minute), value: 0, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: []sample{ { time: testInstant.Add(-1 * 35 * time.Minute), value: 1, }, }, }, sampleGroup{ fingerprint: "0001-A-1-Z", values: []sample{ { time: testInstant.Add(-1 * 30 * time.Minute), value: 2, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 90 * time.Minute), value: 0, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 89 * time.Minute), value: 1, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 88 * time.Minute), value: 2, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 87 * time.Minute), value: 3, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 86 * time.Minute), value: 4, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 85 * time.Minute), value: 5, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 84 * time.Minute), value: 6, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 83 * time.Minute), value: 7, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 82 * time.Minute), value: 8, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 81 * time.Minute), value: 9, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 80 * time.Minute), value: 10, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 79 * time.Minute), value: 11, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 78 * time.Minute), value: 12, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 77 * time.Minute), value: 13, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 76 * time.Minute), value: 14, }, { time: testInstant.Add(-1 * 75 * time.Minute), value: 15, }, { time: testInstant.Add(-1 * 74 * time.Minute), value: 16, }, { time: testInstant.Add(-1 * 73 * time.Minute), value: 17, }, { time: testInstant.Add(-1 * 72 * time.Minute), value: 18, }, { time: testInstant.Add(-1 * 71 * time.Minute), value: 19, }, { time: testInstant.Add(-1 * 70 * time.Minute), value: 20, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 69 * time.Minute), value: 21, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 68 * time.Minute), value: 22, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 67 * time.Minute), value: 23, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 66 * time.Minute), value: 24, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 65 * time.Minute), value: 25, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 64 * time.Minute), value: 26, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 63 * time.Minute), value: 27, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 62 * time.Minute), value: 28, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 61 * time.Minute), value: 29, }, }, }, sampleGroup{ fingerprint: "0002-A-2-Z", values: []sample{ { time: testInstant.Add(-1 * 60 * time.Minute), value: 30, }, }, }, }, }, }, } ) for _, scenario := range scenarios { curatorDirectory := fixture.NewPreparer(t).Prepare("curator", fixture.NewCassetteFactory(scenario.in.curationStates)) defer curatorDirectory.Close() watermarkDirectory := fixture.NewPreparer(t).Prepare("watermark", fixture.NewCassetteFactory(scenario.in.watermarkStates)) defer watermarkDirectory.Close() sampleDirectory := fixture.NewPreparer(t).Prepare("sample", fixture.NewCassetteFactory(scenario.in.sampleGroups)) defer sampleDirectory.Close() curatorStates, err := leveldb.NewLevelDBPersistence(curatorDirectory.Path(), 0, 0) if err != nil { t.Fatal(err) } defer curatorStates.Close() watermarkStates, err := leveldb.NewLevelDBPersistence(watermarkDirectory.Path(), 0, 0) if err != nil { t.Fatal(err) } defer watermarkStates.Close() samples, err := leveldb.NewLevelDBPersistence(sampleDirectory.Path(), 0, 0) if err != nil { t.Fatal(err) } defer samples.Close() c := newCurator(scenario.in.recencyThreshold, scenario.in.groupSize, curatorStates, samples, watermarkStates) c.run(testInstant) } }