@@ -17,7 +17,7 @@ func TestExecCompactionLessFilesThanExpected(t *testing.T) {
17
17
defer cleanDatabaseFolder (t , db )
18
18
defer closeDatabase (t , db )
19
19
20
- db .compactionThreshold = 1
20
+ db .compactionFileThreshold = 1
21
21
db .sstableManager .addReader (& MockSSTableReader {
22
22
metadata : & proto.MetaData {NumRecords : 10 , TotalBytes : 100 },
23
23
path : "1" ,
@@ -34,7 +34,7 @@ func TestExecCompactionSameContent(t *testing.T) {
34
34
// we'll close the database to mock some internals directly, yes it's very hacky
35
35
closeDatabase (t , db )
36
36
db .closed = false
37
- db .compactionThreshold = 1
37
+ db .compactionFileThreshold = 1
38
38
39
39
writeSSTableInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 42 ))
40
40
writeSSTableInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 43 ))
@@ -53,41 +53,12 @@ func TestExecCompactionSameContent(t *testing.T) {
53
53
assert .Nil (t , db .sstableManager .currentReader .Close ())
54
54
}
55
55
56
- func writeSSTableWithDataInDatabaseFolder (t * testing.T , db * DB , p string ) {
57
- fakeTablePath := filepath .Join (db .basePath , p )
58
- assert .Nil (t , os .MkdirAll (fakeTablePath , 0700 ))
59
- mStore := memstore .NewMemStore ()
60
- for i := 0 ; i < 1000 ; i ++ {
61
- assert .Nil (t , mStore .Add ([]byte (fmt .Sprintf ("%d" , i )), []byte (fmt .Sprintf ("%d" , i ))))
62
- }
63
- assert .Nil (t , mStore .Flush (
64
- sstables .WriteBasePath (fakeTablePath ),
65
- sstables .WithKeyComparator (db .cmp ),
66
- ))
67
- }
68
-
69
- func writeSSTableWithTombstoneInDatabaseFolder (t * testing.T , db * DB , p string ) {
70
- fakeTablePath := filepath .Join (db .basePath , p )
71
- assert .Nil (t , os .MkdirAll (fakeTablePath , 0700 ))
72
- mStore := memstore .NewMemStore ()
73
-
74
- // delete all key between 500 and 800
75
- for i := 500 ; i < 800 ; i ++ {
76
- assert .Nil (t , mStore .Tombstone ([]byte (fmt .Sprintf ("%d" , i ))))
77
- }
78
- assert .Nil (t , mStore .FlushWithTombstones (
79
- sstables .WriteBasePath (fakeTablePath ),
80
- sstables .WithKeyComparator (db .cmp ),
81
- ))
82
- }
83
-
84
56
func TestExecCompactionWithTombstone (t * testing.T ) {
85
57
db := newOpenedSimpleDB (t , "simpledb_compactionSameContent" )
86
58
defer cleanDatabaseFolder (t , db )
87
- // we'll close the database to mock some internals directly, yes it's very hacky
88
59
closeDatabase (t , db )
89
60
db .closed = false
90
- db .compactionThreshold = 0
61
+ db .compactionFileThreshold = 0
91
62
92
63
writeSSTableWithDataInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 42 ))
93
64
// only one SStable with holes should shrink
@@ -100,7 +71,7 @@ func TestExecCompactionWithTombstone(t *testing.T) {
100
71
assert .Nil (t , err )
101
72
assert .Equal (t , "sstable_000000000000042" , compactionMeta .ReplacementPath )
102
73
assert .Equal (t , []string {"sstable_000000000000042" , "sstable_000000000000043" }, compactionMeta .SstablePaths )
103
- fmt . Print ( compactionMeta )
74
+
104
75
err = db .sstableManager .reflectCompactionResult (compactionMeta )
105
76
assert .NoError (t , err )
106
77
v , err := db .Get ("512" )
@@ -112,16 +83,15 @@ func TestExecCompactionWithTombstone(t *testing.T) {
112
83
// check size of compacted sstable
113
84
assert .Equal (t , 700 , int (db .sstableManager .currentSSTable ().MetaData ().NumRecords ))
114
85
}
115
- func TestExecCompactionWithTombstoneRewriten (t * testing.T ) {
86
+ func TestExecCompactionWithTombstoneRewritten (t * testing.T ) {
116
87
db := newOpenedSimpleDB (t , "simpledb_compactionSameContent" )
117
88
defer cleanDatabaseFolder (t , db )
118
- // we'll close the database to mock some internals directly, yes it's very hacky
119
89
closeDatabase (t , db )
120
90
db .closed = false
121
- db .compactionThreshold = 0
91
+ db .compactionFileThreshold = 0
122
92
123
93
writeSSTableWithTombstoneInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 42 ))
124
- // the tombstone are overwrite
94
+ // the tombstone will be overwritten
125
95
writeSSTableWithDataInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 43 ))
126
96
assert .Nil (t , db .reconstructSSTables ())
127
97
assert .Equal (t , 1300 , int (db .sstableManager .currentSSTable ().MetaData ().GetNumRecords ()))
@@ -130,7 +100,38 @@ func TestExecCompactionWithTombstoneRewriten(t *testing.T) {
130
100
assert .Nil (t , err )
131
101
assert .Equal (t , "sstable_000000000000042" , compactionMeta .ReplacementPath )
132
102
assert .Equal (t , []string {"sstable_000000000000042" , "sstable_000000000000043" }, compactionMeta .SstablePaths )
133
- fmt .Print (compactionMeta )
103
+
104
+ err = db .sstableManager .reflectCompactionResult (compactionMeta )
105
+ assert .NoError (t , err )
106
+ v , err := db .Get ("512" )
107
+ assert .NoError (t , err )
108
+ assert .Equal (t , "512" , v )
109
+ // for cleanups
110
+ assert .Nil (t , db .sstableManager .currentReader .Close ())
111
+
112
+ // check size of compacted sstable
113
+ assert .Equal (t , 1000 , int (db .sstableManager .currentSSTable ().MetaData ().NumRecords ))
114
+ }
115
+
116
+ // regression reported in https://github.com/thomasjungblut/go-sstables/issues/36
117
+ func TestExecCompactionWithTombstonesEmptyTable (t * testing.T ) {
118
+ db := newOpenedSimpleDB (t , "simpledb_compactionEmptyTable" )
119
+ defer cleanDatabaseFolder (t , db )
120
+ closeDatabase (t , db )
121
+ db .closed = false
122
+ db .compactionFileThreshold = 0
123
+
124
+ writeEmptySSTableInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 41 ))
125
+ writeSSTableWithTombstoneInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 42 ))
126
+ writeSSTableWithDataInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 43 ))
127
+ assert .Nil (t , db .reconstructSSTables ())
128
+ assert .Equal (t , 1300 , int (db .sstableManager .currentSSTable ().MetaData ().GetNumRecords ()))
129
+
130
+ compactionMeta , err := executeCompaction (db )
131
+ assert .Nil (t , err )
132
+ assert .Equal (t , "sstable_000000000000041" , compactionMeta .ReplacementPath )
133
+ assert .Equal (t , []string {"sstable_000000000000041" , "sstable_000000000000042" , "sstable_000000000000043" }, compactionMeta .SstablePaths )
134
+
134
135
err = db .sstableManager .reflectCompactionResult (compactionMeta )
135
136
assert .NoError (t , err )
136
137
v , err := db .Get ("512" )
@@ -142,3 +143,81 @@ func TestExecCompactionWithTombstoneRewriten(t *testing.T) {
142
143
// check size of compacted sstable
143
144
assert .Equal (t , 1000 , int (db .sstableManager .currentSSTable ().MetaData ().NumRecords ))
144
145
}
146
+
147
+ // regression reported in https://github.com/thomasjungblut/go-sstables/issues/36
148
+ // more specifically this relates to a case where the first table is above the compaction threshold and never compacted.
149
+ // The keyspace might already be partially rewritten, thus wasting unnecessary space.
150
+ // This test is supposed to fail for later changes, thus the assertion is inverted
151
+ func TestCompactionWithTombstonesBeyondMaxSize (t * testing.T ) {
152
+ db := newOpenedSimpleDB (t , "simpledb_compactionTombstoneBeyondMaxSize" )
153
+ defer cleanDatabaseFolder (t , db )
154
+ closeDatabase (t , db )
155
+ db .closed = false
156
+ db .compactionFileThreshold = 0
157
+ // the tombstone file is about 6k, the 10 written entries are 300k
158
+ db .compactedMaxSizeBytes = 1024
159
+
160
+ writeSSTableWithTombstoneInDatabaseFolder (t , db , fmt .Sprintf (SSTablePattern , 42 ))
161
+ writeSSTableWithDataInDatabaseFolderRange (t , db , fmt .Sprintf (SSTablePattern , 43 ), 510 , 520 )
162
+ assert .Nil (t , db .reconstructSSTables ())
163
+ assert .Equal (t , 310 , int (db .sstableManager .currentSSTable ().MetaData ().GetNumRecords ()))
164
+
165
+ compactionMeta , err := executeCompaction (db )
166
+ assert .Nil (t , err )
167
+ // TODO(thomas): this should also compact the 42 table, as it wastes a ton of space in tombstones
168
+ assert .Equal (t , "sstable_000000000000043" , compactionMeta .ReplacementPath )
169
+ assert .Equal (t , []string {"sstable_000000000000043" }, compactionMeta .SstablePaths )
170
+
171
+ err = db .sstableManager .reflectCompactionResult (compactionMeta )
172
+ assert .NoError (t , err )
173
+ v , err := db .Get ("512" )
174
+ assert .NoError (t , err )
175
+ assert .Equal (t , "512" , v )
176
+ // for cleanups
177
+ assert .Nil (t , db .sstableManager .currentReader .Close ())
178
+ // TODO(thomas): ideally that table should only be 10
179
+ assert .Equal (t , 310 , int (db .sstableManager .currentSSTable ().MetaData ().NumRecords ))
180
+ }
181
+
182
+ func writeSSTableWithDataInDatabaseFolder (t * testing.T , db * DB , p string ) {
183
+ writeSSTableWithDataInDatabaseFolderRange (t , db , p , 0 , 1000 )
184
+ }
185
+
186
+ func writeSSTableWithDataInDatabaseFolderRange (t * testing.T , db * DB , p string , start , end int ) {
187
+ fakeTablePath := filepath .Join (db .basePath , p )
188
+ assert .Nil (t , os .MkdirAll (fakeTablePath , 0700 ))
189
+ mStore := memstore .NewMemStore ()
190
+ for i := start ; i < end ; i ++ {
191
+ assert .Nil (t , mStore .Add ([]byte (fmt .Sprintf ("%d" , i )), []byte (fmt .Sprintf ("%d" , i ))))
192
+ }
193
+ assert .Nil (t , mStore .Flush (
194
+ sstables .WriteBasePath (fakeTablePath ),
195
+ sstables .WithKeyComparator (db .cmp ),
196
+ ))
197
+ }
198
+
199
+ func writeSSTableWithTombstoneInDatabaseFolder (t * testing.T , db * DB , p string ) {
200
+ fakeTablePath := filepath .Join (db .basePath , p )
201
+ assert .Nil (t , os .MkdirAll (fakeTablePath , 0700 ))
202
+ mStore := memstore .NewMemStore ()
203
+
204
+ // delete all key between 500 and 800
205
+ for i := 500 ; i < 800 ; i ++ {
206
+ assert .Nil (t , mStore .Tombstone ([]byte (fmt .Sprintf ("%d" , i ))))
207
+ }
208
+ assert .Nil (t , mStore .FlushWithTombstones (
209
+ sstables .WriteBasePath (fakeTablePath ),
210
+ sstables .WithKeyComparator (db .cmp ),
211
+ ))
212
+ }
213
+
214
+ func writeEmptySSTableInDatabaseFolder (t * testing.T , db * DB , p string ) {
215
+ fakeTablePath := filepath .Join (db .basePath , p )
216
+ assert .Nil (t , os .MkdirAll (fakeTablePath , 0700 ))
217
+ mStore := memstore .NewMemStore ()
218
+
219
+ assert .Nil (t , mStore .FlushWithTombstones (
220
+ sstables .WriteBasePath (fakeTablePath ),
221
+ sstables .WithKeyComparator (db .cmp ),
222
+ ))
223
+ }
0 commit comments