github.com/m3db/m3@v1.5.0/src/dbnode/integration/commitlog_bootstrap_helpers.go (about) 1 // +build integration 2 3 // Copyright (c) 2017 Uber Technologies, Inc. 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 // THE SOFTWARE. 22 23 package integration 24 25 import ( 26 "math/rand" 27 "testing" 28 "time" 29 30 "github.com/m3db/m3/src/dbnode/integration/generate" 31 "github.com/m3db/m3/src/dbnode/namespace" 32 "github.com/m3db/m3/src/dbnode/persist/fs/commitlog" 33 "github.com/m3db/m3/src/dbnode/ts" 34 "github.com/m3db/m3/src/x/context" 35 "github.com/m3db/m3/src/x/ident" 36 xtime "github.com/m3db/m3/src/x/time" 37 38 "github.com/stretchr/testify/require" 39 ) 40 41 var ( 42 defaultIntegrationTestFlushInterval = 100 * time.Millisecond 43 defaultDerrangementPercent = 0.20 44 ) 45 46 type commitLogSeriesState struct { 47 uniqueIndex uint64 48 tags ident.Tags 49 } 50 51 func newCommitLogSeriesStates( 52 timeBlocks generate.SeriesBlocksByStart, 53 ) map[string]*commitLogSeriesState { 54 var idx uint64 55 lookup := make(map[string]*commitLogSeriesState) 56 for _, blks := range timeBlocks { 57 for _, blk := range blks { 58 id := blk.ID.String() 59 if _, ok := lookup[id]; !ok { 60 lookup[id] = &commitLogSeriesState{ 61 uniqueIndex: idx, 62 tags: blk.Tags, 63 } 64 idx++ 65 } 66 } 67 } 68 return lookup 69 } 70 71 var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 72 73 func randStringRunes(n int) string { 74 b := make([]rune, n) 75 for i := range b { 76 b[i] = letterRunes[rand.Intn(len(letterRunes))] 77 } 78 return string(b) 79 } 80 81 func generateSeriesMaps( 82 numBlocks int, updateConfig generate.UpdateBlockConfig, starts ...xtime.UnixNano, 83 ) generate.SeriesBlocksByStart { 84 blockConfig := []generate.BlockConfig{} 85 for i := 0; i < numBlocks; i++ { 86 name := []string{} 87 for j := 0; j < rand.Intn(10)+1; j++ { 88 name = append(name, randStringRunes(100)) 89 } 90 91 start := starts[rand.Intn(len(starts))] 92 blockConfig = append(blockConfig, generate.BlockConfig{ 93 IDs: name, 94 NumPoints: rand.Intn(100) + 1, 95 Start: start, 96 }) 97 } 98 if updateConfig != nil { 99 updateConfig(blockConfig) 100 } 101 return generate.BlocksByStart(blockConfig) 102 } 103 104 func writeCommitLogData( 105 t *testing.T, 106 s TestSetup, 107 opts commitlog.Options, 108 data generate.SeriesBlocksByStart, 109 namespace namespace.Metadata, 110 genSnapshots bool, 111 ) int { 112 return writeCommitLogDataBase(t, s, opts, data, namespace, nil, nil) 113 } 114 115 func writeCommitLogDataSpecifiedTS( 116 t *testing.T, 117 s TestSetup, 118 opts commitlog.Options, 119 data generate.SeriesBlocksByStart, 120 namespace namespace.Metadata, 121 ts xtime.UnixNano, 122 genSnapshots bool, 123 ) int { 124 return writeCommitLogDataBase(t, s, opts, data, namespace, &ts, nil) 125 } 126 127 func writeCommitLogDataWithPredicate( 128 t *testing.T, 129 s TestSetup, 130 opts commitlog.Options, 131 data generate.SeriesBlocksByStart, 132 namespace namespace.Metadata, 133 pred generate.WriteDatapointPredicate, 134 ) int { 135 return writeCommitLogDataBase(t, s, opts, data, namespace, nil, pred) 136 } 137 138 // returns the number of data points written to the commit log 139 func writeCommitLogDataBase( 140 t *testing.T, 141 s TestSetup, 142 opts commitlog.Options, 143 data generate.SeriesBlocksByStart, 144 namespace namespace.Metadata, 145 specifiedTS *xtime.UnixNano, 146 pred generate.WriteDatapointPredicate, 147 ) int { 148 if pred == nil { 149 pred = generate.WriteAllPredicate 150 } 151 152 // ensure commit log is flushing frequently. 153 require.Equal( 154 t, defaultIntegrationTestFlushInterval, opts.FlushInterval()) 155 156 var ( 157 seriesLookup = newCommitLogSeriesStates(data) 158 shardSet = s.ShardSet() 159 tagEncoderPool = opts.FilesystemOptions().TagEncoderPool() 160 tagSliceIter = ident.NewTagsIterator(ident.Tags{}) 161 writes int 162 ) 163 164 // Write out commit log data. 165 for currTs, blk := range data { 166 if specifiedTS != nil { 167 s.SetNowFn(*specifiedTS) 168 } else { 169 s.SetNowFn(currTs) 170 } 171 ctx := context.NewBackground() 172 defer ctx.Close() 173 174 m := map[xtime.UnixNano]generate.SeriesBlock{ 175 currTs: blk, 176 } 177 178 points := generate. 179 ToPointsByTime(m). 180 Dearrange(defaultDerrangementPercent) 181 182 // create new commit log. 183 commitLog, err := commitlog.NewCommitLog(opts) 184 require.NoError(t, err) 185 require.NoError(t, commitLog.Open()) 186 187 // write points. 188 for _, point := range points { 189 series, ok := seriesLookup[point.ID.String()] 190 require.True(t, ok) 191 192 tagSliceIter.Reset(series.tags) 193 194 tagEncoder := tagEncoderPool.Get() 195 err := tagEncoder.Encode(tagSliceIter) 196 require.NoError(t, err) 197 198 encodedTagsChecked, ok := tagEncoder.Data() 199 require.True(t, ok) 200 201 cID := ts.Series{ 202 Namespace: namespace.ID(), 203 Shard: shardSet.Lookup(point.ID), 204 ID: point.ID, 205 EncodedTags: ts.EncodedTags(encodedTagsChecked.Bytes()), 206 UniqueIndex: series.uniqueIndex, 207 } 208 if pred(point.Value) { 209 require.NoError(t, commitLog.Write(ctx, cID, point.Value.Datapoint, xtime.Second, point.Value.Annotation)) 210 writes++ 211 } 212 } 213 214 // ensure writes finished. 215 require.NoError(t, commitLog.Close()) 216 } 217 return writes 218 } 219 220 func writeSnapshotsWithPredicate( 221 t *testing.T, 222 s TestSetup, 223 opts commitlog.Options, 224 data generate.SeriesBlocksByStart, 225 volume int, 226 namespace namespace.Metadata, 227 specifiedTS *time.Time, 228 pred generate.WriteDatapointPredicate, 229 snapshotInterval time.Duration, 230 ) { 231 // Write out snapshots 232 err := writeTestSnapshotsToDiskWithPredicate( 233 namespace, s, data, volume, pred, snapshotInterval) 234 require.NoError(t, err) 235 }