github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/diskstore/local_diskstore_test.go (about) 1 // Copyright (c) 2017-2018 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package diskstore 16 17 import ( 18 "io/ioutil" 19 "math/rand" 20 "os" 21 "sort" 22 "time" 23 "unsafe" 24 25 "github.com/onsi/ginkgo" 26 . "github.com/onsi/gomega" 27 28 "fmt" 29 "github.com/uber/aresdb/utils" 30 "path/filepath" 31 ) 32 33 var _ = ginkgo.Describe("DiskStore", func() { 34 prefix := "/tmp/testDiskStoreSuite" 35 table := "myTable" 36 shard := 1 37 numFiles := 100 38 numNumbersToWrite := 10 39 createdUnixTs := make([]int64, numFiles) 40 41 ginkgo.BeforeEach(func() { 42 os.Remove(prefix) 43 os.MkdirAll(prefix, 0755) 44 }) 45 46 ginkgo.AfterEach(func() { 47 os.RemoveAll(prefix) 48 }) 49 50 ginkgo.It("Test Read/Write/Delete Redolog Files for LocalDiskstore", func() { 51 // Setup directory 52 redologDirPath := GetPathForTableRedologs(prefix, table, shard) 53 os.MkdirAll(redologDirPath, os.ModeDir|os.ModePerm) 54 for i := 0; i < numFiles; i++ { 55 randInt64 := int64(rand.Uint32()) 56 filePath := GetPathForRedologFile(prefix, table, shard, randInt64) 57 createdUnixTs[i] = randInt64 58 ioutil.WriteFile(filePath, nil, os.ModePerm) 59 } 60 l := NewLocalDiskStore(prefix) 61 logsCreatedUnixTs, err := l.ListLogFiles(table, shard) 62 sort.Sort(utils.Int64Array(createdUnixTs)) 63 Ω(err).Should(BeNil()) 64 Ω(logsCreatedUnixTs).Should(Equal(createdUnixTs)) 65 Ω(len(logsCreatedUnixTs)).Should(Equal(numFiles)) 66 // Delete 67 for i := 0; i < numFiles; i++ { 68 err := l.DeleteLogFile(table, shard, createdUnixTs[i]) 69 Ω(err).Should(BeNil()) 70 logsCreatedUnixTs, err := l.ListLogFiles(table, shard) 71 Ω(err).Should(BeNil()) 72 Ω(len(logsCreatedUnixTs)).Should(Equal(numFiles - i - 1)) 73 } 74 // Write 75 for i := 0; i < numFiles; i++ { 76 writerCloser, err := l.OpenLogFileForAppend(table, shard, createdUnixTs[i]) 77 Ω(writerCloser).ShouldNot(BeNil()) 78 Ω(err).Should(BeNil()) 79 ts := createdUnixTs[i] 80 for j := 0; j < numNumbersToWrite; j++ { 81 p := (*[8]byte)(unsafe.Pointer(&ts))[:] 82 Ω(len(p)).Should(Equal(8)) 83 n, err := writerCloser.Write(p) 84 Ω(n).Should(Equal(8)) 85 Ω(err).Should(BeNil()) 86 err = writerCloser.Close() 87 Ω(err).Should(BeNil()) 88 writerCloser, err = l.OpenLogFileForAppend(table, shard, createdUnixTs[i]) 89 Ω(writerCloser).ShouldNot(BeNil()) 90 Ω(err).Should(BeNil()) 91 ts++ 92 } 93 err = writerCloser.Close() 94 Ω(err).Should(BeNil()) 95 } 96 // Read 97 for i := 0; i < numFiles; i++ { 98 readCloser, err := l.OpenLogFileForReplay(table, shard, createdUnixTs[i]) 99 Ω(readCloser).ShouldNot(BeNil()) 100 Ω(err).Should(BeNil()) 101 102 for j := 0; j < numNumbersToWrite; j++ { 103 reader := utils.NewStreamDataReader(readCloser) 104 readCreatedUnixTs, err := reader.ReadUint64() 105 Ω(err).Should(BeNil()) 106 Ω(int64(readCreatedUnixTs)).Should(Equal(createdUnixTs[i] + int64(j))) 107 } 108 109 err = readCloser.Close() 110 Ω(err).Should(BeNil()) 111 } 112 // Delete 113 for i := 0; i < numFiles; i++ { 114 err := l.DeleteLogFile(table, shard, createdUnixTs[i]) 115 Ω(err).Should(BeNil()) 116 logsCreatedUnixTs, err := l.ListLogFiles(table, shard) 117 Ω(err).Should(BeNil()) 118 Ω(len(logsCreatedUnixTs)).Should(Equal(numFiles - i - 1)) 119 } 120 }) 121 122 ginkgo.It("Test Truncating Redolog Files for LocalDiskstore", func() { 123 // Setup directory 124 redologDirPath := GetPathForTableRedologs(prefix, table, shard) 125 os.MkdirAll(redologDirPath, os.ModeDir|os.ModePerm) 126 for i := 0; i < numFiles; i++ { 127 randInt64 := int64(rand.Uint32()) 128 filePath := GetPathForRedologFile(prefix, table, shard, randInt64) 129 createdUnixTs[i] = randInt64 130 ioutil.WriteFile(filePath, nil, os.ModePerm) 131 } 132 l := NewLocalDiskStore(prefix) 133 // Write 134 for i := 0; i < numFiles; i++ { 135 writerCloser, err := l.OpenLogFileForAppend(table, shard, createdUnixTs[i]) 136 Ω(writerCloser).ShouldNot(BeNil()) 137 Ω(err).Should(BeNil()) 138 ts := createdUnixTs[i] 139 for j := 0; j < numNumbersToWrite; j++ { 140 p := (*[8]byte)(unsafe.Pointer(&ts))[:] 141 Ω(len(p)).Should(Equal(8)) 142 n, err := writerCloser.Write(p) 143 Ω(n).Should(Equal(8)) 144 Ω(err).Should(BeNil()) 145 err = writerCloser.Close() 146 Ω(err).Should(BeNil()) 147 writerCloser, err = l.OpenLogFileForAppend(table, shard, createdUnixTs[i]) 148 Ω(writerCloser).ShouldNot(BeNil()) 149 Ω(err).Should(BeNil()) 150 ts++ 151 } 152 err = writerCloser.Close() 153 Ω(err).Should(BeNil()) 154 } 155 // Truncate 156 truncateSize := int64(numNumbersToWrite * 8 / 2) 157 for i := 0; i < numFiles; i++ { 158 filePath := GetPathForRedologFile(prefix, table, shard, createdUnixTs[i]) 159 oldFileInfo, _ := os.Stat(filePath) 160 err := l.TruncateLogFile(table, shard, createdUnixTs[i], truncateSize) 161 Ω(err).Should(BeNil()) 162 newFileInfo, _ := os.Stat(filePath) 163 Ω(oldFileInfo.Size()).Should(Equal(newFileInfo.Size() * 2)) 164 } 165 // Read 166 for i := 0; i < numFiles; i++ { 167 readCloser, err := l.OpenLogFileForReplay(table, shard, createdUnixTs[i]) 168 Ω(readCloser).ShouldNot(BeNil()) 169 Ω(err).Should(BeNil()) 170 171 for j := 0; j < numNumbersToWrite/2; j++ { 172 reader := utils.NewStreamDataReader(readCloser) 173 readCreatedUnixTs, err := reader.ReadUint64() 174 Ω(err).Should(BeNil()) 175 Ω(int64(readCreatedUnixTs)).Should(Equal(createdUnixTs[i] + int64(j))) 176 } 177 178 err = readCloser.Close() 179 Ω(err).Should(BeNil()) 180 } 181 }) 182 183 ginkgo.It("works with non-existing redolog file directory", func() { 184 l := NewLocalDiskStore(prefix) 185 files, err := l.ListLogFiles(table, shard) 186 Ω(err).Should(BeNil()) 187 Ω(files).Should(BeNil()) 188 }) 189 190 ginkgo.It("Test List Snapshot Dir for LocalDiskstore", func() { 191 // Setup directory 192 snapshotDirPath := GetPathForTableSnapshotDir(prefix, table, shard) 193 os.MkdirAll(snapshotDirPath, 0755) 194 195 var redoLogFile int64 = 1 196 var offset uint32 = 1 197 randomBatches := make([]int, numFiles) 198 for i := 0; i < numFiles; i++ { 199 randomBatch := int(rand.Int31()) 200 filePath := GetPathForTableSnapshotColumnFilePath(prefix, table, shard, redoLogFile, offset, 201 randomBatch, 0) 202 os.MkdirAll(filepath.Dir(filePath), 0755) 203 randomBatches[i] = randomBatch 204 ioutil.WriteFile(filePath, []byte{}, os.ModePerm) 205 } 206 207 sort.Ints(randomBatches) 208 l := NewLocalDiskStore(prefix) 209 210 batches, err := l.ListSnapshotBatches(table, shard, redoLogFile, offset) 211 Ω(err).Should(BeNil()) 212 Ω(batches).Should(Equal(randomBatches)) 213 214 batches, err = l.ListSnapshotBatches(table, shard, redoLogFile, offset+1) 215 Ω(err).Should(BeNil()) 216 Ω(batches).Should(BeEmpty()) 217 }) 218 219 ginkgo.It("Test List Snapshot VP Files", func() { 220 // Setup directory 221 var redoLogFile int64 = 1 222 var offset uint32 = 1 223 batchID := 1 224 batchDir := GetPathForTableSnapshotBatchDir(prefix, table, shard, redoLogFile, offset, batchID) 225 os.MkdirAll(batchDir, 0755) 226 227 randomColumns := make([]int, numFiles) 228 for i := 0; i < numFiles; i++ { 229 randomColumn := int(rand.Int31()) 230 filePath := GetPathForTableSnapshotColumnFilePath(prefix, table, shard, redoLogFile, offset, 231 batchID, randomColumn) 232 randomColumns[i] = randomColumn 233 ioutil.WriteFile(filePath, []byte{}, os.ModePerm) 234 } 235 236 sort.Ints(randomColumns) 237 l := NewLocalDiskStore(prefix) 238 239 columns, err := l.ListSnapshotVectorPartyFiles(table, shard, redoLogFile, offset, batchID) 240 Ω(err).Should(BeNil()) 241 Ω(columns).Should(Equal(randomColumns)) 242 243 columns, err = l.ListSnapshotVectorPartyFiles(table, shard, redoLogFile, offset, batchID+1) 244 Ω(err).Should(BeNil()) 245 Ω(columns).Should(BeEmpty()) 246 }) 247 248 ginkgo.It("Test Read Snapshot Files for LocalDiskstore", func() { 249 // Setup directory 250 var redoLogFile int64 = 1 251 var offset uint32 = 1 252 batchID := 1 253 batchDir := GetPathForTableSnapshotBatchDir(prefix, table, shard, redoLogFile, offset, batchID) 254 os.MkdirAll(batchDir, 0755) 255 256 randomThingToWrite := []byte("Test Read Snapshot Files for LocalDiskstore") 257 randomColumns := make([]int, numFiles) 258 for i := 0; i < numFiles; i++ { 259 randomColumn := int(rand.Int31()) 260 filePath := GetPathForTableSnapshotColumnFilePath(prefix, table, shard, redoLogFile, offset, batchID, randomColumn) 261 randomColumns[i] = randomColumn 262 ioutil.WriteFile(filePath, randomThingToWrite, os.ModePerm) 263 } 264 l := NewLocalDiskStore(prefix) 265 266 // Read 267 for _, column := range randomColumns { 268 readCloser, err := l.OpenSnapshotVectorPartyFileForRead(table, shard, redoLogFile, offset, batchID, column) 269 Ω(readCloser).ShouldNot(BeNil()) 270 Ω(err).Should(BeNil()) 271 p := make([]byte, len(randomThingToWrite)) 272 numBytesRead, err := readCloser.Read(p) 273 Ω(numBytesRead).Should(Equal(len(randomThingToWrite))) 274 Ω(p).Should(Equal(randomThingToWrite)) 275 err = readCloser.Close() 276 Ω(err).Should(BeNil()) 277 } 278 }) 279 280 ginkgo.It("Test Write Snapshot Files for LocalDiskstore", func() { 281 // Setup directory 282 var redoLogFile int64 = 1 283 var offset uint32 = 1 284 batchID := 1 285 batchDir := GetPathForTableSnapshotBatchDir(prefix, table, shard, redoLogFile, offset, batchID) 286 os.MkdirAll(batchDir, 0755) 287 288 randomThingToWrite := []byte("Test Write Snapshot Files for LocalDiskstore") 289 randomColumns := make([]int, numFiles) 290 l := NewLocalDiskStore(prefix) 291 // Initial set and write something longer string. 292 for i := 0; i < numFiles; i++ { 293 randomColumn := int(rand.Int31()) 294 randomColumns[i] = randomColumn 295 writeCloser, err := l.OpenSnapshotVectorPartyFileForWrite(table, shard, redoLogFile, offset, batchID, randomColumn) 296 Ω(writeCloser).ShouldNot(BeNil()) 297 Ω(err).Should(BeNil()) 298 numBytesWritten, err := writeCloser.Write(randomThingToWrite) 299 Ω(numBytesWritten).Should(Equal(len(randomThingToWrite))) 300 Ω(err).Should(BeNil()) 301 err = writeCloser.Close() 302 Ω(err).Should(BeNil()) 303 } 304 // Read 305 for _, column := range randomColumns { 306 readCloser, err := l.OpenSnapshotVectorPartyFileForRead(table, shard, redoLogFile, offset, batchID, column) 307 Ω(readCloser).ShouldNot(BeNil()) 308 Ω(err).Should(BeNil()) 309 p := make([]byte, len(randomThingToWrite)) 310 numBytesRead, err := readCloser.Read(p) 311 Ω(numBytesRead).Should(Equal(len(randomThingToWrite))) 312 Ω(p).Should(Equal(randomThingToWrite)) 313 err = readCloser.Close() 314 Ω(err).Should(BeNil()) 315 } 316 317 anotherRandomThingToWrite := []byte("Write Snapshot Files for LocalDiskstore") 318 // Should overwrite exising files with shorter string. 319 for _, column := range randomColumns { 320 writeCloser, err := l.OpenSnapshotVectorPartyFileForWrite(table, shard, redoLogFile, offset, batchID, column) 321 Ω(writeCloser).ShouldNot(BeNil()) 322 Ω(err).Should(BeNil()) 323 numBytesWritten, err := writeCloser.Write(anotherRandomThingToWrite) 324 Ω(numBytesWritten).Should(Equal(len(anotherRandomThingToWrite))) 325 Ω(err).Should(BeNil()) 326 err = writeCloser.Close() 327 Ω(err).Should(BeNil()) 328 } 329 330 // Read 331 for _, column := range randomColumns { 332 readCloser, err := l.OpenSnapshotVectorPartyFileForRead(table, shard, redoLogFile, offset, batchID, column) 333 Ω(readCloser).ShouldNot(BeNil()) 334 Ω(err).Should(BeNil()) 335 p := make([]byte, len(anotherRandomThingToWrite)) 336 numBytesRead, err := readCloser.Read(p) 337 Ω(numBytesRead).Should(Equal(len(anotherRandomThingToWrite))) 338 Ω(p).Should(Equal(anotherRandomThingToWrite)) 339 err = readCloser.Close() 340 Ω(err).Should(BeNil()) 341 } 342 }) 343 344 ginkgo.It("Test Delete Snapshot Files for LocalDiskstore", func() { 345 // Setup directory 346 snapshotDirPath := GetPathForTableSnapshotDir(prefix, table, shard) 347 os.MkdirAll(snapshotDirPath, 0755) 348 349 randomThingToWrite := []byte("Another Test Write Snapshot Files for LocalDiskstore") 350 randomRedologFiles := make([]int64, numFiles) 351 randomOffsets := make([]uint32, numFiles) 352 l := NewLocalDiskStore(prefix) 353 354 var redoLogFileLimit int64 = 3 355 var offsetLimit uint32 = 10 356 357 keptFilesMap := make(map[string]string) 358 359 redoLogFile := redoLogFileLimit / 2 360 offset := offsetLimit / 2 361 362 // Initial set and write something longer string. 363 for i := 0; i < numFiles; i++ { 364 randomRedoLogFile := rand.Int63n(redoLogFileLimit) 365 randomOffset := uint32(rand.Int31n(int32(offsetLimit))) 366 randomRedologFiles[i] = randomRedoLogFile 367 randomOffsets[i] = randomOffset 368 if randomRedoLogFile > redoLogFile || (randomRedoLogFile == redoLogFile && randomOffset >= offset) { 369 fileName := fmt.Sprintf("%d_%d", randomRedoLogFile, randomOffset) 370 keptFilesMap[fileName] = fileName 371 } 372 writeCloser, err := l.OpenSnapshotVectorPartyFileForWrite(table, shard, 373 randomRedoLogFile, randomOffset, 0, 0) 374 Ω(writeCloser).ShouldNot(BeNil()) 375 Ω(err).Should(BeNil()) 376 numBytesWritten, err := writeCloser.Write(randomThingToWrite) 377 Ω(numBytesWritten).Should(Equal(len(randomThingToWrite))) 378 Ω(err).Should(BeNil()) 379 err = writeCloser.Close() 380 Ω(err).Should(BeNil()) 381 } 382 383 var keptFiles []string 384 385 for _, f := range keptFilesMap { 386 keptFiles = append(keptFiles, f) 387 } 388 389 sort.Strings(keptFiles) 390 391 err := l.DeleteSnapshot(table, shard, redoLogFile, offset) 392 Ω(err).Should(BeNil()) 393 snapshotFileInfos, err := ioutil.ReadDir(snapshotDirPath) 394 Ω(err).Should(BeNil()) 395 snapshotFiles := make([]string, len(snapshotFileInfos)) 396 397 for i, fileInfo := range snapshotFileInfos { 398 snapshotFiles[i] = fileInfo.Name() 399 } 400 401 Ω(snapshotFiles).Should(Equal(keptFiles)) 402 }) 403 404 ginkgo.It("Test Read/Write Archiving Column and DeleteBatchVersions for LocalDiskstore", func() { 405 l := NewLocalDiskStore(prefix) 406 // Setup directory 407 batchID := "1988-06-17" 408 batchIDSinceEpoch := 6742 409 columnID := 617 410 411 randomThingToWrite := []byte("Test Read Snapshot Files for LocalDiskstore") 412 randBatchVersions := make([]uint32, numFiles*2) 413 414 // Write to columns 415 for i := 0; i < numFiles; i++ { 416 randBatchVersion := rand.Uint32() 417 randBatchVersions[i] = randBatchVersion 418 batchDirPath := GetPathForTableArchiveBatchDir(prefix, table, shard, batchID, randBatchVersion, 0) 419 os.MkdirAll(batchDirPath, 0755) 420 batchDirPath = GetPathForTableArchiveBatchDir(prefix, table, shard, batchID, randBatchVersion, 1) 421 os.MkdirAll(batchDirPath, 0755) 422 writeCloser, err := l.OpenVectorPartyFileForWrite(table, columnID, shard, batchIDSinceEpoch, randBatchVersion, 1) 423 numBytesWritten, err := writeCloser.Write(randomThingToWrite) 424 Ω(numBytesWritten).Should(Equal(len(randomThingToWrite))) 425 Ω(err).Should(BeNil()) 426 err = writeCloser.Close() 427 Ω(err).Should(BeNil()) 428 } 429 430 var maxVersion uint32 431 for _, version := range randBatchVersions { 432 if version > maxVersion { 433 maxVersion = version 434 } 435 } 436 437 // Read from columns 438 for i := 0; i < numFiles; i++ { 439 readCloser, err := l.OpenVectorPartyFileForRead(table, columnID, shard, batchIDSinceEpoch, randBatchVersions[i], 1) 440 Ω(readCloser).ShouldNot(BeNil()) 441 Ω(err).Should(BeNil()) 442 p := make([]byte, len(randomThingToWrite)) 443 numBytesRead, err := readCloser.Read(p) 444 Ω(numBytesRead).Should(Equal(len(randomThingToWrite))) 445 Ω(p).Should(Equal(randomThingToWrite)) 446 err = readCloser.Close() 447 Ω(err).Should(BeNil()) 448 } 449 450 // DeleteBatchVersions using the max version will delete all batch versions. 451 batchRootDirPath := GetPathForTableArchiveBatchRootDir(prefix, table, shard) 452 dirs, err := ioutil.ReadDir(batchRootDirPath) 453 Ω(err).Should(BeNil()) 454 Ω(len(dirs)).Should(Equal(numFiles * 2)) 455 err = l.DeleteBatchVersions(table, shard, batchIDSinceEpoch, maxVersion, 1) 456 Ω(err).Should(BeNil()) 457 dirs, err = ioutil.ReadDir(batchRootDirPath) 458 Ω(err).Should(BeNil()) 459 Ω(len(dirs)).Should(Equal(0)) 460 }) 461 462 ginkgo.It("Test DeleteBatches with batchIDCutoff for LocalDiskstore", func() { 463 l := NewLocalDiskStore(prefix) 464 // Setup directory 465 466 startBatchID := "2017-06-17" 467 startBatchIDTime, err := time.Parse(timeFormatForBatchID, startBatchID) 468 Ω(err).Should(BeNil()) 469 batchVersion := rand.Uint32() 470 archiveBatchRootDirPath := GetPathForTableArchiveBatchRootDir(prefix, table, shard) 471 472 // Create BatchID directories 473 for i := 0; i < numFiles; i++ { 474 batchIDTime := startBatchIDTime.Add(time.Duration(24*i) * time.Hour) 475 batchID := batchIDTime.Format(timeFormatForBatchID) 476 versionedBatchDirPath := GetPathForTableArchiveBatchDir(prefix, table, shard, batchID, batchVersion, 0) 477 os.MkdirAll(versionedBatchDirPath, 0755) 478 } 479 480 // DeleteBatch with batchIDCutoff 481 for i := 0; i < numFiles; i++ { 482 batchIDTime := startBatchIDTime.Add(time.Duration(24*i) * time.Hour) 483 _, err = l.DeleteBatches(table, shard, 0, int(batchIDTime.Unix()/86400)) 484 Ω(err).Should(BeNil()) 485 batchDirs, err := ioutil.ReadDir(archiveBatchRootDirPath) 486 Ω(err).Should(BeNil()) 487 Ω(len(batchDirs)).Should(Equal(numFiles - i)) 488 } 489 batchDirs, err := ioutil.ReadDir(archiveBatchRootDirPath) 490 Ω(err).Should(BeNil()) 491 Ω(len(batchDirs)).Should(Equal(1)) 492 493 // Create BatchID directories 494 for i := 0; i < numFiles; i++ { 495 batchIDTime := startBatchIDTime.Add(time.Duration(24*i) * time.Hour) 496 batchID := batchIDTime.Format(timeFormatForBatchID) 497 versionedBatchDirPath := GetPathForTableArchiveBatchDir(prefix, table, shard, batchID, batchVersion, 0) 498 os.MkdirAll(versionedBatchDirPath, 0755) 499 } 500 501 // DeleteBatch with batchIDCutoff 502 for i := 0; i < numFiles; i += 2 { 503 batchIDTime := startBatchIDTime.Add(time.Duration(24*i) * time.Hour) 504 _, err = l.DeleteBatches(table, shard, 0, int(batchIDTime.Unix()/86400)) 505 Ω(err).Should(BeNil()) 506 batchDirs, err := ioutil.ReadDir(archiveBatchRootDirPath) 507 Ω(err).Should(BeNil()) 508 Ω(len(batchDirs)).Should(Equal(numFiles - i)) 509 } 510 batchDirs, err = ioutil.ReadDir(archiveBatchRootDirPath) 511 Ω(err).Should(BeNil()) 512 Ω(len(batchDirs)).Should(Equal(2)) 513 514 }) 515 516 ginkgo.It("Test DeleteColumn for LocalDiskstore", func() { 517 l := NewLocalDiskStore(prefix) 518 // Setup directory 519 numSubDir := 10 520 randomThingToWrite := []byte("Test Read Snapshot Files for LocalDiskstore") 521 startBatchID := "2017-06-17" 522 startBatchIDTime, err := time.Parse(timeFormatForBatchID, startBatchID) 523 Ω(err).Should(BeNil()) 524 startBatchVersion := rand.Uint32() 525 archiveBatchRootDirPath := GetPathForTableArchiveBatchRootDir(prefix, table, shard) 526 527 // Create $numSubDir batches, each batch has $numSubDir versions, each version has $numSubDir columns. 528 for i := 0; i < numSubDir; i++ { 529 batchIDTime := startBatchIDTime.Add(time.Duration(24*i) * time.Hour) 530 batchID := batchIDTime.Format(timeFormatForBatchID) 531 for j := 0; j < numSubDir; j++ { 532 batchVersion := startBatchVersion + uint32(j) 533 versionedBatchDirPath := GetPathForTableArchiveBatchDir(prefix, table, shard, batchID, batchVersion, 0) 534 os.MkdirAll(versionedBatchDirPath, 0755) 535 for k := 0; k < numSubDir; k++ { 536 columnID := k 537 writeCloser, err := l.OpenVectorPartyFileForWrite(table, columnID, shard, int(batchIDTime.Unix()/86400), batchVersion, 0) 538 numBytesWritten, err := writeCloser.Write(randomThingToWrite) 539 Ω(numBytesWritten).Should(Equal(len(randomThingToWrite))) 540 Ω(err).Should(BeNil()) 541 err = writeCloser.Close() 542 Ω(err).Should(BeNil()) 543 } 544 } 545 } 546 547 // DeleteBatch with batchIDCutoff 548 for i := 0; i < numSubDir; i++ { 549 columnID := i 550 l.DeleteColumn(table, columnID, shard) 551 batchDirs, err := ioutil.ReadDir(archiveBatchRootDirPath) 552 Ω(err).Should(BeNil()) 553 for _, f := range batchDirs { 554 batchID, versionID, seqNum, _ := ParseBatchIDAndVersionName(f.Name()) 555 versionedBatchDir := GetPathForTableArchiveBatchDir(prefix, table, shard, batchID, versionID, seqNum) 556 columnFiles, err := ioutil.ReadDir(versionedBatchDir) 557 Ω(err).Should(BeNil()) 558 Ω(len(columnFiles)).Should(Equal(10 - i - 1)) 559 columnFilePath := GetPathForTableArchiveBatchColumnFile(prefix, table, shard, batchID, versionID, seqNum, columnID) 560 _, err = os.Stat(columnFilePath) 561 Ω(err).ShouldNot(BeNil()) 562 } 563 } 564 }) 565 })