get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/filestore_test.go (about) 1 // Copyright 2019-2024 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "archive/tar" 18 "bytes" 19 "crypto/hmac" 20 crand "crypto/rand" 21 "crypto/sha256" 22 "encoding/hex" 23 "encoding/json" 24 "errors" 25 "fmt" 26 "io" 27 "math/bits" 28 "math/rand" 29 "os" 30 "path/filepath" 31 "reflect" 32 "strings" 33 "sync" 34 "testing" 35 "time" 36 37 "github.com/klauspost/compress/s2" 38 ) 39 40 func testFileStoreAllPermutations(t *testing.T, fn func(t *testing.T, fcfg FileStoreConfig)) { 41 for _, fcfg := range []FileStoreConfig{ 42 {Cipher: NoCipher, Compression: NoCompression}, 43 {Cipher: NoCipher, Compression: S2Compression}, 44 {Cipher: AES, Compression: NoCompression}, 45 {Cipher: AES, Compression: S2Compression}, 46 {Cipher: ChaCha, Compression: NoCompression}, 47 {Cipher: ChaCha, Compression: S2Compression}, 48 } { 49 subtestName := fmt.Sprintf("%s-%s", fcfg.Cipher, fcfg.Compression) 50 t.Run(subtestName, func(t *testing.T) { 51 fcfg.StoreDir = t.TempDir() 52 fn(t, fcfg) 53 time.Sleep(100 * time.Millisecond) 54 }) 55 } 56 } 57 58 func prf(fcfg *FileStoreConfig) func(context []byte) ([]byte, error) { 59 if fcfg.Cipher == NoCipher { 60 return nil 61 } 62 return func(context []byte) ([]byte, error) { 63 h := hmac.New(sha256.New, []byte("dlc22")) 64 if _, err := h.Write(context); err != nil { 65 return nil, err 66 } 67 return h.Sum(nil), nil 68 } 69 } 70 71 func TestFileStoreBasics(t *testing.T) { 72 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 73 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 74 require_NoError(t, err) 75 defer fs.Stop() 76 77 subj, msg := "foo", []byte("Hello World") 78 now := time.Now().UnixNano() 79 for i := 1; i <= 5; i++ { 80 if seq, ts, err := fs.StoreMsg(subj, nil, msg); err != nil { 81 t.Fatalf("Error storing msg: %v", err) 82 } else if seq != uint64(i) { 83 t.Fatalf("Expected sequence to be %d, got %d", i, seq) 84 } else if ts < now || ts > now+int64(time.Millisecond) { 85 t.Fatalf("Expected timestamp to be current, got %v", ts-now) 86 } 87 } 88 89 state := fs.State() 90 if state.Msgs != 5 { 91 t.Fatalf("Expected 5 msgs, got %d", state.Msgs) 92 } 93 expectedSize := 5 * fileStoreMsgSize(subj, nil, msg) 94 if state.Bytes != expectedSize { 95 t.Fatalf("Expected %d bytes, got %d", expectedSize, state.Bytes) 96 } 97 98 var smv StoreMsg 99 sm, err := fs.LoadMsg(2, &smv) 100 if err != nil { 101 t.Fatalf("Unexpected error looking up msg: %v", err) 102 } 103 if sm.subj != subj { 104 t.Fatalf("Subjects don't match, original %q vs %q", subj, sm.subj) 105 } 106 if !bytes.Equal(sm.msg, msg) { 107 t.Fatalf("Msgs don't match, original %q vs %q", msg, sm.msg) 108 } 109 _, err = fs.LoadMsg(3, nil) 110 if err != nil { 111 t.Fatalf("Unexpected error looking up msg: %v", err) 112 } 113 114 remove := func(seq, expectedMsgs uint64) { 115 t.Helper() 116 removed, err := fs.RemoveMsg(seq) 117 if err != nil { 118 t.Fatalf("Got an error on remove of %d: %v", seq, err) 119 } 120 if !removed { 121 t.Fatalf("Expected remove to return true for %d", seq) 122 } 123 if state := fs.State(); state.Msgs != expectedMsgs { 124 t.Fatalf("Expected %d msgs, got %d", expectedMsgs, state.Msgs) 125 } 126 } 127 128 // Remove first 129 remove(1, 4) 130 // Remove last 131 remove(5, 3) 132 // Remove a middle 133 remove(3, 2) 134 }) 135 } 136 137 func TestFileStoreMsgHeaders(t *testing.T) { 138 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 139 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 140 require_NoError(t, err) 141 defer fs.Stop() 142 143 subj, hdr, msg := "foo", []byte("name:derek"), []byte("Hello World") 144 elen := 22 + len(subj) + 4 + len(hdr) + len(msg) + 8 145 if sz := int(fileStoreMsgSize(subj, hdr, msg)); sz != elen { 146 t.Fatalf("Wrong size for stored msg with header") 147 } 148 fs.StoreMsg(subj, hdr, msg) 149 var smv StoreMsg 150 sm, err := fs.LoadMsg(1, &smv) 151 if err != nil { 152 t.Fatalf("Unexpected error looking up msg: %v", err) 153 } 154 if !bytes.Equal(msg, sm.msg) { 155 t.Fatalf("Expected same msg, got %q vs %q", sm.msg, msg) 156 } 157 if !bytes.Equal(hdr, sm.hdr) { 158 t.Fatalf("Expected same hdr, got %q vs %q", sm.hdr, hdr) 159 } 160 if removed, _ := fs.EraseMsg(1); !removed { 161 t.Fatalf("Expected erase msg to return success") 162 } 163 }) 164 } 165 166 func TestFileStoreBasicWriteMsgsAndRestore(t *testing.T) { 167 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 168 if _, err := newFileStore(fcfg, StreamConfig{Storage: MemoryStorage}); err == nil { 169 t.Fatalf("Expected an error with wrong type") 170 } 171 if _, err := newFileStore(fcfg, StreamConfig{Storage: FileStorage}); err == nil { 172 t.Fatalf("Expected an error with no name") 173 } 174 175 created := time.Now() 176 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 177 require_NoError(t, err) 178 defer fs.Stop() 179 180 subj := "foo" 181 182 // Write 100 msgs 183 toStore := uint64(100) 184 for i := uint64(1); i <= toStore; i++ { 185 msg := []byte(fmt.Sprintf("[%08d] Hello World!", i)) 186 if seq, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 187 t.Fatalf("Error storing msg: %v", err) 188 } else if seq != uint64(i) { 189 t.Fatalf("Expected sequence to be %d, got %d", i, seq) 190 } 191 } 192 state := fs.State() 193 if state.Msgs != toStore { 194 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 195 } 196 msg22 := []byte(fmt.Sprintf("[%08d] Hello World!", 22)) 197 expectedSize := toStore * fileStoreMsgSize(subj, nil, msg22) 198 199 if state.Bytes != expectedSize { 200 t.Fatalf("Expected %d bytes, got %d", expectedSize, state.Bytes) 201 } 202 // Stop will flush to disk. 203 fs.Stop() 204 205 // Make sure Store call after does not work. 206 if _, _, err := fs.StoreMsg(subj, nil, []byte("no work")); err == nil { 207 t.Fatalf("Expected an error for StoreMsg call after Stop, got none") 208 } 209 210 // Restart 211 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 212 require_NoError(t, err) 213 defer fs.Stop() 214 215 state = fs.State() 216 if state.Msgs != toStore { 217 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 218 } 219 if state.Bytes != expectedSize { 220 t.Fatalf("Expected %d bytes, got %d", expectedSize, state.Bytes) 221 } 222 223 // Now write 100 more msgs 224 for i := uint64(101); i <= toStore*2; i++ { 225 msg := []byte(fmt.Sprintf("[%08d] Hello World!", i)) 226 if seq, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 227 t.Fatalf("Error storing msg: %v", err) 228 } else if seq != uint64(i) { 229 t.Fatalf("Expected sequence to be %d, got %d", i, seq) 230 } 231 } 232 state = fs.State() 233 if state.Msgs != toStore*2 { 234 t.Fatalf("Expected %d msgs, got %d", toStore*2, state.Msgs) 235 } 236 237 // Now cycle again and make sure that last batch was stored. 238 // Stop will flush to disk. 239 fs.Stop() 240 241 // Restart 242 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 243 require_NoError(t, err) 244 defer fs.Stop() 245 246 state = fs.State() 247 if state.Msgs != toStore*2 { 248 t.Fatalf("Expected %d msgs, got %d", toStore*2, state.Msgs) 249 } 250 if state.Bytes != expectedSize*2 { 251 t.Fatalf("Expected %d bytes, got %d", expectedSize*2, state.Bytes) 252 } 253 254 fs.Purge() 255 fs.Stop() 256 257 // Restart 258 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 259 require_NoError(t, err) 260 defer fs.Stop() 261 262 state = fs.State() 263 if state.Msgs != 0 { 264 t.Fatalf("Expected %d msgs, got %d", 0, state.Msgs) 265 } 266 if state.Bytes != 0 { 267 t.Fatalf("Expected %d bytes, got %d", 0, state.Bytes) 268 } 269 270 seq, _, err := fs.StoreMsg(subj, nil, []byte("Hello")) 271 if err != nil { 272 t.Fatalf("Unexpected error: %v", err) 273 } 274 fs.RemoveMsg(seq) 275 276 fs.Stop() 277 278 // Restart 279 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 280 require_NoError(t, err) 281 defer fs.Stop() 282 283 state = fs.State() 284 require_Equal(t, state.FirstSeq, seq+1) 285 }) 286 } 287 288 func TestFileStoreSelectNextFirst(t *testing.T) { 289 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 290 fcfg.BlockSize = 256 291 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 292 require_NoError(t, err) 293 defer fs.Stop() 294 295 numMsgs := 10 296 subj, msg := "zzz", []byte("Hello World") 297 for i := 0; i < numMsgs; i++ { 298 fs.StoreMsg(subj, nil, msg) 299 } 300 if state := fs.State(); state.Msgs != uint64(numMsgs) { 301 t.Fatalf("Expected %d msgs, got %d", numMsgs, state.Msgs) 302 } 303 304 // Note the 256 block size is tied to the msg size below to give us 5 messages per block. 305 if fmb := fs.selectMsgBlock(1); fmb.msgs != 5 { 306 t.Fatalf("Expected 5 messages per block, but got %d", fmb.msgs) 307 } 308 309 // Delete 2-7, this will cross message blocks. 310 for i := 2; i <= 7; i++ { 311 fs.RemoveMsg(uint64(i)) 312 } 313 314 if state := fs.State(); state.Msgs != 4 || state.FirstSeq != 1 { 315 t.Fatalf("Expected 4 msgs, first seq of 11, got msgs of %d and first seq of %d", state.Msgs, state.FirstSeq) 316 } 317 // Now close the gap which will force the system to jump underlying message blocks to find the right sequence. 318 fs.RemoveMsg(1) 319 if state := fs.State(); state.Msgs != 3 || state.FirstSeq != 8 { 320 t.Fatalf("Expected 3 msgs, first seq of 8, got msgs of %d and first seq of %d", state.Msgs, state.FirstSeq) 321 } 322 }) 323 } 324 325 func TestFileStoreSkipMsg(t *testing.T) { 326 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 327 fcfg.BlockSize = 256 328 created := time.Now() 329 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 330 require_NoError(t, err) 331 defer fs.Stop() 332 333 numSkips := 10 334 for i := 0; i < numSkips; i++ { 335 fs.SkipMsg() 336 } 337 state := fs.State() 338 if state.Msgs != 0 { 339 t.Fatalf("Expected %d msgs, got %d", 0, state.Msgs) 340 } 341 if state.FirstSeq != uint64(numSkips+1) || state.LastSeq != uint64(numSkips) { 342 t.Fatalf("Expected first to be %d and last to be %d. got first %d and last %d", numSkips+1, numSkips, state.FirstSeq, state.LastSeq) 343 } 344 345 fs.StoreMsg("zzz", nil, []byte("Hello World!")) 346 fs.SkipMsg() 347 fs.SkipMsg() 348 fs.StoreMsg("zzz", nil, []byte("Hello World!")) 349 fs.SkipMsg() 350 351 state = fs.State() 352 if state.Msgs != 2 { 353 t.Fatalf("Expected %d msgs, got %d", 2, state.Msgs) 354 } 355 if state.FirstSeq != uint64(numSkips+1) || state.LastSeq != uint64(numSkips+5) { 356 t.Fatalf("Expected first to be %d and last to be %d. got first %d and last %d", numSkips+1, numSkips+5, state.FirstSeq, state.LastSeq) 357 } 358 359 // Make sure we recover same state. 360 fs.Stop() 361 362 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 363 require_NoError(t, err) 364 defer fs.Stop() 365 366 state = fs.State() 367 if state.Msgs != 2 { 368 t.Fatalf("Expected %d msgs, got %d", 2, state.Msgs) 369 } 370 if state.FirstSeq != uint64(numSkips+1) || state.LastSeq != uint64(numSkips+5) { 371 t.Fatalf("Expected first to be %d and last to be %d. got first %d and last %d", numSkips+1, numSkips+5, state.FirstSeq, state.LastSeq) 372 } 373 374 var smv StoreMsg 375 sm, err := fs.LoadMsg(11, &smv) 376 if err != nil { 377 t.Fatalf("Unexpected error looking up seq 11: %v", err) 378 } 379 if sm.subj != "zzz" || string(sm.msg) != "Hello World!" { 380 t.Fatalf("Message did not match") 381 } 382 383 fs.SkipMsg() 384 nseq, _, err := fs.StoreMsg("AAA", nil, []byte("Skip?")) 385 if err != nil { 386 t.Fatalf("Unexpected error looking up seq 11: %v", err) 387 } 388 if nseq != 17 { 389 t.Fatalf("Expected seq of %d but got %d", 17, nseq) 390 } 391 392 // Make sure we recover same state. 393 fs.Stop() 394 395 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 396 require_NoError(t, err) 397 defer fs.Stop() 398 399 sm, err = fs.LoadMsg(nseq, &smv) 400 if err != nil { 401 t.Fatalf("Unexpected error looking up seq %d: %v", nseq, err) 402 } 403 if sm.subj != "AAA" || string(sm.msg) != "Skip?" { 404 t.Fatalf("Message did not match") 405 } 406 }) 407 } 408 409 func TestFileStoreWriteExpireWrite(t *testing.T) { 410 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 411 cexp := 10 * time.Millisecond 412 fcfg.CacheExpire = cexp 413 created := time.Now() 414 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 415 require_NoError(t, err) 416 defer fs.Stop() 417 418 toSend := 10 419 for i := 0; i < toSend; i++ { 420 fs.StoreMsg("zzz", nil, []byte("Hello World!")) 421 } 422 423 // Wait for write cache portion to go to zero. 424 checkFor(t, time.Second, 20*time.Millisecond, func() error { 425 if csz := fs.cacheSize(); csz != 0 { 426 return fmt.Errorf("cache size not 0, got %s", friendlyBytes(int64(csz))) 427 } 428 return nil 429 }) 430 431 for i := 0; i < toSend; i++ { 432 fs.StoreMsg("zzz", nil, []byte("Hello World! - 22")) 433 } 434 435 if state := fs.State(); state.Msgs != uint64(toSend*2) { 436 t.Fatalf("Expected %d msgs, got %d", toSend*2, state.Msgs) 437 } 438 439 // Make sure we recover same state. 440 fs.Stop() 441 442 fcfg.CacheExpire = 0 443 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 444 require_NoError(t, err) 445 defer fs.Stop() 446 447 if state := fs.State(); state.Msgs != uint64(toSend*2) { 448 t.Fatalf("Expected %d msgs, got %d", toSend*2, state.Msgs) 449 } 450 451 // Now load them in and check. 452 var smv StoreMsg 453 for i := 1; i <= toSend*2; i++ { 454 sm, err := fs.LoadMsg(uint64(i), &smv) 455 if err != nil { 456 t.Fatalf("Unexpected error looking up seq %d: %v", i, err) 457 } 458 str := "Hello World!" 459 if i > toSend { 460 str = "Hello World! - 22" 461 } 462 if sm.subj != "zzz" || string(sm.msg) != str { 463 t.Fatalf("Message did not match") 464 } 465 } 466 }) 467 } 468 469 func TestFileStoreMsgLimit(t *testing.T) { 470 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 471 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage, MaxMsgs: 10}, time.Now(), prf(&fcfg), nil) 472 require_NoError(t, err) 473 defer fs.Stop() 474 475 subj, msg := "foo", []byte("Hello World") 476 for i := 0; i < 10; i++ { 477 fs.StoreMsg(subj, nil, msg) 478 } 479 state := fs.State() 480 if state.Msgs != 10 { 481 t.Fatalf("Expected %d msgs, got %d", 10, state.Msgs) 482 } 483 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 484 t.Fatalf("Error storing msg: %v", err) 485 } 486 state = fs.State() 487 if state.Msgs != 10 { 488 t.Fatalf("Expected %d msgs, got %d", 10, state.Msgs) 489 } 490 if state.LastSeq != 11 { 491 t.Fatalf("Expected the last sequence to be 11 now, but got %d", state.LastSeq) 492 } 493 if state.FirstSeq != 2 { 494 t.Fatalf("Expected the first sequence to be 2 now, but got %d", state.FirstSeq) 495 } 496 // Make sure we can not lookup seq 1. 497 if _, err := fs.LoadMsg(1, nil); err == nil { 498 t.Fatalf("Expected error looking up seq 1 but got none") 499 } 500 }) 501 } 502 503 func TestFileStoreMsgLimitBug(t *testing.T) { 504 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 505 created := time.Now() 506 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage, MaxMsgs: 1}, created, prf(&fcfg), nil) 507 require_NoError(t, err) 508 defer fs.Stop() 509 510 subj, msg := "foo", []byte("Hello World") 511 fs.StoreMsg(subj, nil, msg) 512 fs.StoreMsg(subj, nil, msg) 513 fs.Stop() 514 515 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage, MaxMsgs: 1}, created, prf(&fcfg), nil) 516 require_NoError(t, err) 517 defer fs.Stop() 518 fs.StoreMsg(subj, nil, msg) 519 }) 520 } 521 522 func TestFileStoreBytesLimit(t *testing.T) { 523 subj, msg := "foo", make([]byte, 512) 524 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 525 526 toStore := uint64(1024) 527 maxBytes := storedMsgSize * toStore 528 529 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 530 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage, MaxBytes: int64(maxBytes)}, time.Now(), prf(&fcfg), nil) 531 require_NoError(t, err) 532 defer fs.Stop() 533 534 for i := uint64(0); i < toStore; i++ { 535 fs.StoreMsg(subj, nil, msg) 536 } 537 state := fs.State() 538 if state.Msgs != toStore { 539 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 540 } 541 if state.Bytes != storedMsgSize*toStore { 542 t.Fatalf("Expected bytes to be %d, got %d", storedMsgSize*toStore, state.Bytes) 543 } 544 545 // Now send 10 more and check that bytes limit enforced. 546 for i := 0; i < 10; i++ { 547 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 548 t.Fatalf("Error storing msg: %v", err) 549 } 550 } 551 state = fs.State() 552 if state.Msgs != toStore { 553 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 554 } 555 if state.Bytes != storedMsgSize*toStore { 556 t.Fatalf("Expected bytes to be %d, got %d", storedMsgSize*toStore, state.Bytes) 557 } 558 if state.FirstSeq != 11 { 559 t.Fatalf("Expected first sequence to be 11, got %d", state.FirstSeq) 560 } 561 if state.LastSeq != toStore+10 { 562 t.Fatalf("Expected last sequence to be %d, got %d", toStore+10, state.LastSeq) 563 } 564 }) 565 } 566 567 // https://github.com/nats-io/nats-server/issues/4771 568 func TestFileStoreBytesLimitWithDiscardNew(t *testing.T) { 569 subj, msg := "tiny", make([]byte, 7) 570 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 571 572 toStore := uint64(2) 573 maxBytes := 100 574 575 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 576 cfg := StreamConfig{Name: "zzz", Storage: FileStorage, MaxBytes: int64(maxBytes), Discard: DiscardNew} 577 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 578 require_NoError(t, err) 579 defer fs.Stop() 580 581 for i := 0; i < 10; i++ { 582 _, _, err := fs.StoreMsg(subj, nil, msg) 583 if i < int(toStore) { 584 if err != nil { 585 t.Fatalf("Error storing msg: %v", err) 586 } 587 } else if !errors.Is(err, ErrMaxBytes) { 588 t.Fatalf("Storing msg should result in: %v", ErrMaxBytes) 589 } 590 } 591 state := fs.State() 592 if state.Msgs != toStore { 593 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 594 } 595 if state.Bytes != storedMsgSize*toStore { 596 t.Fatalf("Expected bytes to be %d, got %d", storedMsgSize*toStore, state.Bytes) 597 } 598 }) 599 } 600 601 func TestFileStoreAgeLimit(t *testing.T) { 602 maxAge := 1 * time.Second 603 604 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 605 if fcfg.Compression != NoCompression { 606 // TODO(nat): This test fails at the moment with compression enabled 607 // because it takes longer to compress the blocks, by which time the 608 // messages have expired. Need to think about a balanced age so that 609 // the test doesn't take too long in non-compressed cases. 610 t.SkipNow() 611 } 612 613 fcfg.BlockSize = 256 614 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage, MaxAge: maxAge}, time.Now(), prf(&fcfg), nil) 615 require_NoError(t, err) 616 defer fs.Stop() 617 618 // Store some messages. Does not really matter how many. 619 subj, msg := "foo", []byte("Hello World") 620 toStore := 500 621 for i := 0; i < toStore; i++ { 622 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 623 t.Fatalf("Unexpected error: %v", err) 624 } 625 } 626 state := fs.State() 627 if state.Msgs != uint64(toStore) { 628 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 629 } 630 checkExpired := func(t *testing.T) { 631 t.Helper() 632 checkFor(t, 5*time.Second, maxAge, func() error { 633 state = fs.State() 634 if state.Msgs != 0 { 635 return fmt.Errorf("Expected no msgs, got %d", state.Msgs) 636 } 637 if state.Bytes != 0 { 638 return fmt.Errorf("Expected no bytes, got %d", state.Bytes) 639 } 640 return nil 641 }) 642 } 643 // Let them expire 644 checkExpired(t) 645 646 // Now add some more and make sure that timer will fire again. 647 for i := 0; i < toStore; i++ { 648 fs.StoreMsg(subj, nil, msg) 649 } 650 state = fs.State() 651 if state.Msgs != uint64(toStore) { 652 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 653 } 654 fs.RemoveMsg(502) 655 fs.RemoveMsg(602) 656 fs.RemoveMsg(702) 657 fs.RemoveMsg(802) 658 // We will measure the time to make sure expires works with interior deletes. 659 start := time.Now() 660 checkExpired(t) 661 if elapsed := time.Since(start); elapsed > 5*time.Second { 662 t.Fatalf("Took too long to expire: %v", elapsed) 663 } 664 }) 665 } 666 667 func TestFileStoreTimeStamps(t *testing.T) { 668 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 669 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 670 require_NoError(t, err) 671 defer fs.Stop() 672 673 last := time.Now().UnixNano() 674 subj, msg := "foo", []byte("Hello World") 675 for i := 0; i < 10; i++ { 676 time.Sleep(5 * time.Millisecond) 677 fs.StoreMsg(subj, nil, msg) 678 } 679 var smv StoreMsg 680 for seq := uint64(1); seq <= 10; seq++ { 681 sm, err := fs.LoadMsg(seq, &smv) 682 if err != nil { 683 t.Fatalf("Unexpected error looking up msg [%d]: %v", seq, err) 684 } 685 // These should be different 686 if sm.ts <= last { 687 t.Fatalf("Expected different timestamps, got last %v vs %v", last, sm.ts) 688 } 689 last = sm.ts 690 } 691 }) 692 } 693 694 func TestFileStorePurge(t *testing.T) { 695 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 696 blkSize := uint64(64 * 1024) 697 fcfg.BlockSize = blkSize 698 created := time.Now() 699 700 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 701 require_NoError(t, err) 702 defer fs.Stop() 703 704 subj, msg := "foo", make([]byte, 8*1024) 705 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 706 707 toStore := uint64(1024) 708 for i := uint64(0); i < toStore; i++ { 709 fs.StoreMsg(subj, nil, msg) 710 } 711 state := fs.State() 712 if state.Msgs != toStore { 713 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 714 } 715 if state.Bytes != storedMsgSize*toStore { 716 t.Fatalf("Expected bytes to be %d, got %d", storedMsgSize*toStore, state.Bytes) 717 } 718 719 expectedBlocks := int(storedMsgSize * toStore / blkSize) 720 if numBlocks := fs.numMsgBlocks(); numBlocks <= expectedBlocks { 721 t.Fatalf("Expected to have more then %d msg blocks, got %d", blkSize, numBlocks) 722 } 723 724 fs.Purge() 725 726 if numBlocks := fs.numMsgBlocks(); numBlocks != 1 { 727 t.Fatalf("Expected to have exactly 1 empty msg block, got %d", numBlocks) 728 } 729 730 checkPurgeState := func(stored uint64) { 731 t.Helper() 732 state = fs.State() 733 if state.Msgs != 0 { 734 t.Fatalf("Expected 0 msgs after purge, got %d", state.Msgs) 735 } 736 if state.Bytes != 0 { 737 t.Fatalf("Expected 0 bytes after purge, got %d", state.Bytes) 738 } 739 if state.LastSeq != stored { 740 t.Fatalf("Expected LastSeq to be %d., got %d", toStore, state.LastSeq) 741 } 742 if state.FirstSeq != stored+1 { 743 t.Fatalf("Expected FirstSeq to be %d., got %d", toStore+1, state.FirstSeq) 744 } 745 } 746 checkPurgeState(toStore) 747 748 // Make sure we recover same state. 749 fs.Stop() 750 751 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 752 require_NoError(t, err) 753 defer fs.Stop() 754 755 if numBlocks := fs.numMsgBlocks(); numBlocks != 1 { 756 t.Fatalf("Expected to have exactly 1 empty msg block, got %d", numBlocks) 757 } 758 759 checkPurgeState(toStore) 760 761 // Now make sure we clean up any dangling purged messages. 762 for i := uint64(0); i < toStore; i++ { 763 fs.StoreMsg(subj, nil, msg) 764 } 765 state = fs.State() 766 if state.Msgs != toStore { 767 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 768 } 769 if state.Bytes != storedMsgSize*toStore { 770 t.Fatalf("Expected bytes to be %d, got %d", storedMsgSize*toStore, state.Bytes) 771 } 772 773 // We will simulate crashing before the purge directory is cleared. 774 mdir := filepath.Join(fs.fcfg.StoreDir, msgDir) 775 pdir := filepath.Join(fs.fcfg.StoreDir, "ptest") 776 os.Rename(mdir, pdir) 777 os.MkdirAll(mdir, 0755) 778 779 fs.Purge() 780 checkPurgeState(toStore * 2) 781 782 // Make sure we recover same state. 783 fs.Stop() 784 785 purgeDir := filepath.Join(fs.fcfg.StoreDir, purgeDir) 786 os.Rename(pdir, purgeDir) 787 788 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 789 require_NoError(t, err) 790 defer fs.Stop() 791 792 if numBlocks := fs.numMsgBlocks(); numBlocks != 1 { 793 t.Fatalf("Expected to have exactly 1 empty msg block, got %d", numBlocks) 794 } 795 796 checkPurgeState(toStore * 2) 797 798 checkFor(t, 2*time.Second, 100*time.Millisecond, func() error { 799 if _, err := os.Stat(purgeDir); err == nil { 800 return fmt.Errorf("purge directory still present") 801 } 802 return nil 803 }) 804 }) 805 } 806 807 func TestFileStoreCompact(t *testing.T) { 808 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 809 fcfg.BlockSize = 350 810 created := time.Now() 811 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 812 require_NoError(t, err) 813 defer fs.Stop() 814 815 subj, msg := "foo", []byte("Hello World") 816 for i := 0; i < 10; i++ { 817 fs.StoreMsg(subj, nil, msg) 818 } 819 if state := fs.State(); state.Msgs != 10 { 820 t.Fatalf("Expected 10 msgs, got %d", state.Msgs) 821 } 822 n, err := fs.Compact(6) 823 if err != nil { 824 t.Fatalf("Unexpected error: %v", err) 825 } 826 if n != 5 { 827 t.Fatalf("Expected to have purged 5 msgs, got %d", n) 828 } 829 state := fs.State() 830 if state.Msgs != 5 { 831 t.Fatalf("Expected 5 msgs, got %d", state.Msgs) 832 } 833 if state.FirstSeq != 6 { 834 t.Fatalf("Expected first seq of 6, got %d", state.FirstSeq) 835 } 836 // Now test that compact will also reset first if seq > last 837 n, err = fs.Compact(100) 838 if err != nil { 839 t.Fatalf("Unexpected error: %v", err) 840 } 841 if n != 5 { 842 t.Fatalf("Expected to have purged 5 msgs, got %d", n) 843 } 844 if state = fs.State(); state.FirstSeq != 100 { 845 t.Fatalf("Expected first seq of 100, got %d", state.FirstSeq) 846 } 847 848 fs.Stop() 849 850 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 851 require_NoError(t, err) 852 defer fs.Stop() 853 854 if state = fs.State(); state.FirstSeq != 100 { 855 t.Fatalf("Expected first seq of 100, got %d", state.FirstSeq) 856 } 857 }) 858 } 859 860 func TestFileStoreCompactLastPlusOne(t *testing.T) { 861 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 862 fcfg.BlockSize = 8192 863 fcfg.AsyncFlush = true 864 865 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 866 require_NoError(t, err) 867 defer fs.Stop() 868 869 subj, msg := "foo", make([]byte, 10_000) 870 for i := 0; i < 10_000; i++ { 871 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 872 t.Fatalf("Unexpected error: %v", err) 873 } 874 } 875 876 // The performance of this test is quite terrible with compression 877 // if we have AsyncFlush = false, so we'll batch flushes instead. 878 fs.mu.Lock() 879 fs.checkAndFlushAllBlocks() 880 fs.mu.Unlock() 881 882 if state := fs.State(); state.Msgs != 10_000 { 883 t.Fatalf("Expected 1000000 msgs, got %d", state.Msgs) 884 } 885 if _, err := fs.Compact(10_001); err != nil { 886 t.Fatalf("Unexpected error: %v", err) 887 } 888 state := fs.State() 889 if state.Msgs != 0 { 890 t.Fatalf("Expected no message but got %d", state.Msgs) 891 } 892 893 fs.StoreMsg(subj, nil, msg) 894 state = fs.State() 895 if state.Msgs != 1 { 896 t.Fatalf("Expected one message but got %d", state.Msgs) 897 } 898 }) 899 } 900 901 func TestFileStoreCompactMsgCountBug(t *testing.T) { 902 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 903 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 904 require_NoError(t, err) 905 defer fs.Stop() 906 907 subj, msg := "foo", []byte("Hello World") 908 for i := 0; i < 10; i++ { 909 fs.StoreMsg(subj, nil, msg) 910 } 911 if state := fs.State(); state.Msgs != 10 { 912 t.Fatalf("Expected 10 msgs, got %d", state.Msgs) 913 } 914 // Now delete 2,3,4. 915 fs.EraseMsg(2) 916 fs.EraseMsg(3) 917 fs.EraseMsg(4) 918 919 // Also delete 7,8, and 9. 920 fs.RemoveMsg(7) 921 fs.RemoveMsg(8) 922 fs.RemoveMsg(9) 923 924 n, err := fs.Compact(6) 925 if err != nil { 926 t.Fatalf("Unexpected error: %v", err) 927 } 928 // 1 & 5 929 if n != 2 { 930 t.Fatalf("Expected to have deleted 2 msgs, got %d", n) 931 } 932 if state := fs.State(); state.Msgs != 2 { 933 t.Fatalf("Expected to have 2 remaining, got %d", state.Msgs) 934 } 935 }) 936 } 937 938 func TestFileStoreCompactPerf(t *testing.T) { 939 t.SkipNow() 940 941 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 942 fcfg.BlockSize = 8192 943 fcfg.AsyncFlush = true 944 945 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 946 require_NoError(t, err) 947 defer fs.Stop() 948 949 subj, msg := "foo", []byte("Hello World") 950 for i := 0; i < 100_000; i++ { 951 fs.StoreMsg(subj, nil, msg) 952 } 953 if state := fs.State(); state.Msgs != 100_000 { 954 t.Fatalf("Expected 1000000 msgs, got %d", state.Msgs) 955 } 956 start := time.Now() 957 n, err := fs.Compact(90_001) 958 if err != nil { 959 t.Fatalf("Unexpected error: %v", err) 960 } 961 t.Logf("Took %v to compact\n", time.Since(start)) 962 963 if n != 90_000 { 964 t.Fatalf("Expected to have purged 90_000 msgs, got %d", n) 965 } 966 state := fs.State() 967 if state.Msgs != 10_000 { 968 t.Fatalf("Expected 10_000 msgs, got %d", state.Msgs) 969 } 970 if state.FirstSeq != 90_001 { 971 t.Fatalf("Expected first seq of 90_001, got %d", state.FirstSeq) 972 } 973 }) 974 } 975 976 func TestFileStoreStreamTruncate(t *testing.T) { 977 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 978 fcfg.BlockSize = 350 979 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 980 created := time.Now() 981 982 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 983 require_NoError(t, err) 984 defer fs.Stop() 985 986 tseq := uint64(50) 987 988 subj, toStore := "foo", uint64(100) 989 for i := uint64(1); i < tseq; i++ { 990 _, _, err := fs.StoreMsg(subj, nil, []byte("ok")) 991 require_NoError(t, err) 992 } 993 subj = "bar" 994 for i := tseq; i <= toStore; i++ { 995 _, _, err := fs.StoreMsg(subj, nil, []byte("ok")) 996 require_NoError(t, err) 997 } 998 999 if state := fs.State(); state.Msgs != toStore { 1000 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 1001 } 1002 1003 // Check that sequence has to be interior. 1004 if err := fs.Truncate(toStore + 1); err != ErrInvalidSequence { 1005 t.Fatalf("Expected err of '%v', got '%v'", ErrInvalidSequence, err) 1006 } 1007 1008 if err := fs.Truncate(tseq); err != nil { 1009 t.Fatalf("Unexpected error: %v", err) 1010 } 1011 if state := fs.State(); state.Msgs != tseq { 1012 t.Fatalf("Expected %d msgs, got %d", tseq, state.Msgs) 1013 } 1014 1015 // Now make sure we report properly if we have some deleted interior messages. 1016 fs.RemoveMsg(10) 1017 fs.RemoveMsg(20) 1018 fs.RemoveMsg(30) 1019 fs.RemoveMsg(40) 1020 1021 tseq = uint64(25) 1022 if err := fs.Truncate(tseq); err != nil { 1023 t.Fatalf("Unexpected error: %v", err) 1024 } 1025 state := fs.State() 1026 if state.Msgs != tseq-2 { 1027 t.Fatalf("Expected %d msgs, got %d", tseq-2, state.Msgs) 1028 } 1029 expected := []uint64{10, 20} 1030 if !reflect.DeepEqual(state.Deleted, expected) { 1031 t.Fatalf("Expected deleted to be %+v, got %+v\n", expected, state.Deleted) 1032 } 1033 1034 before := state 1035 1036 // Make sure we can recover same state. 1037 fs.Stop() 1038 1039 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 1040 require_NoError(t, err) 1041 defer fs.Stop() 1042 1043 if state := fs.State(); !reflect.DeepEqual(state, before) { 1044 t.Fatalf("Expected state of %+v, got %+v", before, state) 1045 } 1046 1047 mb := fs.getFirstBlock() 1048 require_True(t, mb != nil) 1049 require_NoError(t, mb.loadMsgs()) 1050 }) 1051 } 1052 1053 func TestFileStoreRemovePartialRecovery(t *testing.T) { 1054 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1055 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 1056 created := time.Now() 1057 1058 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 1059 require_NoError(t, err) 1060 defer fs.Stop() 1061 1062 subj, msg := "foo", []byte("Hello World") 1063 toStore := 100 1064 for i := 0; i < toStore; i++ { 1065 fs.StoreMsg(subj, nil, msg) 1066 } 1067 state := fs.State() 1068 if state.Msgs != uint64(toStore) { 1069 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 1070 } 1071 1072 // Remove half 1073 for i := 1; i <= toStore/2; i++ { 1074 fs.RemoveMsg(uint64(i)) 1075 } 1076 1077 state = fs.State() 1078 if state.Msgs != uint64(toStore/2) { 1079 t.Fatalf("Expected %d msgs, got %d", toStore/2, state.Msgs) 1080 } 1081 1082 // Make sure we recover same state. 1083 fs.Stop() 1084 1085 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 1086 require_NoError(t, err) 1087 defer fs.Stop() 1088 1089 state2 := fs.State() 1090 if !reflect.DeepEqual(state2, state) { 1091 t.Fatalf("Expected recovered state to be the same, got %+v vs %+v\n", state2, state) 1092 } 1093 }) 1094 } 1095 1096 func TestFileStoreRemoveOutOfOrderRecovery(t *testing.T) { 1097 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1098 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 1099 created := time.Now() 1100 1101 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 1102 require_NoError(t, err) 1103 defer fs.Stop() 1104 1105 subj, msg := "foo", []byte("Hello World") 1106 toStore := 100 1107 for i := 0; i < toStore; i++ { 1108 fs.StoreMsg(subj, nil, msg) 1109 } 1110 state := fs.State() 1111 if state.Msgs != uint64(toStore) { 1112 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 1113 } 1114 1115 // Remove evens 1116 for i := 2; i <= toStore; i += 2 { 1117 if removed, _ := fs.RemoveMsg(uint64(i)); !removed { 1118 t.Fatalf("Expected remove to return true") 1119 } 1120 } 1121 1122 state = fs.State() 1123 if state.Msgs != uint64(toStore/2) { 1124 t.Fatalf("Expected %d msgs, got %d", toStore/2, state.Msgs) 1125 } 1126 1127 var smv StoreMsg 1128 if _, err := fs.LoadMsg(1, &smv); err != nil { 1129 t.Fatalf("Expected to retrieve seq 1") 1130 } 1131 for i := 2; i <= toStore; i += 2 { 1132 if _, err := fs.LoadMsg(uint64(i), &smv); err == nil { 1133 t.Fatalf("Expected error looking up seq %d that should be deleted", i) 1134 } 1135 } 1136 1137 // Make sure we recover same state. 1138 fs.Stop() 1139 1140 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 1141 require_NoError(t, err) 1142 defer fs.Stop() 1143 1144 state2 := fs.State() 1145 if !reflect.DeepEqual(state2, state) { 1146 t.Fatalf("Expected recovered states to be the same, got %+v vs %+v\n", state, state2) 1147 } 1148 1149 if _, err := fs.LoadMsg(1, &smv); err != nil { 1150 t.Fatalf("Expected to retrieve seq 1") 1151 } 1152 for i := 2; i <= toStore; i += 2 { 1153 if _, err := fs.LoadMsg(uint64(i), nil); err == nil { 1154 t.Fatalf("Expected error looking up seq %d that should be deleted", i) 1155 } 1156 } 1157 }) 1158 } 1159 1160 func TestFileStoreAgeLimitRecovery(t *testing.T) { 1161 maxAge := 1 * time.Second 1162 1163 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1164 fcfg.CacheExpire = 1 * time.Millisecond 1165 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage, MaxAge: maxAge} 1166 created := time.Now() 1167 1168 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 1169 require_NoError(t, err) 1170 defer fs.Stop() 1171 1172 // Store some messages. Does not really matter how many. 1173 subj, msg := "foo", []byte("Hello World") 1174 toStore := 100 1175 for i := 0; i < toStore; i++ { 1176 fs.StoreMsg(subj, nil, msg) 1177 } 1178 state := fs.State() 1179 if state.Msgs != uint64(toStore) { 1180 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 1181 } 1182 fs.Stop() 1183 1184 time.Sleep(maxAge) 1185 1186 fcfg.CacheExpire = 0 1187 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 1188 require_NoError(t, err) 1189 defer fs.Stop() 1190 1191 // Make sure they expire. 1192 checkFor(t, time.Second, 2*maxAge, func() error { 1193 t.Helper() 1194 state = fs.State() 1195 if state.Msgs != 0 { 1196 return fmt.Errorf("Expected no msgs, got %d", state.Msgs) 1197 } 1198 if state.Bytes != 0 { 1199 return fmt.Errorf("Expected no bytes, got %d", state.Bytes) 1200 } 1201 return nil 1202 }) 1203 }) 1204 } 1205 1206 func TestFileStoreBitRot(t *testing.T) { 1207 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1208 created := time.Now() 1209 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 1210 require_NoError(t, err) 1211 defer fs.Stop() 1212 1213 // Store some messages. Does not really matter how many. 1214 subj, msg := "foo", []byte("Hello World") 1215 toStore := 100 1216 for i := 0; i < toStore; i++ { 1217 fs.StoreMsg(subj, nil, msg) 1218 } 1219 state := fs.State() 1220 if state.Msgs != uint64(toStore) { 1221 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 1222 } 1223 1224 if ld := fs.checkMsgs(); ld != nil && len(ld.Msgs) > 0 { 1225 t.Fatalf("Expected to have no corrupt msgs, got %d", len(ld.Msgs)) 1226 } 1227 1228 for i := 0; i < 10; i++ { 1229 // Now twiddle some bits. 1230 fs.mu.Lock() 1231 lmb := fs.lmb 1232 contents, err := os.ReadFile(lmb.mfn) 1233 require_NoError(t, err) 1234 require_True(t, len(contents) > 0) 1235 1236 var index int 1237 for { 1238 index = rand.Intn(len(contents)) 1239 // Reverse one byte anywhere. 1240 b := contents[index] 1241 contents[index] = bits.Reverse8(b) 1242 if b != contents[index] { 1243 break 1244 } 1245 } 1246 os.WriteFile(lmb.mfn, contents, 0644) 1247 fs.mu.Unlock() 1248 1249 ld := fs.checkMsgs() 1250 if len(ld.Msgs) > 0 { 1251 break 1252 } 1253 // If our bitrot caused us to not be able to recover any messages we can break as well. 1254 if state := fs.State(); state.Msgs == 0 { 1255 break 1256 } 1257 // Fail the test if we have tried the 10 times and still did not 1258 // get any corruption report. 1259 if i == 9 { 1260 t.Fatalf("Expected to have corrupt msgs got none: changed [%d]", index) 1261 } 1262 } 1263 1264 // Make sure we can restore. 1265 fs.Stop() 1266 1267 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 1268 require_NoError(t, err) 1269 defer fs.Stop() 1270 1271 // checkMsgs will repair the underlying store, so checkMsgs should be clean now. 1272 if ld := fs.checkMsgs(); ld != nil { 1273 // If we have no msgs left this will report the head msgs as lost again. 1274 if state := fs.State(); state.Msgs > 0 { 1275 t.Fatalf("Expected no errors restoring checked and fixed filestore, got %+v", ld) 1276 } 1277 } 1278 }) 1279 } 1280 1281 func TestFileStoreEraseMsg(t *testing.T) { 1282 // Just do no encryption, etc. 1283 fcfg := FileStoreConfig{StoreDir: t.TempDir()} 1284 fs, err := newFileStore(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}) 1285 require_NoError(t, err) 1286 defer fs.Stop() 1287 1288 subj, msg := "foo", []byte("Hello World") 1289 fs.StoreMsg(subj, nil, msg) 1290 fs.StoreMsg(subj, nil, msg) // To keep block from being deleted. 1291 var smv StoreMsg 1292 sm, err := fs.LoadMsg(1, &smv) 1293 if err != nil { 1294 t.Fatalf("Unexpected error looking up msg: %v", err) 1295 } 1296 if !bytes.Equal(msg, sm.msg) { 1297 t.Fatalf("Expected same msg, got %q vs %q", sm.msg, msg) 1298 } 1299 if removed, _ := fs.EraseMsg(1); !removed { 1300 t.Fatalf("Expected erase msg to return success") 1301 } 1302 if sm2, _ := fs.msgForSeq(1, nil); sm2 != nil { 1303 t.Fatalf("Expected msg to be erased") 1304 } 1305 fs.checkAndFlushAllBlocks() 1306 1307 // Now look on disk as well. 1308 rl := fileStoreMsgSize(subj, nil, msg) 1309 buf := make([]byte, rl) 1310 fp, err := os.Open(filepath.Join(fcfg.StoreDir, msgDir, fmt.Sprintf(blkScan, 1))) 1311 if err != nil { 1312 t.Fatalf("Error opening msg block file: %v", err) 1313 } 1314 defer fp.Close() 1315 1316 fp.ReadAt(buf, 0) 1317 fs.mu.RLock() 1318 mb := fs.blks[0] 1319 fs.mu.RUnlock() 1320 mb.mu.Lock() 1321 sm, err = mb.msgFromBuf(buf, nil, nil) 1322 mb.mu.Unlock() 1323 if err != nil { 1324 t.Fatalf("error reading message from block: %v", err) 1325 } 1326 if sm.subj == subj { 1327 t.Fatalf("Expected the subjects to be different") 1328 } 1329 if sm.seq != 0 && sm.seq&ebit == 0 { 1330 t.Fatalf("Expected seq to be 0, marking as deleted, got %d", sm.seq) 1331 } 1332 if sm.ts != 0 { 1333 t.Fatalf("Expected timestamp to be 0, got %d", sm.ts) 1334 } 1335 if bytes.Equal(sm.msg, msg) { 1336 t.Fatalf("Expected message body to be randomized") 1337 } 1338 } 1339 1340 func TestFileStoreEraseAndNoIndexRecovery(t *testing.T) { 1341 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1342 created := time.Now() 1343 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 1344 require_NoError(t, err) 1345 defer fs.Stop() 1346 1347 subj, msg := "foo", []byte("Hello World") 1348 toStore := 100 1349 for i := 0; i < toStore; i++ { 1350 fs.StoreMsg(subj, nil, msg) 1351 } 1352 state := fs.State() 1353 if state.Msgs != uint64(toStore) { 1354 t.Fatalf("Expected %d msgs, got %d", toStore, state.Msgs) 1355 } 1356 1357 // Erase the even messages. 1358 for i := 2; i <= toStore; i += 2 { 1359 if removed, _ := fs.EraseMsg(uint64(i)); !removed { 1360 t.Fatalf("Expected erase msg to return true") 1361 } 1362 } 1363 state = fs.State() 1364 if state.Msgs != uint64(toStore/2) { 1365 t.Fatalf("Expected %d msgs, got %d", toStore/2, state.Msgs) 1366 } 1367 1368 // Stop and remove the optional index file. 1369 fs.Stop() 1370 ifn := filepath.Join(fcfg.StoreDir, msgDir, fmt.Sprintf(indexScan, 1)) 1371 os.Remove(ifn) 1372 1373 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 1374 require_NoError(t, err) 1375 defer fs.Stop() 1376 1377 state = fs.State() 1378 if state.Msgs != uint64(toStore/2) { 1379 t.Fatalf("Expected %d msgs, got %d", toStore/2, state.Msgs) 1380 } 1381 1382 for i := 2; i <= toStore; i += 2 { 1383 if _, err := fs.LoadMsg(uint64(i), nil); err == nil { 1384 t.Fatalf("Expected error looking up seq %d that should be erased", i) 1385 } 1386 } 1387 }) 1388 } 1389 1390 func TestFileStoreMeta(t *testing.T) { 1391 // Just do no encryption, etc. 1392 fcfg := FileStoreConfig{StoreDir: t.TempDir()} 1393 mconfig := StreamConfig{Name: "ZZ-22-33", Storage: FileStorage, Subjects: []string{"foo.*"}, Replicas: 22} 1394 fs, err := newFileStore(fcfg, mconfig) 1395 require_NoError(t, err) 1396 defer fs.Stop() 1397 1398 metafile := filepath.Join(fcfg.StoreDir, JetStreamMetaFile) 1399 metasum := filepath.Join(fcfg.StoreDir, JetStreamMetaFileSum) 1400 1401 // Test to make sure meta file and checksum are present. 1402 if _, err := os.Stat(metafile); os.IsNotExist(err) { 1403 t.Fatalf("Expected metafile %q to exist", metafile) 1404 } 1405 if _, err := os.Stat(metasum); os.IsNotExist(err) { 1406 t.Fatalf("Expected metafile's checksum %q to exist", metasum) 1407 } 1408 1409 buf, err := os.ReadFile(metafile) 1410 if err != nil { 1411 t.Fatalf("Error reading metafile: %v", err) 1412 } 1413 var mconfig2 StreamConfig 1414 if err := json.Unmarshal(buf, &mconfig2); err != nil { 1415 t.Fatalf("Error unmarshalling: %v", err) 1416 } 1417 if !reflect.DeepEqual(mconfig, mconfig2) { 1418 t.Fatalf("Stream configs not equal, got %+v vs %+v", mconfig2, mconfig) 1419 } 1420 checksum, err := os.ReadFile(metasum) 1421 if err != nil { 1422 t.Fatalf("Error reading metafile checksum: %v", err) 1423 } 1424 1425 fs.mu.Lock() 1426 fs.hh.Reset() 1427 fs.hh.Write(buf) 1428 mychecksum := hex.EncodeToString(fs.hh.Sum(nil)) 1429 fs.mu.Unlock() 1430 1431 if mychecksum != string(checksum) { 1432 t.Fatalf("Checksums do not match, got %q vs %q", mychecksum, checksum) 1433 } 1434 1435 // Now create a consumer. Same deal for them. 1436 oconfig := ConsumerConfig{ 1437 DeliverSubject: "d", 1438 FilterSubject: "foo", 1439 AckPolicy: AckAll, 1440 } 1441 oname := "obs22" 1442 obs, err := fs.ConsumerStore(oname, &oconfig) 1443 if err != nil { 1444 t.Fatalf("Unexpected error: %v", err) 1445 } 1446 1447 ometafile := filepath.Join(fcfg.StoreDir, consumerDir, oname, JetStreamMetaFile) 1448 ometasum := filepath.Join(fcfg.StoreDir, consumerDir, oname, JetStreamMetaFileSum) 1449 1450 // Test to make sure meta file and checksum are present. 1451 if _, err := os.Stat(ometafile); os.IsNotExist(err) { 1452 t.Fatalf("Expected consumer metafile %q to exist", ometafile) 1453 } 1454 if _, err := os.Stat(ometasum); os.IsNotExist(err) { 1455 t.Fatalf("Expected consumer metafile's checksum %q to exist", ometasum) 1456 } 1457 1458 buf, err = os.ReadFile(ometafile) 1459 if err != nil { 1460 t.Fatalf("Error reading consumer metafile: %v", err) 1461 } 1462 1463 var oconfig2 ConsumerConfig 1464 if err := json.Unmarshal(buf, &oconfig2); err != nil { 1465 t.Fatalf("Error unmarshalling: %v", err) 1466 } 1467 // Since we set name we will get that back now. 1468 oconfig.Name = oname 1469 if !reflect.DeepEqual(oconfig2, oconfig) { 1470 t.Fatalf("Consumer configs not equal, got %+v vs %+v", oconfig2, oconfig) 1471 } 1472 checksum, err = os.ReadFile(ometasum) 1473 1474 if err != nil { 1475 t.Fatalf("Error reading consumer metafile checksum: %v", err) 1476 } 1477 1478 hh := obs.(*consumerFileStore).hh 1479 hh.Reset() 1480 hh.Write(buf) 1481 mychecksum = hex.EncodeToString(hh.Sum(nil)) 1482 if mychecksum != string(checksum) { 1483 t.Fatalf("Checksums do not match, got %q vs %q", mychecksum, checksum) 1484 } 1485 } 1486 1487 func TestFileStoreWriteAndReadSameBlock(t *testing.T) { 1488 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1489 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 1490 require_NoError(t, err) 1491 defer fs.Stop() 1492 1493 subj, msg := "foo", []byte("Hello World!") 1494 1495 for i := uint64(1); i <= 10; i++ { 1496 fs.StoreMsg(subj, nil, msg) 1497 if _, err := fs.LoadMsg(i, nil); err != nil { 1498 t.Fatalf("Error loading %d: %v", i, err) 1499 } 1500 } 1501 }) 1502 } 1503 1504 func TestFileStoreAndRetrieveMultiBlock(t *testing.T) { 1505 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1506 subj, msg := "foo", []byte("Hello World!") 1507 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 1508 1509 fcfg.BlockSize = 4 * storedMsgSize 1510 created := time.Now() 1511 1512 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 1513 require_NoError(t, err) 1514 defer fs.Stop() 1515 1516 for i := 0; i < 20; i++ { 1517 fs.StoreMsg(subj, nil, msg) 1518 } 1519 state := fs.State() 1520 if state.Msgs != 20 { 1521 t.Fatalf("Expected 20 msgs, got %d", state.Msgs) 1522 } 1523 fs.Stop() 1524 1525 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 1526 require_NoError(t, err) 1527 defer fs.Stop() 1528 1529 var smv StoreMsg 1530 for i := uint64(1); i <= 20; i++ { 1531 if _, err := fs.LoadMsg(i, &smv); err != nil { 1532 t.Fatalf("Error loading %d: %v", i, err) 1533 } 1534 } 1535 }) 1536 } 1537 1538 func TestFileStoreCollapseDmap(t *testing.T) { 1539 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1540 subj, msg := "foo", []byte("Hello World!") 1541 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 1542 1543 fcfg.BlockSize = 4 * storedMsgSize 1544 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 1545 require_NoError(t, err) 1546 defer fs.Stop() 1547 1548 for i := 0; i < 10; i++ { 1549 fs.StoreMsg(subj, nil, msg) 1550 } 1551 state := fs.State() 1552 if state.Msgs != 10 { 1553 t.Fatalf("Expected 10 msgs, got %d", state.Msgs) 1554 } 1555 1556 checkDmapTotal := func(total int) { 1557 t.Helper() 1558 if nde := fs.dmapEntries(); nde != total { 1559 t.Fatalf("Expecting only %d entries, got %d", total, nde) 1560 } 1561 } 1562 1563 checkFirstSeq := func(seq uint64) { 1564 t.Helper() 1565 state := fs.State() 1566 if state.FirstSeq != seq { 1567 t.Fatalf("Expected first seq to be %d, got %d", seq, state.FirstSeq) 1568 } 1569 } 1570 1571 // Now remove some out of order, forming gaps and entries in dmaps. 1572 fs.RemoveMsg(2) 1573 checkFirstSeq(1) 1574 fs.RemoveMsg(4) 1575 checkFirstSeq(1) 1576 fs.RemoveMsg(8) 1577 checkFirstSeq(1) 1578 1579 state = fs.State() 1580 if state.Msgs != 7 { 1581 t.Fatalf("Expected 7 msgs, got %d", state.Msgs) 1582 } 1583 1584 checkDmapTotal(3) 1585 1586 // Close gaps.. 1587 fs.RemoveMsg(1) 1588 checkDmapTotal(2) 1589 checkFirstSeq(3) 1590 1591 fs.RemoveMsg(3) 1592 checkDmapTotal(1) 1593 checkFirstSeq(5) 1594 1595 fs.RemoveMsg(5) 1596 checkDmapTotal(1) 1597 checkFirstSeq(6) 1598 1599 fs.RemoveMsg(7) 1600 checkDmapTotal(2) 1601 1602 fs.RemoveMsg(6) 1603 checkDmapTotal(0) 1604 }) 1605 } 1606 1607 func TestFileStoreReadCache(t *testing.T) { 1608 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1609 fcfg.CacheExpire = 100 * time.Millisecond 1610 1611 subj, msg := "foo.bar", make([]byte, 1024) 1612 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 1613 1614 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 1615 require_NoError(t, err) 1616 defer fs.Stop() 1617 1618 toStore := 500 1619 totalBytes := uint64(toStore) * storedMsgSize 1620 1621 for i := 0; i < toStore; i++ { 1622 fs.StoreMsg(subj, nil, msg) 1623 } 1624 1625 // Wait for cache to go to zero. 1626 checkFor(t, time.Second, 10*time.Millisecond, func() error { 1627 if csz := fs.cacheSize(); csz != 0 { 1628 return fmt.Errorf("cache size not 0, got %s", friendlyBytes(int64(csz))) 1629 } 1630 return nil 1631 }) 1632 1633 fs.LoadMsg(1, nil) 1634 if csz := fs.cacheSize(); csz != totalBytes { 1635 t.Fatalf("Expected all messages to be cached, got %d vs %d", csz, totalBytes) 1636 } 1637 // Should expire and be removed. 1638 checkFor(t, time.Second, 10*time.Millisecond, func() error { 1639 if csz := fs.cacheSize(); csz != 0 { 1640 return fmt.Errorf("cache size not 0, got %s", friendlyBytes(int64(csz))) 1641 } 1642 return nil 1643 }) 1644 if cls := fs.cacheLoads(); cls != 1 { 1645 t.Fatalf("Expected only 1 cache load, got %d", cls) 1646 } 1647 // Now make sure we do not reload cache if there is activity. 1648 fs.LoadMsg(1, nil) 1649 timeout := time.Now().Add(250 * time.Millisecond) 1650 for time.Now().Before(timeout) { 1651 if cls := fs.cacheLoads(); cls != 2 { 1652 t.Fatalf("cache loads not 2, got %d", cls) 1653 } 1654 time.Sleep(5 * time.Millisecond) 1655 fs.LoadMsg(1, nil) // register activity. 1656 } 1657 }) 1658 } 1659 1660 func TestFileStorePartialCacheExpiration(t *testing.T) { 1661 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1662 cexp := 10 * time.Millisecond 1663 fcfg.CacheExpire = cexp 1664 1665 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 1666 require_NoError(t, err) 1667 defer fs.Stop() 1668 1669 fs.StoreMsg("foo", nil, []byte("msg1")) 1670 1671 // Should expire and be removed. 1672 time.Sleep(2 * cexp) 1673 fs.StoreMsg("bar", nil, []byte("msg2")) 1674 1675 // Again wait for cache to expire. 1676 time.Sleep(2 * cexp) 1677 if _, err := fs.LoadMsg(1, nil); err != nil { 1678 t.Fatalf("Error loading message 1: %v", err) 1679 } 1680 }) 1681 } 1682 1683 func TestFileStorePartialIndexes(t *testing.T) { 1684 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1685 cexp := 10 * time.Millisecond 1686 fcfg.CacheExpire = cexp 1687 1688 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 1689 require_NoError(t, err) 1690 defer fs.Stop() 1691 1692 toSend := 5 1693 for i := 0; i < toSend; i++ { 1694 fs.StoreMsg("foo", nil, []byte("ok-1")) 1695 } 1696 1697 // Now wait til the cache expires, including the index. 1698 fs.mu.Lock() 1699 mb := fs.blks[0] 1700 fs.mu.Unlock() 1701 1702 // Force idx to expire by resetting last remove ts. 1703 mb.mu.Lock() 1704 mb.llts = mb.llts - int64(defaultCacheBufferExpiration*2) 1705 mb.mu.Unlock() 1706 1707 checkFor(t, time.Second, 10*time.Millisecond, func() error { 1708 mb.mu.Lock() 1709 defer mb.mu.Unlock() 1710 if mb.cache == nil || len(mb.cache.idx) == 0 { 1711 return nil 1712 } 1713 return fmt.Errorf("Index not empty") 1714 }) 1715 1716 // Create a partial cache by adding more msgs. 1717 for i := 0; i < toSend; i++ { 1718 fs.StoreMsg("foo", nil, []byte("ok-2")) 1719 } 1720 // If we now load in a message in second half if we do not 1721 // detect idx is a partial correctly this will panic. 1722 if _, err := fs.LoadMsg(8, nil); err != nil { 1723 t.Fatalf("Error loading %d: %v", 1, err) 1724 } 1725 }) 1726 } 1727 1728 func TestFileStoreSnapshot(t *testing.T) { 1729 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1730 subj, msg := "foo", []byte("Hello Snappy!") 1731 scfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 1732 1733 fs, err := newFileStoreWithCreated(fcfg, scfg, time.Now(), prf(&fcfg), nil) 1734 require_NoError(t, err) 1735 defer fs.Stop() 1736 1737 toSend := 2233 1738 for i := 0; i < toSend; i++ { 1739 fs.StoreMsg(subj, nil, msg) 1740 } 1741 1742 // Create a few consumers. 1743 o1, err := fs.ConsumerStore("o22", &ConsumerConfig{}) 1744 if err != nil { 1745 t.Fatalf("Unexpected error: %v", err) 1746 } 1747 o2, err := fs.ConsumerStore("o33", &ConsumerConfig{}) 1748 if err != nil { 1749 t.Fatalf("Unexpected error: %v", err) 1750 } 1751 state := &ConsumerState{} 1752 state.Delivered.Consumer = 100 1753 state.Delivered.Stream = 100 1754 state.AckFloor.Consumer = 22 1755 state.AckFloor.Stream = 22 1756 1757 if err := o1.Update(state); err != nil { 1758 t.Fatalf("Unexpected error updating state: %v", err) 1759 } 1760 state.AckFloor.Consumer = 33 1761 state.AckFloor.Stream = 33 1762 1763 if err := o2.Update(state); err != nil { 1764 t.Fatalf("Unexpected error updating state: %v", err) 1765 } 1766 1767 snapshot := func() []byte { 1768 t.Helper() 1769 r, err := fs.Snapshot(5*time.Second, true, true) 1770 if err != nil { 1771 t.Fatalf("Error creating snapshot") 1772 } 1773 snapshot, err := io.ReadAll(r.Reader) 1774 if err != nil { 1775 t.Fatalf("Error reading snapshot") 1776 } 1777 return snapshot 1778 } 1779 1780 // This will unzip the snapshot and create a new filestore that will recover the state. 1781 // We will compare the states for this vs the original one. 1782 verifySnapshot := func(snap []byte) { 1783 t.Helper() 1784 r := bytes.NewReader(snap) 1785 tr := tar.NewReader(s2.NewReader(r)) 1786 1787 rstoreDir := t.TempDir() 1788 1789 for { 1790 hdr, err := tr.Next() 1791 if err == io.EOF { 1792 break // End of archive 1793 } 1794 if err != nil { 1795 t.Fatalf("Error getting next entry from snapshot: %v", err) 1796 } 1797 fpath := filepath.Join(rstoreDir, filepath.Clean(hdr.Name)) 1798 pdir := filepath.Dir(fpath) 1799 os.MkdirAll(pdir, 0755) 1800 fd, err := os.OpenFile(fpath, os.O_CREATE|os.O_RDWR, 0600) 1801 if err != nil { 1802 t.Fatalf("Error opening file[%s]: %v", fpath, err) 1803 } 1804 if _, err := io.Copy(fd, tr); err != nil { 1805 t.Fatalf("Error writing file[%s]: %v", fpath, err) 1806 } 1807 fd.Close() 1808 } 1809 1810 fcfg.StoreDir = rstoreDir 1811 fsr, err := newFileStoreWithCreated(fcfg, scfg, time.Now(), prf(&fcfg), nil) 1812 require_NoError(t, err) 1813 defer fsr.Stop() 1814 state := fs.State() 1815 rstate := fsr.State() 1816 1817 // FIXME(dlc) 1818 // Right now the upper layers in JetStream recover the consumers and do not expect 1819 // the lower layers to do that. So for now blank that out of our original state. 1820 // Will have more exhaustive tests in jetstream_test.go. 1821 state.Consumers = 0 1822 1823 // Just check the state. 1824 if !reflect.DeepEqual(rstate, state) { 1825 t.Fatalf("Restored state does not match:\n%+v\n\n%+v", rstate, state) 1826 } 1827 } 1828 1829 // Simple case first. 1830 snap := snapshot() 1831 verifySnapshot(snap) 1832 1833 // Remove first 100 messages. 1834 for i := 1; i <= 100; i++ { 1835 fs.RemoveMsg(uint64(i)) 1836 } 1837 1838 snap = snapshot() 1839 verifySnapshot(snap) 1840 1841 // Now sporadic messages inside the stream. 1842 total := int64(toSend - 100) 1843 // Delete 50 random messages. 1844 for i := 0; i < 50; i++ { 1845 seq := uint64(rand.Int63n(total) + 101) 1846 fs.RemoveMsg(seq) 1847 } 1848 1849 snap = snapshot() 1850 verifySnapshot(snap) 1851 1852 // Make sure compaction works with snapshots. 1853 fs.mu.RLock() 1854 for _, mb := range fs.blks { 1855 // Should not call compact on last msg block. 1856 if mb != fs.lmb { 1857 mb.mu.Lock() 1858 mb.compact() 1859 mb.mu.Unlock() 1860 } 1861 } 1862 fs.mu.RUnlock() 1863 1864 snap = snapshot() 1865 verifySnapshot(snap) 1866 1867 // Now check to make sure that we get the correct error when trying to delete or erase 1868 // a message when a snapshot is in progress and that closing the reader releases that condition. 1869 sr, err := fs.Snapshot(5*time.Second, false, true) 1870 if err != nil { 1871 t.Fatalf("Error creating snapshot") 1872 } 1873 if _, err := fs.RemoveMsg(122); err != ErrStoreSnapshotInProgress { 1874 t.Fatalf("Did not get the correct error on remove during snapshot: %v", err) 1875 } 1876 if _, err := fs.EraseMsg(122); err != ErrStoreSnapshotInProgress { 1877 t.Fatalf("Did not get the correct error on remove during snapshot: %v", err) 1878 } 1879 1880 // Now make sure we can do these when we close the reader and release the snapshot condition. 1881 sr.Reader.Close() 1882 checkFor(t, time.Second, 10*time.Millisecond, func() error { 1883 if _, err := fs.RemoveMsg(122); err != nil { 1884 return fmt.Errorf("Got an error on remove after snapshot: %v", err) 1885 } 1886 return nil 1887 }) 1888 1889 // Make sure if we do not read properly then it will close the writer and report an error. 1890 sr, err = fs.Snapshot(25*time.Millisecond, false, false) 1891 if err != nil { 1892 t.Fatalf("Error creating snapshot") 1893 } 1894 1895 // Cause snapshot to timeout. 1896 time.Sleep(50 * time.Millisecond) 1897 // Read should fail 1898 var buf [32]byte 1899 if _, err := sr.Reader.Read(buf[:]); err != io.EOF { 1900 t.Fatalf("Expected read to produce an error, got none") 1901 } 1902 }) 1903 } 1904 1905 func TestFileStoreConsumer(t *testing.T) { 1906 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 1907 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 1908 require_NoError(t, err) 1909 defer fs.Stop() 1910 1911 o, err := fs.ConsumerStore("obs22", &ConsumerConfig{}) 1912 if err != nil { 1913 t.Fatalf("Unexpected error: %v", err) 1914 } 1915 if state, err := o.State(); err != nil || state.Delivered.Consumer != 0 { 1916 t.Fatalf("Unexpected state or error: %v", err) 1917 } 1918 1919 state := &ConsumerState{} 1920 1921 updateAndCheck := func() { 1922 t.Helper() 1923 if err := o.Update(state); err != nil { 1924 t.Fatalf("Unexpected error updating state: %v", err) 1925 } 1926 s2, err := o.State() 1927 if err != nil { 1928 t.Fatalf("Unexpected error getting state: %v", err) 1929 } 1930 if !reflect.DeepEqual(state, s2) { 1931 t.Fatalf("State is not the same: wanted %+v got %+v", state, s2) 1932 } 1933 } 1934 1935 shouldFail := func() { 1936 t.Helper() 1937 if err := o.Update(state); err == nil { 1938 t.Fatalf("Expected an error and got none") 1939 } 1940 } 1941 1942 state.Delivered.Consumer = 1 1943 state.Delivered.Stream = 22 1944 updateAndCheck() 1945 1946 state.Delivered.Consumer = 100 1947 state.Delivered.Stream = 122 1948 state.AckFloor.Consumer = 50 1949 state.AckFloor.Stream = 123 1950 // This should fail, bad state. 1951 shouldFail() 1952 // So should this. 1953 state.AckFloor.Consumer = 200 1954 state.AckFloor.Stream = 100 1955 shouldFail() 1956 1957 // Should succeed 1958 state.AckFloor.Consumer = 50 1959 state.AckFloor.Stream = 72 1960 updateAndCheck() 1961 1962 tn := time.Now().UnixNano() 1963 1964 // We should sanity check pending here as well, so will check if a pending value is below 1965 // ack floor or above delivered. 1966 state.Pending = map[uint64]*Pending{70: {70, tn}} 1967 shouldFail() 1968 state.Pending = map[uint64]*Pending{140: {140, tn}} 1969 shouldFail() 1970 state.Pending = map[uint64]*Pending{72: {72, tn}} // exact on floor should fail 1971 shouldFail() 1972 1973 // Put timestamps a second apart. 1974 // We will downsample to second resolution to save space. So setup our times 1975 // to reflect that. 1976 ago := time.Now().Add(-30 * time.Second).Truncate(time.Second) 1977 nt := func() *Pending { 1978 ago = ago.Add(time.Second) 1979 return &Pending{0, ago.UnixNano()} 1980 } 1981 // Should succeed. 1982 state.Pending = map[uint64]*Pending{75: nt(), 80: nt(), 83: nt(), 90: nt(), 111: nt()} 1983 updateAndCheck() 1984 1985 // Now do redlivery, but first with no pending. 1986 state.Pending = nil 1987 state.Redelivered = map[uint64]uint64{22: 3, 44: 8} 1988 updateAndCheck() 1989 1990 // All together. 1991 state.Pending = map[uint64]*Pending{75: nt(), 80: nt(), 83: nt(), 90: nt(), 111: nt()} 1992 updateAndCheck() 1993 1994 // Large one 1995 state.Delivered.Consumer = 10000 1996 state.Delivered.Stream = 10000 1997 state.AckFloor.Consumer = 100 1998 state.AckFloor.Stream = 100 1999 // Generate 8k pending. 2000 state.Pending = make(map[uint64]*Pending) 2001 for len(state.Pending) < 8192 { 2002 seq := uint64(rand.Intn(9890) + 101) 2003 if _, ok := state.Pending[seq]; !ok { 2004 state.Pending[seq] = nt() 2005 } 2006 } 2007 updateAndCheck() 2008 2009 state.Pending = nil 2010 state.AckFloor.Consumer = 10000 2011 state.AckFloor.Stream = 10000 2012 updateAndCheck() 2013 }) 2014 } 2015 2016 func TestFileStoreConsumerEncodeDecodeRedelivered(t *testing.T) { 2017 state := &ConsumerState{} 2018 2019 state.Delivered.Consumer = 100 2020 state.Delivered.Stream = 100 2021 state.AckFloor.Consumer = 50 2022 state.AckFloor.Stream = 50 2023 2024 state.Redelivered = map[uint64]uint64{122: 3, 144: 8} 2025 buf := encodeConsumerState(state) 2026 2027 rstate, err := decodeConsumerState(buf) 2028 if err != nil { 2029 t.Fatalf("Unexpected error: %v", err) 2030 } 2031 if !reflect.DeepEqual(state, rstate) { 2032 t.Fatalf("States do not match: %+v vs %+v", state, rstate) 2033 } 2034 } 2035 2036 func TestFileStoreConsumerEncodeDecodePendingBelowStreamAckFloor(t *testing.T) { 2037 state := &ConsumerState{} 2038 2039 state.Delivered.Consumer = 1192 2040 state.Delivered.Stream = 10185 2041 state.AckFloor.Consumer = 1189 2042 state.AckFloor.Stream = 10815 2043 2044 now := time.Now().Round(time.Second).Add(-10 * time.Second).UnixNano() 2045 state.Pending = map[uint64]*Pending{ 2046 10782: {1190, now}, 2047 10810: {1191, now + int64(time.Second)}, 2048 10815: {1192, now + int64(2*time.Second)}, 2049 } 2050 buf := encodeConsumerState(state) 2051 2052 rstate, err := decodeConsumerState(buf) 2053 if err != nil { 2054 t.Fatalf("Unexpected error: %v", err) 2055 } 2056 if len(rstate.Pending) != 3 { 2057 t.Fatalf("Invalid pending: %v", rstate.Pending) 2058 } 2059 for k, v := range state.Pending { 2060 rv, ok := rstate.Pending[k] 2061 if !ok { 2062 t.Fatalf("Did not find sseq=%v", k) 2063 } 2064 if !reflect.DeepEqual(v, rv) { 2065 t.Fatalf("Pending for sseq=%v should be %+v, got %+v", k, v, rv) 2066 } 2067 } 2068 state.Pending, rstate.Pending = nil, nil 2069 if !reflect.DeepEqual(*state, *rstate) { 2070 t.Fatalf("States do not match: %+v vs %+v", state, rstate) 2071 } 2072 } 2073 2074 func TestFileStoreWriteFailures(t *testing.T) { 2075 // This test should be run inside an environment where this directory 2076 // has a limited size. 2077 // E.g. Docker 2078 // docker run -ti --tmpfs /jswf_test:rw,size=32k --rm -v ~/Development/go/src:/go/src -w /go/src/github.com/nats-io/nats-server/ golang:1.21 /bin/bash 2079 tdir := filepath.Join("/", "jswf_test") 2080 if stat, err := os.Stat(tdir); err != nil || !stat.IsDir() { 2081 t.SkipNow() 2082 } 2083 2084 storeDir := filepath.Join(tdir, JetStreamStoreDir) 2085 os.MkdirAll(storeDir, 0755) 2086 2087 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2088 fcfg.StoreDir = storeDir 2089 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 2090 created := time.Now() 2091 2092 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 2093 require_NoError(t, err) 2094 defer fs.Stop() 2095 2096 subj, msg := "foo", []byte("Hello Write Failures!") 2097 2098 var lseq uint64 2099 // msz about will be ~54 bytes, so if limit is 32k trying to send 1000 will fail at some point. 2100 for i := 1; i <= 1000; i++ { 2101 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 2102 lseq = uint64(i) 2103 break 2104 } 2105 } 2106 if lseq == 0 { 2107 t.Fatalf("Expected to get a failure but did not") 2108 } 2109 2110 state := fs.State() 2111 2112 if state.LastSeq != lseq-1 { 2113 t.Fatalf("Expected last seq to be %d, got %d\n", lseq-1, state.LastSeq) 2114 } 2115 if state.Msgs != lseq-1 { 2116 t.Fatalf("Expected total msgs to be %d, got %d\n", lseq-1, state.Msgs) 2117 } 2118 if _, err := fs.LoadMsg(lseq, nil); err == nil { 2119 t.Fatalf("Expected error loading seq that failed, got none") 2120 } 2121 // Loading should still work. 2122 if _, err := fs.LoadMsg(1, nil); err != nil { 2123 t.Fatalf("Unexpected error: %v", err) 2124 } 2125 2126 // Make sure we recover same state. 2127 fs.Stop() 2128 2129 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 2130 require_NoError(t, err) 2131 defer fs.Stop() 2132 2133 state2 := fs.State() 2134 2135 // Ignore lost state. 2136 state.Lost, state2.Lost = nil, nil 2137 if !reflect.DeepEqual(state2, state) { 2138 t.Fatalf("Expected recovered state to be the same\n%+v\nvs\n%+v\n", state2, state) 2139 } 2140 2141 // We should still fail here. 2142 for i := 1; i <= 100; i++ { 2143 _, _, err = fs.StoreMsg(subj, nil, msg) 2144 if err != nil { 2145 break 2146 } 2147 } 2148 require_Error(t, err) 2149 2150 lseq = fs.State().LastSeq + 1 2151 2152 // Purge should help. 2153 if _, err := fs.Purge(); err != nil { 2154 t.Fatalf("Unexpected error: %v", err) 2155 } 2156 // Wait for purge to complete its out of band processing. 2157 time.Sleep(50 * time.Millisecond) 2158 2159 // Check we will fail again in same spot. 2160 for i := 1; i <= 1000; i++ { 2161 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 2162 if i != int(lseq) { 2163 t.Fatalf("Expected to fail after purge about the same spot, wanted %d got %d", lseq, i) 2164 } 2165 break 2166 } 2167 } 2168 }) 2169 } 2170 2171 func TestFileStorePerf(t *testing.T) { 2172 // Comment out to run, holding place for now. 2173 t.SkipNow() 2174 2175 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2176 fcfg.AsyncFlush = true 2177 2178 subj, msg := "foo", make([]byte, 1024-33) 2179 for i := 0; i < len(msg); i++ { 2180 msg[i] = 'D' 2181 } 2182 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 2183 2184 // 5GB 2185 toStore := 5 * 1024 * 1024 * 1024 / storedMsgSize 2186 2187 fmt.Printf("storing %d msgs of %s each, totalling %s\n", 2188 toStore, 2189 friendlyBytes(int64(storedMsgSize)), 2190 friendlyBytes(int64(toStore*storedMsgSize)), 2191 ) 2192 2193 created := time.Now() 2194 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 2195 require_NoError(t, err) 2196 defer fs.Stop() 2197 2198 start := time.Now() 2199 for i := 0; i < int(toStore); i++ { 2200 fs.StoreMsg(subj, nil, msg) 2201 } 2202 fs.Stop() 2203 2204 tt := time.Since(start) 2205 fmt.Printf("time to store is %v\n", tt) 2206 fmt.Printf("%.0f msgs/sec\n", float64(toStore)/tt.Seconds()) 2207 fmt.Printf("%s per sec\n", friendlyBytes(int64(float64(toStore*storedMsgSize)/tt.Seconds()))) 2208 2209 fmt.Printf("Filesystem cache flush, paused 5 seconds.\n\n") 2210 time.Sleep(5 * time.Second) 2211 2212 fmt.Printf("Restoring..\n") 2213 start = time.Now() 2214 fcfg.AsyncFlush = false 2215 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 2216 require_NoError(t, err) 2217 defer fs.Stop() 2218 2219 fmt.Printf("time to restore is %v\n\n", time.Since(start)) 2220 2221 fmt.Printf("LOAD: reading %d msgs of %s each, totalling %s\n", 2222 toStore, 2223 friendlyBytes(int64(storedMsgSize)), 2224 friendlyBytes(int64(toStore*storedMsgSize)), 2225 ) 2226 2227 var smv StoreMsg 2228 start = time.Now() 2229 for i := uint64(1); i <= toStore; i++ { 2230 if _, err := fs.LoadMsg(i, &smv); err != nil { 2231 t.Fatalf("Error loading %d: %v", i, err) 2232 } 2233 } 2234 2235 tt = time.Since(start) 2236 fmt.Printf("time to read all back messages is %v\n", tt) 2237 fmt.Printf("%.0f msgs/sec\n", float64(toStore)/tt.Seconds()) 2238 fmt.Printf("%s per sec\n", friendlyBytes(int64(float64(toStore*storedMsgSize)/tt.Seconds()))) 2239 2240 // Do again to test skip for hash.. 2241 fmt.Printf("\nSKIP CHECKSUM: reading %d msgs of %s each, totalling %s\n", 2242 toStore, 2243 friendlyBytes(int64(storedMsgSize)), 2244 friendlyBytes(int64(toStore*storedMsgSize)), 2245 ) 2246 2247 start = time.Now() 2248 for i := uint64(1); i <= toStore; i++ { 2249 if _, err := fs.LoadMsg(i, &smv); err != nil { 2250 t.Fatalf("Error loading %d: %v", i, err) 2251 } 2252 } 2253 2254 tt = time.Since(start) 2255 fmt.Printf("time to read all back messages is %v\n", tt) 2256 fmt.Printf("%.0f msgs/sec\n", float64(toStore)/tt.Seconds()) 2257 fmt.Printf("%s per sec\n", friendlyBytes(int64(float64(toStore*storedMsgSize)/tt.Seconds()))) 2258 2259 fs.Stop() 2260 2261 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 2262 require_NoError(t, err) 2263 defer fs.Stop() 2264 2265 fmt.Printf("\nremoving [in order] %d msgs of %s each, totalling %s\n", 2266 toStore, 2267 friendlyBytes(int64(storedMsgSize)), 2268 friendlyBytes(int64(toStore*storedMsgSize)), 2269 ) 2270 2271 start = time.Now() 2272 // For reverse order. 2273 //for i := toStore; i > 0; i-- { 2274 for i := uint64(1); i <= toStore; i++ { 2275 fs.RemoveMsg(i) 2276 } 2277 fs.Stop() 2278 2279 tt = time.Since(start) 2280 fmt.Printf("time to remove all messages is %v\n", tt) 2281 fmt.Printf("%.0f msgs/sec\n", float64(toStore)/tt.Seconds()) 2282 fmt.Printf("%s per sec\n", friendlyBytes(int64(float64(toStore*storedMsgSize)/tt.Seconds()))) 2283 2284 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 2285 require_NoError(t, err) 2286 defer fs.Stop() 2287 2288 state := fs.State() 2289 if state.Msgs != 0 { 2290 t.Fatalf("Expected no msgs, got %d", state.Msgs) 2291 } 2292 if state.Bytes != 0 { 2293 t.Fatalf("Expected no bytes, got %d", state.Bytes) 2294 } 2295 }) 2296 } 2297 2298 func TestFileStoreReadBackMsgPerf(t *testing.T) { 2299 // Comment out to run, holding place for now. 2300 t.SkipNow() 2301 2302 subj := "foo" 2303 msg := []byte("ABCDEFGH") // Smaller shows problems more. 2304 2305 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 2306 2307 // Make sure we store 2 blocks. 2308 toStore := defaultLargeBlockSize * 2 / storedMsgSize 2309 2310 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2311 fmt.Printf("storing %d msgs of %s each, totalling %s\n", 2312 toStore, 2313 friendlyBytes(int64(storedMsgSize)), 2314 friendlyBytes(int64(toStore*storedMsgSize)), 2315 ) 2316 2317 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2318 require_NoError(t, err) 2319 defer fs.Stop() 2320 2321 start := time.Now() 2322 for i := 0; i < int(toStore); i++ { 2323 fs.StoreMsg(subj, nil, msg) 2324 } 2325 2326 tt := time.Since(start) 2327 fmt.Printf("time to store is %v\n", tt) 2328 fmt.Printf("%.0f msgs/sec\n", float64(toStore)/tt.Seconds()) 2329 fmt.Printf("%s per sec\n", friendlyBytes(int64(float64(toStore*storedMsgSize)/tt.Seconds()))) 2330 2331 // We should not have cached here with no reads. 2332 // Pick something towards end of the block. 2333 index := defaultLargeBlockSize/storedMsgSize - 22 2334 start = time.Now() 2335 fs.LoadMsg(index, nil) 2336 fmt.Printf("Time to load first msg [%d] = %v\n", index, time.Since(start)) 2337 2338 start = time.Now() 2339 fs.LoadMsg(index+2, nil) 2340 fmt.Printf("Time to load second msg [%d] = %v\n", index+2, time.Since(start)) 2341 }) 2342 } 2343 2344 // This test is testing an upper level stream with a message or byte limit. 2345 // Even though this is 1, any limit would trigger same behavior once the limit was reached 2346 // and we were adding and removing. 2347 func TestFileStoreStoreLimitRemovePerf(t *testing.T) { 2348 // Comment out to run, holding place for now. 2349 t.SkipNow() 2350 2351 subj, msg := "foo", make([]byte, 1024-33) 2352 for i := 0; i < len(msg); i++ { 2353 msg[i] = 'D' 2354 } 2355 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 2356 2357 // 1GB 2358 toStore := 1 * 1024 * 1024 * 1024 / storedMsgSize 2359 2360 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2361 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2362 require_NoError(t, err) 2363 defer fs.Stop() 2364 2365 fs.RegisterStorageUpdates(func(md, bd int64, seq uint64, subj string) {}) 2366 2367 fmt.Printf("storing and removing (limit 1) %d msgs of %s each, totalling %s\n", 2368 toStore, 2369 friendlyBytes(int64(storedMsgSize)), 2370 friendlyBytes(int64(toStore*storedMsgSize)), 2371 ) 2372 2373 start := time.Now() 2374 for i := 0; i < int(toStore); i++ { 2375 seq, _, err := fs.StoreMsg(subj, nil, msg) 2376 if err != nil { 2377 t.Fatalf("Unexpected error storing message: %v", err) 2378 } 2379 if i > 0 { 2380 fs.RemoveMsg(seq - 1) 2381 } 2382 } 2383 fs.Stop() 2384 2385 tt := time.Since(start) 2386 fmt.Printf("time to store and remove all messages is %v\n", tt) 2387 fmt.Printf("%.0f msgs/sec\n", float64(toStore)/tt.Seconds()) 2388 fmt.Printf("%s per sec\n", friendlyBytes(int64(float64(toStore*storedMsgSize)/tt.Seconds()))) 2389 }) 2390 } 2391 2392 func TestFileStorePubPerfWithSmallBlkSize(t *testing.T) { 2393 // Comment out to run, holding place for now. 2394 t.SkipNow() 2395 2396 subj, msg := "foo", make([]byte, 1024-33) 2397 for i := 0; i < len(msg); i++ { 2398 msg[i] = 'D' 2399 } 2400 storedMsgSize := fileStoreMsgSize(subj, nil, msg) 2401 2402 // 1GB 2403 toStore := 1 * 1024 * 1024 * 1024 / storedMsgSize 2404 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2405 fmt.Printf("storing %d msgs of %s each, totalling %s\n", 2406 toStore, 2407 friendlyBytes(int64(storedMsgSize)), 2408 friendlyBytes(int64(toStore*storedMsgSize)), 2409 ) 2410 2411 fcfg.BlockSize = FileStoreMinBlkSize 2412 2413 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2414 require_NoError(t, err) 2415 defer fs.Stop() 2416 2417 start := time.Now() 2418 for i := 0; i < int(toStore); i++ { 2419 fs.StoreMsg(subj, nil, msg) 2420 } 2421 fs.Stop() 2422 2423 tt := time.Since(start) 2424 fmt.Printf("time to store is %v\n", tt) 2425 fmt.Printf("%.0f msgs/sec\n", float64(toStore)/tt.Seconds()) 2426 fmt.Printf("%s per sec\n", friendlyBytes(int64(float64(toStore*storedMsgSize)/tt.Seconds()))) 2427 }) 2428 } 2429 2430 // Saw this manifest from a restart test with max delivered set for JetStream. 2431 func TestFileStoreConsumerRedeliveredLost(t *testing.T) { 2432 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2433 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2434 require_NoError(t, err) 2435 defer fs.Stop() 2436 2437 cfg := &ConsumerConfig{AckPolicy: AckExplicit} 2438 o, err := fs.ConsumerStore("o22", cfg) 2439 if err != nil { 2440 t.Fatalf("Unexpected error: %v", err) 2441 } 2442 2443 restartConsumer := func() { 2444 t.Helper() 2445 o.Stop() 2446 time.Sleep(20 * time.Millisecond) // Wait for all things to settle. 2447 o, err = fs.ConsumerStore("o22", cfg) 2448 if err != nil { 2449 t.Fatalf("Unexpected error: %v", err) 2450 } 2451 // Make sure we recovered Redelivered. 2452 state, err := o.State() 2453 if err != nil { 2454 t.Fatalf("Unexpected error: %v", err) 2455 } 2456 if state == nil { 2457 t.Fatalf("Did not recover state") 2458 } 2459 if len(state.Redelivered) == 0 { 2460 t.Fatalf("Did not recover redelivered") 2461 } 2462 } 2463 2464 ts := time.Now().UnixNano() 2465 o.UpdateDelivered(1, 1, 1, ts) 2466 o.UpdateDelivered(2, 1, 2, ts) 2467 o.UpdateDelivered(3, 1, 3, ts) 2468 o.UpdateDelivered(4, 1, 4, ts) 2469 o.UpdateDelivered(5, 2, 1, ts) 2470 2471 restartConsumer() 2472 2473 o.UpdateDelivered(6, 2, 2, ts) 2474 o.UpdateDelivered(7, 3, 1, ts) 2475 2476 restartConsumer() 2477 if state, _ := o.State(); len(state.Pending) != 3 { 2478 t.Fatalf("Did not recover pending correctly") 2479 } 2480 2481 o.UpdateAcks(7, 3) 2482 o.UpdateAcks(6, 2) 2483 2484 restartConsumer() 2485 o.UpdateAcks(4, 1) 2486 2487 state, _ := o.State() 2488 if len(state.Pending) != 0 { 2489 t.Fatalf("Did not clear pending correctly") 2490 } 2491 if len(state.Redelivered) != 0 { 2492 t.Fatalf("Did not clear redelivered correctly") 2493 } 2494 }) 2495 } 2496 2497 func TestFileStoreConsumerFlusher(t *testing.T) { 2498 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2499 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2500 require_NoError(t, err) 2501 defer fs.Stop() 2502 2503 o, err := fs.ConsumerStore("o22", &ConsumerConfig{}) 2504 if err != nil { 2505 t.Fatalf("Unexpected error: %v", err) 2506 } 2507 // Get the underlying impl. 2508 oc := o.(*consumerFileStore) 2509 // Wait for flusher to be running. 2510 checkFor(t, time.Second, 20*time.Millisecond, func() error { 2511 if !oc.inFlusher() { 2512 return fmt.Errorf("Flusher not running") 2513 } 2514 return nil 2515 }) 2516 // Stop and make sure the flusher goes away 2517 o.Stop() 2518 // Wait for flusher to stop. 2519 checkFor(t, time.Second, 20*time.Millisecond, func() error { 2520 if oc.inFlusher() { 2521 return fmt.Errorf("Flusher still running") 2522 } 2523 return nil 2524 }) 2525 }) 2526 } 2527 2528 func TestFileStoreConsumerDeliveredUpdates(t *testing.T) { 2529 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2530 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2531 require_NoError(t, err) 2532 defer fs.Stop() 2533 2534 // Simple consumer, no ack policy configured. 2535 o, err := fs.ConsumerStore("o22", &ConsumerConfig{}) 2536 if err != nil { 2537 t.Fatalf("Unexpected error: %v", err) 2538 } 2539 defer o.Stop() 2540 2541 testDelivered := func(dseq, sseq uint64) { 2542 t.Helper() 2543 ts := time.Now().UnixNano() 2544 if err := o.UpdateDelivered(dseq, sseq, 1, ts); err != nil { 2545 t.Fatalf("Unexpected error: %v", err) 2546 } 2547 state, err := o.State() 2548 if err != nil { 2549 t.Fatalf("Error getting state: %v", err) 2550 } 2551 if state == nil { 2552 t.Fatalf("No state available") 2553 } 2554 expected := SequencePair{dseq, sseq} 2555 if state.Delivered != expected { 2556 t.Fatalf("Unexpected state, wanted %+v, got %+v", expected, state.Delivered) 2557 } 2558 if state.AckFloor != expected { 2559 t.Fatalf("Unexpected ack floor state, wanted %+v, got %+v", expected, state.AckFloor) 2560 } 2561 if len(state.Pending) != 0 { 2562 t.Fatalf("Did not expect any pending, got %d pending", len(state.Pending)) 2563 } 2564 } 2565 2566 testDelivered(1, 100) 2567 testDelivered(2, 110) 2568 testDelivered(5, 130) 2569 2570 // If we try to do an ack this should err since we are not configured with ack policy. 2571 if err := o.UpdateAcks(1, 100); err != ErrNoAckPolicy { 2572 t.Fatalf("Expected a no ack policy error on update acks, got %v", err) 2573 } 2574 // Also if we do an update with a delivery count of anything but 1 here should also give same error. 2575 ts := time.Now().UnixNano() 2576 if err := o.UpdateDelivered(5, 130, 2, ts); err != ErrNoAckPolicy { 2577 t.Fatalf("Expected a no ack policy error on update delivered with dc > 1, got %v", err) 2578 } 2579 }) 2580 } 2581 2582 func TestFileStoreConsumerDeliveredAndAckUpdates(t *testing.T) { 2583 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2584 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2585 require_NoError(t, err) 2586 defer fs.Stop() 2587 2588 // Simple consumer, no ack policy configured. 2589 o, err := fs.ConsumerStore("o22", &ConsumerConfig{AckPolicy: AckExplicit}) 2590 if err != nil { 2591 t.Fatalf("Unexpected error: %v", err) 2592 } 2593 defer o.Stop() 2594 2595 // Track pending. 2596 var pending int 2597 2598 testDelivered := func(dseq, sseq uint64) { 2599 t.Helper() 2600 ts := time.Now().Round(time.Second).UnixNano() 2601 if err := o.UpdateDelivered(dseq, sseq, 1, ts); err != nil { 2602 t.Fatalf("Unexpected error: %v", err) 2603 } 2604 pending++ 2605 state, err := o.State() 2606 if err != nil { 2607 t.Fatalf("Error getting state: %v", err) 2608 } 2609 if state == nil { 2610 t.Fatalf("No state available") 2611 } 2612 expected := SequencePair{dseq, sseq} 2613 if state.Delivered != expected { 2614 t.Fatalf("Unexpected delivered state, wanted %+v, got %+v", expected, state.Delivered) 2615 } 2616 if len(state.Pending) != pending { 2617 t.Fatalf("Expected %d pending, got %d pending", pending, len(state.Pending)) 2618 } 2619 } 2620 2621 testDelivered(1, 100) 2622 testDelivered(2, 110) 2623 testDelivered(3, 130) 2624 testDelivered(4, 150) 2625 testDelivered(5, 165) 2626 2627 testBadAck := func(dseq, sseq uint64) { 2628 t.Helper() 2629 if err := o.UpdateAcks(dseq, sseq); err == nil { 2630 t.Fatalf("Expected error but got none") 2631 } 2632 } 2633 testBadAck(3, 101) 2634 testBadAck(1, 1) 2635 2636 testAck := func(dseq, sseq, dflr, sflr uint64) { 2637 t.Helper() 2638 if err := o.UpdateAcks(dseq, sseq); err != nil { 2639 t.Fatalf("Unexpected error: %v", err) 2640 } 2641 pending-- 2642 state, err := o.State() 2643 if err != nil { 2644 t.Fatalf("Error getting state: %v", err) 2645 } 2646 if state == nil { 2647 t.Fatalf("No state available") 2648 } 2649 if len(state.Pending) != pending { 2650 t.Fatalf("Expected %d pending, got %d pending", pending, len(state.Pending)) 2651 } 2652 eflr := SequencePair{dflr, sflr} 2653 if state.AckFloor != eflr { 2654 t.Fatalf("Unexpected ack floor state, wanted %+v, got %+v", eflr, state.AckFloor) 2655 } 2656 } 2657 2658 testAck(1, 100, 1, 109) 2659 testAck(3, 130, 1, 109) 2660 testAck(2, 110, 3, 149) // We do not track explicit state on previous stream floors, so we take last known -1 2661 testAck(5, 165, 3, 149) 2662 testAck(4, 150, 5, 165) 2663 2664 testDelivered(6, 170) 2665 testDelivered(7, 171) 2666 testDelivered(8, 172) 2667 testDelivered(9, 173) 2668 testDelivered(10, 200) 2669 2670 testAck(7, 171, 5, 165) 2671 testAck(8, 172, 5, 165) 2672 2673 state, err := o.State() 2674 if err != nil { 2675 t.Fatalf("Unexpected error getting state: %v", err) 2676 } 2677 o.Stop() 2678 2679 o, err = fs.ConsumerStore("o22", &ConsumerConfig{AckPolicy: AckExplicit}) 2680 if err != nil { 2681 t.Fatalf("Unexpected error: %v", err) 2682 } 2683 defer o.Stop() 2684 2685 nstate, err := o.State() 2686 if err != nil { 2687 t.Fatalf("Unexpected error getting state: %v", err) 2688 } 2689 if !reflect.DeepEqual(nstate, state) { 2690 t.Fatalf("States don't match! NEW %+v OLD %+v", nstate, state) 2691 } 2692 }) 2693 } 2694 2695 func TestFileStoreStreamStateDeleted(t *testing.T) { 2696 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2697 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2698 require_NoError(t, err) 2699 defer fs.Stop() 2700 2701 subj, toStore := "foo", uint64(10) 2702 for i := uint64(1); i <= toStore; i++ { 2703 msg := []byte(fmt.Sprintf("[%08d] Hello World!", i)) 2704 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 2705 t.Fatalf("Error storing msg: %v", err) 2706 } 2707 } 2708 state := fs.State() 2709 if len(state.Deleted) != 0 { 2710 t.Fatalf("Expected deleted to be empty") 2711 } 2712 // Now remove some interior messages. 2713 var expected []uint64 2714 for seq := uint64(2); seq < toStore; seq += 2 { 2715 fs.RemoveMsg(seq) 2716 expected = append(expected, seq) 2717 } 2718 state = fs.State() 2719 if !reflect.DeepEqual(state.Deleted, expected) { 2720 t.Fatalf("Expected deleted to be %+v, got %+v\n", expected, state.Deleted) 2721 } 2722 // Now fill the gap by deleting 1 and 3 2723 fs.RemoveMsg(1) 2724 fs.RemoveMsg(3) 2725 expected = expected[2:] 2726 state = fs.State() 2727 if !reflect.DeepEqual(state.Deleted, expected) { 2728 t.Fatalf("Expected deleted to be %+v, got %+v\n", expected, state.Deleted) 2729 } 2730 if state.FirstSeq != 5 { 2731 t.Fatalf("Expected first seq to be 5, got %d", state.FirstSeq) 2732 } 2733 fs.Purge() 2734 if state = fs.State(); len(state.Deleted) != 0 { 2735 t.Fatalf("Expected no deleted after purge, got %+v\n", state.Deleted) 2736 } 2737 }) 2738 } 2739 2740 // We have reports that sometimes under load a stream could complain about a storage directory 2741 // not being empty. 2742 func TestFileStoreStreamDeleteDirNotEmpty(t *testing.T) { 2743 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2744 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2745 require_NoError(t, err) 2746 defer fs.Stop() 2747 2748 subj, toStore := "foo", uint64(10) 2749 for i := uint64(1); i <= toStore; i++ { 2750 msg := []byte(fmt.Sprintf("[%08d] Hello World!", i)) 2751 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 2752 t.Fatalf("Error storing msg: %v", err) 2753 } 2754 } 2755 2756 ready := make(chan bool) 2757 go func() { 2758 g := filepath.Join(fcfg.StoreDir, "g") 2759 ready <- true 2760 for i := 0; i < 100; i++ { 2761 os.WriteFile(g, []byte("OK"), defaultFilePerms) 2762 } 2763 }() 2764 2765 <-ready 2766 if err := fs.Delete(); err != nil { 2767 t.Fatalf("Delete returned an error: %v", err) 2768 } 2769 }) 2770 } 2771 2772 func TestFileStoreConsumerPerf(t *testing.T) { 2773 // Comment out to run, holding place for now. 2774 t.SkipNow() 2775 2776 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2777 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2778 require_NoError(t, err) 2779 defer fs.Stop() 2780 2781 o, err := fs.ConsumerStore("o22", &ConsumerConfig{AckPolicy: AckExplicit}) 2782 if err != nil { 2783 t.Fatalf("Unexpected error: %v", err) 2784 } 2785 // Get the underlying impl. 2786 oc := o.(*consumerFileStore) 2787 // Wait for flusher to br running 2788 checkFor(t, time.Second, 20*time.Millisecond, func() error { 2789 if !oc.inFlusher() { 2790 return fmt.Errorf("not in flusher") 2791 } 2792 return nil 2793 }) 2794 2795 // Stop flusher for this benchmark since we will invoke directly. 2796 oc.mu.Lock() 2797 qch := oc.qch 2798 oc.qch = nil 2799 oc.mu.Unlock() 2800 close(qch) 2801 2802 checkFor(t, time.Second, 20*time.Millisecond, func() error { 2803 if oc.inFlusher() { 2804 return fmt.Errorf("still in flusher") 2805 } 2806 return nil 2807 }) 2808 2809 toStore := uint64(1_000_000) 2810 2811 start := time.Now() 2812 2813 ts := start.UnixNano() 2814 2815 for i := uint64(1); i <= toStore; i++ { 2816 if err := o.UpdateDelivered(i, i, 1, ts); err != nil { 2817 t.Fatalf("Unexpected error: %v", err) 2818 } 2819 } 2820 tt := time.Since(start) 2821 fmt.Printf("time to update %d is %v\n", toStore, tt) 2822 fmt.Printf("%.0f updates/sec\n", float64(toStore)/tt.Seconds()) 2823 2824 start = time.Now() 2825 oc.mu.Lock() 2826 buf, err := oc.encodeState() 2827 oc.mu.Unlock() 2828 if err != nil { 2829 t.Fatalf("Error encoding state: %v", err) 2830 } 2831 fmt.Printf("time to encode %d bytes is %v\n", len(buf), time.Since(start)) 2832 start = time.Now() 2833 oc.writeState(buf) 2834 fmt.Printf("time to write is %v\n", time.Since(start)) 2835 }) 2836 } 2837 2838 // Reported by Ivan. 2839 func TestFileStoreStreamDeleteCacheBug(t *testing.T) { 2840 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2841 fcfg.CacheExpire = 50 * time.Millisecond 2842 2843 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 2844 require_NoError(t, err) 2845 defer fs.Stop() 2846 2847 subj, msg := "foo", []byte("Hello World") 2848 2849 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 2850 t.Fatalf("Unexpected error: %v", err) 2851 } 2852 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 2853 t.Fatalf("Unexpected error: %v", err) 2854 } 2855 if _, err := fs.EraseMsg(1); err != nil { 2856 t.Fatalf("Got an error on remove of %d: %v", 1, err) 2857 } 2858 time.Sleep(100 * time.Millisecond) 2859 if _, err := fs.LoadMsg(2, nil); err != nil { 2860 t.Fatalf("Unexpected error looking up msg: %v", err) 2861 } 2862 }) 2863 } 2864 2865 // rip 2866 func TestFileStoreStreamFailToRollBug(t *testing.T) { 2867 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2868 fcfg.BlockSize = 512 2869 2870 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage, MaxBytes: 300}, time.Now(), prf(&fcfg), nil) 2871 require_NoError(t, err) 2872 defer fs.Stop() 2873 2874 // Make sure we properly roll underlying blocks. 2875 n, msg := 200, bytes.Repeat([]byte("ABC"), 33) // ~100bytes 2876 for i := 0; i < n; i++ { 2877 if _, _, err := fs.StoreMsg("zzz", nil, msg); err != nil { 2878 t.Fatalf("Unexpected error: %v", err) 2879 } 2880 } 2881 2882 // Grab some info for introspection. 2883 fs.mu.RLock() 2884 numBlks := len(fs.blks) 2885 var index uint32 2886 var blkSize int64 2887 if numBlks > 0 { 2888 mb := fs.blks[0] 2889 mb.mu.RLock() 2890 index = mb.index 2891 if fi, _ := os.Stat(mb.mfn); fi != nil { 2892 blkSize = fi.Size() 2893 } 2894 mb.mu.RUnlock() 2895 } 2896 fs.mu.RUnlock() 2897 2898 if numBlks != 1 { 2899 t.Fatalf("Expected only one block, got %d", numBlks) 2900 } 2901 if index < 60 { 2902 t.Fatalf("Expected a block index > 60, got %d", index) 2903 } 2904 if blkSize > 512 { 2905 t.Fatalf("Expected block to be <= 512, got %d", blkSize) 2906 } 2907 }) 2908 } 2909 2910 // We had a case where a consumer state had a redelivered record that had seq of 0. 2911 // This was causing the server to panic. 2912 func TestFileStoreBadConsumerState(t *testing.T) { 2913 bs := []byte("\x16\x02\x01\x01\x03\x02\x01\x98\xf4\x8a\x8a\f\x01\x03\x86\xfa\n\x01\x00\x01") 2914 if cs, err := decodeConsumerState(bs); err != nil || cs == nil { 2915 t.Fatalf("Expected to not throw error, got %v and %+v", err, cs) 2916 } 2917 } 2918 2919 func TestFileStoreExpireMsgsOnStart(t *testing.T) { 2920 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 2921 fcfg.BlockSize = 8 * 1024 2922 ttl := 250 * time.Millisecond 2923 cfg := StreamConfig{Name: "ORDERS", Subjects: []string{"orders.*"}, Storage: FileStorage, MaxAge: ttl} 2924 var fs *fileStore 2925 2926 startFS := func() *fileStore { 2927 t.Helper() 2928 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 2929 require_NoError(t, err) 2930 return fs 2931 } 2932 2933 newFS := func() *fileStore { 2934 t.Helper() 2935 if fs != nil { 2936 fs.Stop() 2937 fs = nil 2938 } 2939 removeDir(t, fcfg.StoreDir) 2940 return startFS() 2941 } 2942 2943 restartFS := func(delay time.Duration) *fileStore { 2944 if fs != nil { 2945 fs.Stop() 2946 fs = nil 2947 time.Sleep(delay) 2948 } 2949 fs = startFS() 2950 return fs 2951 } 2952 2953 fs = newFS() 2954 defer fs.Stop() 2955 2956 msg := bytes.Repeat([]byte("ABC"), 33) // ~100bytes 2957 loadMsgs := func(n int) { 2958 t.Helper() 2959 for i := 1; i <= n; i++ { 2960 if _, _, err := fs.StoreMsg(fmt.Sprintf("orders.%d", i%10), nil, msg); err != nil { 2961 t.Fatalf("Unexpected error: %v", err) 2962 } 2963 } 2964 } 2965 2966 checkState := func(msgs, first, last uint64) { 2967 t.Helper() 2968 if fs == nil { 2969 t.Fatalf("No fs") 2970 return 2971 } 2972 state := fs.State() 2973 if state.Msgs != msgs { 2974 t.Fatalf("Expected %d msgs, got %d", msgs, state.Msgs) 2975 } 2976 if state.FirstSeq != first { 2977 t.Fatalf("Expected %d as first, got %d", first, state.FirstSeq) 2978 } 2979 if state.LastSeq != last { 2980 t.Fatalf("Expected %d as last, got %d", last, state.LastSeq) 2981 } 2982 } 2983 2984 checkNumBlks := func(expected int) { 2985 t.Helper() 2986 fs.mu.RLock() 2987 n := len(fs.blks) 2988 fs.mu.RUnlock() 2989 if n != expected { 2990 t.Fatalf("Expected %d msg blks, got %d", expected, n) 2991 } 2992 } 2993 2994 // Check the filtered subject state and make sure that is tracked properly. 2995 checkFiltered := func(subject string, ss SimpleState) { 2996 t.Helper() 2997 fss := fs.FilteredState(1, subject) 2998 if fss != ss { 2999 t.Fatalf("Expected FilteredState of %+v, got %+v", ss, fss) 3000 } 3001 } 3002 3003 // Make sure state on disk matches (e.g. writeIndexInfo properly called) 3004 checkBlkState := func(index int) { 3005 t.Helper() 3006 fs.mu.RLock() 3007 if index >= len(fs.blks) { 3008 t.Fatalf("Out of range, wanted %d but only %d blks", index, len(fs.blks)) 3009 } 3010 fs.mu.RUnlock() 3011 } 3012 3013 lastSeqForBlk := func(index int) uint64 { 3014 t.Helper() 3015 fs.mu.RLock() 3016 defer fs.mu.RUnlock() 3017 if len(fs.blks) == 0 { 3018 t.Fatalf("No blocks?") 3019 } 3020 mb := fs.blks[0] 3021 mb.mu.RLock() 3022 defer mb.mu.RUnlock() 3023 return mb.last.seq 3024 } 3025 3026 // Actual testing here. 3027 3028 loadMsgs(500) 3029 restartFS(ttl + 100*time.Millisecond) 3030 checkState(0, 501, 500) 3031 // We actually hold onto the last one now to remember our starting sequence. 3032 checkNumBlks(1) 3033 3034 // Now check partial expires and the fss tracking state. 3035 // Small numbers is to keep them in one block. 3036 fs = newFS() 3037 loadMsgs(10) 3038 time.Sleep(100 * time.Millisecond) 3039 loadMsgs(10) 3040 checkFiltered("orders.*", SimpleState{Msgs: 20, First: 1, Last: 20}) 3041 3042 restartFS(ttl - 100*time.Millisecond + 25*time.Millisecond) // Just want half 3043 checkState(10, 11, 20) 3044 checkNumBlks(1) 3045 checkFiltered("orders.*", SimpleState{Msgs: 10, First: 11, Last: 20}) 3046 checkFiltered("orders.5", SimpleState{Msgs: 1, First: 15, Last: 15}) 3047 checkBlkState(0) 3048 3049 fs = newFS() 3050 loadMsgs(5) 3051 time.Sleep(100 * time.Millisecond) 3052 loadMsgs(15) 3053 restartFS(ttl - 100*time.Millisecond + 25*time.Millisecond) // Just want half 3054 checkState(15, 6, 20) 3055 checkFiltered("orders.*", SimpleState{Msgs: 15, First: 6, Last: 20}) 3056 checkFiltered("orders.5", SimpleState{Msgs: 2, First: 10, Last: 20}) 3057 3058 // Now we want to test that if the end of a msg block is all deletes msgs that we do the right thing. 3059 fs = newFS() 3060 loadMsgs(150) 3061 time.Sleep(100 * time.Millisecond) 3062 loadMsgs(100) 3063 3064 checkNumBlks(5) 3065 3066 // Now delete 10 messages from the end of the first block which we will expire on restart. 3067 // We will expire up to seq 100, so delete 91-100. 3068 lseq := lastSeqForBlk(0) 3069 for seq := lseq; seq > lseq-10; seq-- { 3070 removed, err := fs.RemoveMsg(seq) 3071 if err != nil || !removed { 3072 t.Fatalf("Error removing message: %v", err) 3073 } 3074 } 3075 restartFS(ttl - 100*time.Millisecond + 25*time.Millisecond) // Just want half 3076 checkState(100, 151, 250) 3077 checkNumBlks(3) // We should only have 3 blks left. 3078 checkBlkState(0) 3079 3080 // Now make sure that we properly clean up any internal dmap entries (sparse) when expiring. 3081 fs = newFS() 3082 loadMsgs(10) 3083 // Remove some in sparse fashion, adding to dmap. 3084 fs.RemoveMsg(2) 3085 fs.RemoveMsg(4) 3086 fs.RemoveMsg(6) 3087 time.Sleep(100 * time.Millisecond) 3088 loadMsgs(10) 3089 restartFS(ttl - 100*time.Millisecond + 25*time.Millisecond) // Just want half 3090 checkState(10, 11, 20) 3091 checkNumBlks(1) 3092 checkBlkState(0) 3093 3094 // Make sure expiring a block with tail deleted messages removes the message block etc. 3095 fs = newFS() 3096 loadMsgs(7) 3097 time.Sleep(100 * time.Millisecond) 3098 loadMsgs(3) 3099 fs.RemoveMsg(8) 3100 fs.RemoveMsg(9) 3101 fs.RemoveMsg(10) 3102 restartFS(ttl - 100*time.Millisecond + 25*time.Millisecond) 3103 checkState(0, 11, 10) 3104 3105 fs.Stop() 3106 // Not for start per se but since we have all the test tooling here check that Compact() does right thing as well. 3107 fs = newFS() 3108 defer fs.Stop() 3109 loadMsgs(100) 3110 checkFiltered("orders.*", SimpleState{Msgs: 100, First: 1, Last: 100}) 3111 checkFiltered("orders.5", SimpleState{Msgs: 10, First: 5, Last: 95}) 3112 // Check that Compact keeps fss updated, does dmap etc. 3113 fs.Compact(51) 3114 checkFiltered("orders.*", SimpleState{Msgs: 50, First: 51, Last: 100}) 3115 checkFiltered("orders.5", SimpleState{Msgs: 5, First: 55, Last: 95}) 3116 checkBlkState(0) 3117 }) 3118 } 3119 3120 func TestFileStoreSparseCompaction(t *testing.T) { 3121 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3122 fcfg.BlockSize = 1024 * 1024 3123 cfg := StreamConfig{Name: "KV", Subjects: []string{"kv.>"}, Storage: FileStorage} 3124 3125 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3126 require_NoError(t, err) 3127 defer fs.Stop() 3128 3129 msg := bytes.Repeat([]byte("ABC"), 33) // ~100bytes 3130 loadMsgs := func(n int) { 3131 t.Helper() 3132 for i := 1; i <= n; i++ { 3133 if _, _, err := fs.StoreMsg(fmt.Sprintf("kv.%d", i%10), nil, msg); err != nil { 3134 t.Fatalf("Unexpected error: %v", err) 3135 } 3136 } 3137 } 3138 3139 checkState := func(msgs, first, last uint64) { 3140 t.Helper() 3141 if fs == nil { 3142 t.Fatalf("No fs") 3143 return 3144 } 3145 state := fs.State() 3146 if state.Msgs != msgs { 3147 t.Fatalf("Expected %d msgs, got %d", msgs, state.Msgs) 3148 } 3149 if state.FirstSeq != first { 3150 t.Fatalf("Expected %d as first, got %d", first, state.FirstSeq) 3151 } 3152 if state.LastSeq != last { 3153 t.Fatalf("Expected %d as last, got %d", last, state.LastSeq) 3154 } 3155 } 3156 3157 deleteMsgs := func(seqs ...uint64) { 3158 t.Helper() 3159 for _, seq := range seqs { 3160 removed, err := fs.RemoveMsg(seq) 3161 if err != nil || !removed { 3162 t.Fatalf("Got an error on remove of %d: %v", seq, err) 3163 } 3164 } 3165 } 3166 3167 eraseMsgs := func(seqs ...uint64) { 3168 t.Helper() 3169 for _, seq := range seqs { 3170 removed, err := fs.EraseMsg(seq) 3171 if err != nil || !removed { 3172 t.Fatalf("Got an error on erase of %d: %v", seq, err) 3173 } 3174 } 3175 } 3176 3177 compact := func() { 3178 t.Helper() 3179 var ssb, ssa StreamState 3180 fs.FastState(&ssb) 3181 tb, ub, _ := fs.Utilization() 3182 3183 fs.mu.RLock() 3184 if len(fs.blks) == 0 { 3185 t.Fatalf("No blocks?") 3186 } 3187 mb := fs.blks[0] 3188 fs.mu.RUnlock() 3189 3190 mb.mu.Lock() 3191 mb.compact() 3192 mb.mu.Unlock() 3193 3194 fs.FastState(&ssa) 3195 if !reflect.DeepEqual(ssb, ssa) { 3196 t.Fatalf("States do not match; %+v vs %+v", ssb, ssa) 3197 } 3198 ta, ua, _ := fs.Utilization() 3199 if ub != ua { 3200 t.Fatalf("Expected used to be the same, got %d vs %d", ub, ua) 3201 } 3202 if ta >= tb { 3203 t.Fatalf("Expected total after to be less then before, got %d vs %d", tb, ta) 3204 } 3205 } 3206 3207 // Actual testing here. 3208 loadMsgs(1000) 3209 checkState(1000, 1, 1000) 3210 3211 // Now delete a few messages. 3212 deleteMsgs(1) 3213 compact() 3214 3215 deleteMsgs(1000, 999, 998, 997) 3216 compact() 3217 3218 eraseMsgs(500, 502, 504, 506, 508, 510) 3219 compact() 3220 }) 3221 } 3222 3223 func TestFileStoreSparseCompactionWithInteriorDeletes(t *testing.T) { 3224 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3225 cfg := StreamConfig{Name: "KV", Subjects: []string{"kv.>"}, Storage: FileStorage} 3226 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3227 require_NoError(t, err) 3228 defer fs.Stop() 3229 3230 for i := 1; i <= 1000; i++ { 3231 if _, _, err := fs.StoreMsg(fmt.Sprintf("kv.%d", i%10), nil, []byte("OK")); err != nil { 3232 t.Fatalf("Unexpected error: %v", err) 3233 } 3234 } 3235 3236 // Now do interior deletes. 3237 for _, seq := range []uint64{500, 600, 700, 800} { 3238 removed, err := fs.RemoveMsg(seq) 3239 if err != nil || !removed { 3240 t.Fatalf("Got an error on remove of %d: %v", seq, err) 3241 } 3242 } 3243 3244 _, err = fs.LoadMsg(900, nil) 3245 if err != nil { 3246 t.Fatalf("Unexpected error: %v", err) 3247 } 3248 3249 // Do compact by hand, make sure we can still access msgs past the interior deletes. 3250 fs.mu.RLock() 3251 lmb := fs.lmb 3252 lmb.dirtyCloseWithRemove(false) 3253 lmb.compact() 3254 fs.mu.RUnlock() 3255 3256 if _, err = fs.LoadMsg(900, nil); err != nil { 3257 t.Fatalf("Unexpected error: %v", err) 3258 } 3259 }) 3260 } 3261 3262 // When messages span multiple blocks and we want to purge but keep some amount, say 1, we would remove all. 3263 // This is because we would not break out of iterator across more message blocks. 3264 // Issue #2622 3265 func TestFileStorePurgeExKeepOneBug(t *testing.T) { 3266 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3267 fcfg.BlockSize = 128 3268 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 3269 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3270 require_NoError(t, err) 3271 defer fs.Stop() 3272 3273 fill := bytes.Repeat([]byte("X"), 128) 3274 3275 fs.StoreMsg("A", nil, []byte("META")) 3276 fs.StoreMsg("B", nil, fill) 3277 fs.StoreMsg("A", nil, []byte("META")) 3278 fs.StoreMsg("B", nil, fill) 3279 3280 if fss := fs.FilteredState(1, "A"); fss.Msgs != 2 { 3281 t.Fatalf("Expected to find 2 `A` msgs, got %d", fss.Msgs) 3282 } 3283 3284 n, err := fs.PurgeEx("A", 0, 1) 3285 if err != nil { 3286 t.Fatalf("Unexpected error: %v", err) 3287 } 3288 if n != 1 { 3289 t.Fatalf("Expected PurgeEx to remove 1 `A` msgs, got %d", n) 3290 } 3291 if fss := fs.FilteredState(1, "A"); fss.Msgs != 1 { 3292 t.Fatalf("Expected to find 1 `A` msgs, got %d", fss.Msgs) 3293 } 3294 }) 3295 } 3296 3297 func TestFileStoreFilteredPendingBug(t *testing.T) { 3298 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3299 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 3300 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3301 require_NoError(t, err) 3302 defer fs.Stop() 3303 3304 fs.StoreMsg("foo", nil, []byte("msg")) 3305 fs.StoreMsg("bar", nil, []byte("msg")) 3306 fs.StoreMsg("baz", nil, []byte("msg")) 3307 3308 fs.mu.Lock() 3309 mb := fs.lmb 3310 fs.mu.Unlock() 3311 3312 total, f, l := mb.filteredPending("foo", false, 3) 3313 if total != 0 { 3314 t.Fatalf("Expected total of 0 but got %d", total) 3315 } 3316 if f != 0 || l != 0 { 3317 t.Fatalf("Expected first and last to be 0 as well, but got %d %d", f, l) 3318 } 3319 }) 3320 } 3321 3322 // Test to optimize the selectMsgBlock with lots of blocks. 3323 func TestFileStoreFetchPerf(t *testing.T) { 3324 // Comment out to run. 3325 t.SkipNow() 3326 3327 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3328 fcfg.BlockSize = 8192 3329 fcfg.AsyncFlush = true 3330 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 3331 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3332 require_NoError(t, err) 3333 defer fs.Stop() 3334 3335 // Will create 25k msg blocks. 3336 n, subj, msg := 100_000, "zzz", bytes.Repeat([]byte("ABC"), 600) 3337 for i := 0; i < n; i++ { 3338 if _, _, err := fs.StoreMsg(subj, nil, msg); err != nil { 3339 t.Fatalf("Unexpected error: %v", err) 3340 } 3341 } 3342 3343 // Time how long it takes us to load all messages. 3344 var smv StoreMsg 3345 now := time.Now() 3346 for i := 0; i < n; i++ { 3347 _, err := fs.LoadMsg(uint64(i), &smv) 3348 if err != nil { 3349 t.Fatalf("Unexpected error looking up seq %d: %v", i, err) 3350 } 3351 } 3352 fmt.Printf("Elapsed to load all messages is %v\n", time.Since(now)) 3353 }) 3354 } 3355 3356 // For things like raft log when we compact and have a message block that could reclaim > 50% of space for block we want to do that. 3357 // https://github.com/nats-io/nats-server/issues/2936 3358 func TestFileStoreCompactReclaimHeadSpace(t *testing.T) { 3359 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3360 fcfg.BlockSize = 4 * 1024 * 1024 3361 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 3362 created := time.Now() 3363 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 3364 require_NoError(t, err) 3365 defer fs.Stop() 3366 3367 // Create random bytes for payload to test for corruption vs repeated. 3368 msg := make([]byte, 64*1024) 3369 crand.Read(msg) 3370 3371 // This gives us ~63 msgs in first and ~37 in second. 3372 n, subj := 100, "z" 3373 for i := 0; i < n; i++ { 3374 _, _, err := fs.StoreMsg(subj, nil, msg) 3375 require_NoError(t, err) 3376 } 3377 3378 checkNumBlocks := func(n int) { 3379 t.Helper() 3380 fs.mu.RLock() 3381 defer fs.mu.RUnlock() 3382 if len(fs.blks) != n { 3383 t.Fatalf("Expected to have %d blocks, got %d", n, len(fs.blks)) 3384 } 3385 } 3386 3387 getBlock := func(index int) *msgBlock { 3388 t.Helper() 3389 fs.mu.RLock() 3390 defer fs.mu.RUnlock() 3391 return fs.blks[index] 3392 } 3393 3394 // Check that we did right thing and actually reclaimed since > 50% 3395 checkBlock := func(mb *msgBlock) { 3396 t.Helper() 3397 3398 mb.mu.RLock() 3399 nbytes, rbytes, mfn := mb.bytes, mb.rbytes, mb.mfn 3400 fseq, lseq := mb.first.seq, mb.last.seq 3401 mb.mu.RUnlock() 3402 3403 // Check that sizes match as long as we are not doing compression. 3404 if fcfg.Compression == NoCompression { 3405 // Check rbytes then the actual file as well. 3406 if nbytes != rbytes { 3407 t.Fatalf("Expected to reclaim and have bytes == rbytes, got %d vs %d", nbytes, rbytes) 3408 } 3409 file, err := os.Open(mfn) 3410 require_NoError(t, err) 3411 defer file.Close() 3412 fi, err := file.Stat() 3413 require_NoError(t, err) 3414 if rbytes != uint64(fi.Size()) { 3415 t.Fatalf("Expected to rbytes == fi.Size, got %d vs %d", rbytes, fi.Size()) 3416 } 3417 } 3418 3419 // Make sure we can pull messages and that they are ok. 3420 var smv StoreMsg 3421 sm, err := fs.LoadMsg(fseq, &smv) 3422 require_NoError(t, err) 3423 if !bytes.Equal(sm.msg, msg) { 3424 t.Fatalf("Msgs don't match, original %q vs %q", msg, sm.msg) 3425 } 3426 sm, err = fs.LoadMsg(lseq, &smv) 3427 require_NoError(t, err) 3428 if !bytes.Equal(sm.msg, msg) { 3429 t.Fatalf("Msgs don't match, original %q vs %q", msg, sm.msg) 3430 } 3431 } 3432 3433 checkNumBlocks(2) 3434 _, err = fs.Compact(33) 3435 require_NoError(t, err) 3436 3437 checkNumBlocks(2) 3438 checkBlock(getBlock(0)) 3439 checkBlock(getBlock(1)) 3440 3441 _, err = fs.Compact(85) 3442 require_NoError(t, err) 3443 3444 checkNumBlocks(1) 3445 checkBlock(getBlock(0)) 3446 3447 // Make sure we can write. 3448 _, _, err = fs.StoreMsg(subj, nil, msg) 3449 require_NoError(t, err) 3450 3451 checkNumBlocks(1) 3452 checkBlock(getBlock(0)) 3453 3454 // Stop and start again. 3455 fs.Stop() 3456 3457 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 3458 require_NoError(t, err) 3459 defer fs.Stop() 3460 3461 checkNumBlocks(1) 3462 checkBlock(getBlock(0)) 3463 3464 // Make sure we can write. 3465 _, _, err = fs.StoreMsg(subj, nil, msg) 3466 require_NoError(t, err) 3467 }) 3468 } 3469 3470 func TestFileStoreRememberLastMsgTime(t *testing.T) { 3471 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3472 var fs *fileStore 3473 cfg := StreamConfig{Name: "TEST", Storage: FileStorage, MaxAge: 1 * time.Second} 3474 3475 getFS := func() *fileStore { 3476 t.Helper() 3477 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3478 require_NoError(t, err) 3479 return fs 3480 } 3481 restartFS := func() { 3482 t.Helper() 3483 fs.Stop() 3484 fs = getFS() 3485 } 3486 3487 msg := bytes.Repeat([]byte("X"), 2*1024*1024) 3488 3489 // Get first one. 3490 fs = getFS() 3491 defer fs.Stop() 3492 3493 seq, ts, err := fs.StoreMsg("foo", nil, msg) 3494 require_NoError(t, err) 3495 // We will test that last msg time survives from delete, purge and expires after restart. 3496 removed, err := fs.RemoveMsg(seq) 3497 require_NoError(t, err) 3498 require_True(t, removed) 3499 3500 lt := time.Unix(0, ts).UTC() 3501 require_True(t, lt == fs.State().LastTime) 3502 3503 // Restart 3504 restartFS() 3505 3506 // Test that last time survived. 3507 require_True(t, lt == fs.State().LastTime) 3508 3509 seq, ts, err = fs.StoreMsg("foo", nil, msg) 3510 require_NoError(t, err) 3511 3512 var smv StoreMsg 3513 _, err = fs.LoadMsg(seq, &smv) 3514 require_NoError(t, err) 3515 3516 fs.Purge() 3517 3518 // Restart 3519 restartFS() 3520 3521 lt = time.Unix(0, ts).UTC() 3522 require_True(t, lt == fs.State().LastTime) 3523 3524 _, _, err = fs.StoreMsg("foo", nil, msg) 3525 require_NoError(t, err) 3526 seq, ts, err = fs.StoreMsg("foo", nil, msg) 3527 require_NoError(t, err) 3528 3529 require_True(t, seq == 4) 3530 3531 // Wait til messages expire. 3532 checkFor(t, 5*time.Second, time.Second, func() error { 3533 state := fs.State() 3534 if state.Msgs == 0 { 3535 return nil 3536 } 3537 return fmt.Errorf("Still has %d msgs", state.Msgs) 3538 }) 3539 3540 // Restart 3541 restartFS() 3542 3543 lt = time.Unix(0, ts).UTC() 3544 require_True(t, lt == fs.State().LastTime) 3545 3546 // Now make sure we retain the true last seq. 3547 _, _, err = fs.StoreMsg("foo", nil, msg) 3548 require_NoError(t, err) 3549 seq, ts, err = fs.StoreMsg("foo", nil, msg) 3550 require_NoError(t, err) 3551 3552 require_True(t, seq == 6) 3553 removed, err = fs.RemoveMsg(seq) 3554 require_NoError(t, err) 3555 require_True(t, removed) 3556 3557 removed, err = fs.RemoveMsg(seq - 1) 3558 require_NoError(t, err) 3559 require_True(t, removed) 3560 3561 // Restart 3562 restartFS() 3563 3564 lt = time.Unix(0, ts).UTC() 3565 require_True(t, lt == fs.State().LastTime) 3566 require_True(t, seq == 6) 3567 }) 3568 } 3569 3570 func (fs *fileStore) getFirstBlock() *msgBlock { 3571 fs.mu.RLock() 3572 defer fs.mu.RUnlock() 3573 if len(fs.blks) == 0 { 3574 return nil 3575 } 3576 return fs.blks[0] 3577 } 3578 3579 func TestFileStoreRebuildStateDmapAccountingBug(t *testing.T) { 3580 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3581 fcfg.BlockSize = 1024 * 1024 3582 3583 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 3584 require_NoError(t, err) 3585 defer fs.Stop() 3586 3587 for i := 0; i < 100; i++ { 3588 _, _, err = fs.StoreMsg("foo", nil, nil) 3589 require_NoError(t, err) 3590 } 3591 // Delete 2-40. 3592 for i := 2; i <= 40; i++ { 3593 _, err := fs.RemoveMsg(uint64(i)) 3594 require_NoError(t, err) 3595 } 3596 3597 mb := fs.getFirstBlock() 3598 require_True(t, mb != nil) 3599 3600 check := func() { 3601 t.Helper() 3602 mb.mu.RLock() 3603 defer mb.mu.RUnlock() 3604 dmapLen := uint64(mb.dmap.Size()) 3605 if mb.msgs != (mb.last.seq-mb.first.seq+1)-dmapLen { 3606 t.Fatalf("Consistency check failed: %d != %d -> last %d first %d len(dmap) %d", 3607 mb.msgs, (mb.last.seq-mb.first.seq+1)-dmapLen, mb.last.seq, mb.first.seq, dmapLen) 3608 } 3609 } 3610 3611 check() 3612 3613 mb.mu.Lock() 3614 mb.compact() 3615 mb.mu.Unlock() 3616 3617 // Now delete first. 3618 _, err = fs.RemoveMsg(1) 3619 require_NoError(t, err) 3620 3621 mb.mu.Lock() 3622 _, _, err = mb.rebuildStateLocked() 3623 mb.mu.Unlock() 3624 require_NoError(t, err) 3625 3626 check() 3627 }) 3628 } 3629 3630 func TestFileStorePurgeExWithSubject(t *testing.T) { 3631 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3632 fcfg.BlockSize = 1000 3633 cfg := StreamConfig{Name: "TEST", Subjects: []string{"foo.>"}, Storage: FileStorage} 3634 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3635 require_NoError(t, err) 3636 defer fs.Stop() 3637 3638 payload := make([]byte, 20) 3639 total := 200 3640 for i := 0; i < total; i++ { 3641 _, _, err = fs.StoreMsg("foo.1", nil, payload) 3642 require_NoError(t, err) 3643 } 3644 _, _, err = fs.StoreMsg("foo.2", nil, []byte("xxxxxx")) 3645 require_NoError(t, err) 3646 3647 // This should purge all. 3648 p, err := fs.PurgeEx("foo.1", 1, 0) 3649 require_NoError(t, err) 3650 require_True(t, int(p) == total) 3651 require_True(t, int(p) == total) 3652 require_True(t, fs.State().Msgs == 1) 3653 require_True(t, fs.State().FirstSeq == 201) 3654 }) 3655 } 3656 3657 // When the N.idx file is shorter than the previous write we could fail to recover the idx properly. 3658 // For instance, with encryption and an expiring stream that has no messages, when a restart happens the decrypt will fail 3659 // since their are extra bytes, and this could lead to a stream sequence reset to zero. 3660 // 3661 // NOTE: We do not use idx files anymore, but keeping test. 3662 func TestFileStoreShortIndexWriteBug(t *testing.T) { 3663 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3664 // Encrypted mode shows, but could effect non-encrypted mode. 3665 cfg := StreamConfig{Name: "TEST", Storage: FileStorage, MaxAge: time.Second} 3666 created := time.Now() 3667 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 3668 require_NoError(t, err) 3669 defer fs.Stop() 3670 3671 for i := 0; i < 100; i++ { 3672 _, _, err = fs.StoreMsg("foo", nil, nil) 3673 require_NoError(t, err) 3674 } 3675 // Wait til messages all go away. 3676 checkFor(t, 5*time.Second, 200*time.Millisecond, func() error { 3677 if state := fs.State(); state.Msgs != 0 { 3678 return fmt.Errorf("Expected no msgs, got %d", state.Msgs) 3679 } 3680 return nil 3681 }) 3682 3683 if state := fs.State(); state.FirstSeq != 101 { 3684 t.Fatalf("Expected first sequence of 101 vs %d", state.FirstSeq) 3685 } 3686 3687 // Now restart.. 3688 fs.Stop() 3689 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 3690 require_NoError(t, err) 3691 defer fs.Stop() 3692 3693 if state := fs.State(); state.FirstSeq != 101 || state.LastSeq != 100 { 3694 t.Fatalf("Expected first sequence of 101 vs %d", state.FirstSeq) 3695 } 3696 }) 3697 } 3698 3699 func TestFileStoreDoubleCompactWithWriteInBetweenEncryptedBug(t *testing.T) { 3700 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3701 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 3702 require_NoError(t, err) 3703 defer fs.Stop() 3704 3705 subj, msg := "foo", []byte("ouch") 3706 for i := 0; i < 5; i++ { 3707 fs.StoreMsg(subj, nil, msg) 3708 } 3709 _, err = fs.Compact(5) 3710 require_NoError(t, err) 3711 3712 if state := fs.State(); state.LastSeq != 5 { 3713 t.Fatalf("Expected last sequence to be 5 but got %d", state.LastSeq) 3714 } 3715 for i := 0; i < 5; i++ { 3716 fs.StoreMsg(subj, nil, msg) 3717 } 3718 _, err = fs.Compact(10) 3719 require_NoError(t, err) 3720 3721 if state := fs.State(); state.LastSeq != 10 { 3722 t.Fatalf("Expected last sequence to be 10 but got %d", state.LastSeq) 3723 } 3724 }) 3725 } 3726 3727 // When we kept the empty block for tracking sequence, we needed to reset the bek 3728 // counter when encrypted for subsequent writes to be correct. The bek in place could 3729 // possibly still have a non-zero counter from previous writes. 3730 // Happens when all messages expire and the are flushed and then subsequent writes occur. 3731 func TestFileStoreEncryptedKeepIndexNeedBekResetBug(t *testing.T) { 3732 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3733 ttl := 1 * time.Second 3734 cfg := StreamConfig{Name: "zzz", Storage: FileStorage, MaxAge: ttl} 3735 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3736 require_NoError(t, err) 3737 defer fs.Stop() 3738 3739 subj, msg := "foo", []byte("ouch") 3740 for i := 0; i < 5; i++ { 3741 fs.StoreMsg(subj, nil, msg) 3742 } 3743 3744 // Want to go to 0. 3745 // This will leave the marker. 3746 checkFor(t, 5*time.Second, ttl, func() error { 3747 if state := fs.State(); state.Msgs != 0 { 3748 return fmt.Errorf("Expected no msgs, got %d", state.Msgs) 3749 } 3750 return nil 3751 }) 3752 3753 // Now write additional messages. 3754 for i := 0; i < 5; i++ { 3755 fs.StoreMsg(subj, nil, msg) 3756 } 3757 3758 // Make sure the buffer is cleared. 3759 fs.mu.RLock() 3760 mb := fs.lmb 3761 fs.mu.RUnlock() 3762 mb.mu.Lock() 3763 mb.clearCacheAndOffset() 3764 mb.mu.Unlock() 3765 3766 // Now make sure we can read. 3767 var smv StoreMsg 3768 _, err = fs.LoadMsg(10, &smv) 3769 require_NoError(t, err) 3770 }) 3771 } 3772 3773 func (fs *fileStore) reportMeta() (hasPSIM, hasAnyFSS bool) { 3774 fs.mu.RLock() 3775 defer fs.mu.RUnlock() 3776 3777 hasPSIM = fs.psim != nil 3778 for _, mb := range fs.blks { 3779 mb.mu.RLock() 3780 hasAnyFSS = hasAnyFSS || mb.fss != nil 3781 mb.mu.RUnlock() 3782 if hasAnyFSS { 3783 break 3784 } 3785 } 3786 return hasPSIM, hasAnyFSS 3787 } 3788 3789 func TestFileStoreExpireSubjectMeta(t *testing.T) { 3790 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3791 fcfg.BlockSize = 1024 3792 fcfg.CacheExpire = time.Second 3793 fcfg.SyncInterval = time.Second 3794 cfg := StreamConfig{Name: "zzz", Subjects: []string{"kv.>"}, Storage: FileStorage, MaxMsgsPer: 1} 3795 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3796 require_NoError(t, err) 3797 defer fs.Stop() 3798 3799 ns := 100 3800 for i := 1; i <= ns; i++ { 3801 subj := fmt.Sprintf("kv.%d", i) 3802 _, _, err := fs.StoreMsg(subj, nil, []byte("value")) 3803 require_NoError(t, err) 3804 } 3805 3806 // Test that on restart we do not have extensize metadata but do have correct number of subjects/keys. 3807 // Only thing really needed for store state / stream info. 3808 fs.Stop() 3809 fs, err = newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3810 require_NoError(t, err) 3811 defer fs.Stop() 3812 3813 var ss StreamState 3814 fs.FastState(&ss) 3815 if ss.NumSubjects != ns { 3816 t.Fatalf("Expected NumSubjects of %d, got %d", ns, ss.NumSubjects) 3817 } 3818 3819 // Make sure we clear mb fss meta 3820 checkFor(t, 10*time.Second, 500*time.Millisecond, func() error { 3821 if _, hasAnyFSS := fs.reportMeta(); hasAnyFSS { 3822 return fmt.Errorf("Still have mb fss state") 3823 } 3824 return nil 3825 }) 3826 3827 // LoadLast, which is what KV uses, should load meta and succeed. 3828 _, err = fs.LoadLastMsg("kv.22", nil) 3829 require_NoError(t, err) 3830 // Make sure we clear mb fss meta 3831 checkFor(t, 10*time.Second, 500*time.Millisecond, func() error { 3832 if _, hasAnyFSS := fs.reportMeta(); hasAnyFSS { 3833 return fmt.Errorf("Still have mb fss state") 3834 } 3835 return nil 3836 }) 3837 }) 3838 } 3839 3840 func TestFileStoreMaxMsgsPerSubject(t *testing.T) { 3841 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3842 fcfg.BlockSize = 128 3843 fcfg.CacheExpire = time.Second 3844 cfg := StreamConfig{Name: "zzz", Subjects: []string{"kv.>"}, Storage: FileStorage, MaxMsgsPer: 1} 3845 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3846 require_NoError(t, err) 3847 defer fs.Stop() 3848 3849 ns := 100 3850 for i := 1; i <= ns; i++ { 3851 subj := fmt.Sprintf("kv.%d", i) 3852 _, _, err := fs.StoreMsg(subj, nil, []byte("value")) 3853 require_NoError(t, err) 3854 } 3855 3856 for i := 1; i <= ns; i++ { 3857 subj := fmt.Sprintf("kv.%d", i) 3858 _, _, err := fs.StoreMsg(subj, nil, []byte("value")) 3859 require_NoError(t, err) 3860 } 3861 3862 if state := fs.State(); state.Msgs != 100 || state.FirstSeq != 101 || state.LastSeq != 200 || len(state.Deleted) != 0 { 3863 t.Fatalf("Bad state: %+v", state) 3864 } 3865 3866 if nb := fs.numMsgBlocks(); nb != 34 { 3867 t.Fatalf("Expected 34 blocks, got %d", nb) 3868 } 3869 }) 3870 } 3871 3872 // Testing the case in https://github.com/nats-io/nats-server/issues/4247 3873 func TestFileStoreMaxMsgsAndMaxMsgsPerSubject(t *testing.T) { 3874 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3875 fcfg.BlockSize = 128 3876 fcfg.CacheExpire = time.Second 3877 cfg := StreamConfig{ 3878 Name: "zzz", 3879 Subjects: []string{"kv.>"}, 3880 Storage: FileStorage, 3881 Discard: DiscardNew, MaxMsgs: 100, // Total stream policy 3882 DiscardNewPer: true, MaxMsgsPer: 1, // Per-subject policy 3883 } 3884 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3885 require_NoError(t, err) 3886 defer fs.Stop() 3887 3888 for i := 1; i <= 101; i++ { 3889 subj := fmt.Sprintf("kv.%d", i) 3890 _, _, err := fs.StoreMsg(subj, nil, []byte("value")) 3891 if i == 101 { 3892 // The 101th iteration should fail because MaxMsgs is set to 3893 // 100 and the policy is DiscardNew. 3894 require_Error(t, err) 3895 } else { 3896 require_NoError(t, err) 3897 } 3898 } 3899 3900 for i := 1; i <= 100; i++ { 3901 subj := fmt.Sprintf("kv.%d", i) 3902 _, _, err := fs.StoreMsg(subj, nil, []byte("value")) 3903 // All of these iterations should fail because MaxMsgsPer is set 3904 // to 1 and DiscardNewPer is set to true, forcing us to reject 3905 // cases where there is already a message on this subject. 3906 require_Error(t, err) 3907 } 3908 3909 if state := fs.State(); state.Msgs != 100 || state.FirstSeq != 1 || state.LastSeq != 100 || len(state.Deleted) != 0 { 3910 // There should be 100 messages exactly, as the 101st subject 3911 // should have been rejected in the first loop, and any duplicates 3912 // on the other subjects should have been rejected in the second loop. 3913 t.Fatalf("Bad state: %+v", state) 3914 } 3915 }) 3916 } 3917 3918 func TestFileStoreSubjectStateCacheExpiration(t *testing.T) { 3919 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3920 fcfg.BlockSize = 32 3921 fcfg.CacheExpire = time.Second 3922 fcfg.SyncInterval = time.Second 3923 cfg := StreamConfig{Name: "zzz", Subjects: []string{"kv.>"}, Storage: FileStorage, MaxMsgsPer: 2} 3924 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 3925 require_NoError(t, err) 3926 defer fs.Stop() 3927 3928 for i := 1; i <= 100; i++ { 3929 subj := fmt.Sprintf("kv.foo.%d", i) 3930 _, _, err := fs.StoreMsg(subj, nil, []byte("value")) 3931 require_NoError(t, err) 3932 } 3933 for i := 1; i <= 100; i++ { 3934 subj := fmt.Sprintf("kv.bar.%d", i) 3935 _, _, err := fs.StoreMsg(subj, nil, []byte("value")) 3936 require_NoError(t, err) 3937 } 3938 3939 // Make sure we clear mb fss meta before asking for SubjectState. 3940 checkFor(t, 10*time.Second, 500*time.Millisecond, func() error { 3941 if _, hasAnyFSS := fs.reportMeta(); hasAnyFSS { 3942 return fmt.Errorf("Still have mb fss state") 3943 } 3944 return nil 3945 }) 3946 3947 if fss := fs.SubjectsState("kv.bar.>"); len(fss) != 100 { 3948 t.Fatalf("Expected 100 entries but got %d", len(fss)) 3949 } 3950 3951 fss := fs.SubjectsState("kv.bar.99") 3952 if len(fss) != 1 { 3953 t.Fatalf("Expected 1 entry but got %d", len(fss)) 3954 } 3955 expected := SimpleState{Msgs: 1, First: 199, Last: 199} 3956 if ss := fss["kv.bar.99"]; ss != expected { 3957 t.Fatalf("Bad subject state, expected %+v but got %+v", expected, ss) 3958 } 3959 3960 // Now add one to end and check as well for non-wildcard. 3961 _, _, err = fs.StoreMsg("kv.foo.1", nil, []byte("value22")) 3962 require_NoError(t, err) 3963 3964 if state := fs.State(); state.Msgs != 201 { 3965 t.Fatalf("Expected 201 msgs but got %+v", state) 3966 } 3967 3968 fss = fs.SubjectsState("kv.foo.1") 3969 if len(fss) != 1 { 3970 t.Fatalf("Expected 1 entry but got %d", len(fss)) 3971 } 3972 expected = SimpleState{Msgs: 2, First: 1, Last: 201} 3973 if ss := fss["kv.foo.1"]; ss != expected { 3974 t.Fatalf("Bad subject state, expected %+v but got %+v", expected, ss) 3975 } 3976 }) 3977 } 3978 3979 func TestFileStoreEncrypted(t *testing.T) { 3980 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 3981 created := time.Now() 3982 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 3983 require_NoError(t, err) 3984 defer fs.Stop() 3985 3986 subj, msg := "foo", []byte("aes ftw") 3987 for i := 0; i < 50; i++ { 3988 fs.StoreMsg(subj, nil, msg) 3989 } 3990 3991 o, err := fs.ConsumerStore("o22", &ConsumerConfig{}) 3992 require_NoError(t, err) 3993 3994 state := &ConsumerState{} 3995 state.Delivered.Consumer = 22 3996 state.Delivered.Stream = 22 3997 state.AckFloor.Consumer = 11 3998 state.AckFloor.Stream = 11 3999 err = o.Update(state) 4000 require_NoError(t, err) 4001 4002 fs.Stop() 4003 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 4004 require_NoError(t, err) 4005 defer fs.Stop() 4006 4007 // Now make sure we can read. 4008 var smv StoreMsg 4009 sm, err := fs.LoadMsg(10, &smv) 4010 require_NoError(t, err) 4011 require_True(t, string(sm.msg) == "aes ftw") 4012 4013 o, err = fs.ConsumerStore("o22", &ConsumerConfig{}) 4014 require_NoError(t, err) 4015 rstate, err := o.State() 4016 require_NoError(t, err) 4017 4018 if rstate.Delivered != state.Delivered || rstate.AckFloor != state.AckFloor { 4019 t.Fatalf("Bad recovered consumer state, expected %+v got %+v", state, rstate) 4020 } 4021 }) 4022 } 4023 4024 // Make sure we do not go through block loads when we know no subjects will exists, e.g. raft. 4025 func TestFileStoreNoFSSWhenNoSubjects(t *testing.T) { 4026 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4027 created := time.Now() 4028 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 4029 require_NoError(t, err) 4030 defer fs.Stop() 4031 4032 n, msg := 100, []byte("raft state") 4033 for i := 0; i < n; i++ { 4034 _, _, err := fs.StoreMsg(_EMPTY_, nil, msg) 4035 require_NoError(t, err) 4036 } 4037 4038 state := fs.State() 4039 require_True(t, state.Msgs == uint64(n)) 4040 4041 fs.Stop() 4042 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, created, prf(&fcfg), nil) 4043 require_NoError(t, err) 4044 defer fs.Stop() 4045 4046 // Make sure we did not load the block trying to generate fss. 4047 fs.mu.RLock() 4048 mb := fs.blks[0] 4049 fs.mu.RUnlock() 4050 4051 mb.mu.Lock() 4052 defer mb.mu.Unlock() 4053 4054 if mb.cloads > 0 { 4055 t.Fatalf("Expected no cache loads but got %d", mb.cloads) 4056 } 4057 if mb.fss != nil { 4058 t.Fatalf("Expected fss to be nil") 4059 } 4060 }) 4061 } 4062 4063 func TestFileStoreNoFSSBugAfterRemoveFirst(t *testing.T) { 4064 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4065 fcfg.BlockSize = 8 * 1024 * 1024 4066 fcfg.CacheExpire = 200 * time.Millisecond 4067 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo.bar.*"}, Storage: FileStorage} 4068 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4069 require_NoError(t, err) 4070 defer fs.Stop() 4071 4072 n, msg := 100, bytes.Repeat([]byte("ZZZ"), 33) // ~100bytes 4073 for i := 0; i < n; i++ { 4074 subj := fmt.Sprintf("foo.bar.%d", i) 4075 _, _, err := fs.StoreMsg(subj, nil, msg) 4076 require_NoError(t, err) 4077 } 4078 4079 state := fs.State() 4080 require_True(t, state.Msgs == uint64(n)) 4081 4082 // Let fss expire. 4083 time.Sleep(250 * time.Millisecond) 4084 4085 _, err = fs.RemoveMsg(1) 4086 require_NoError(t, err) 4087 4088 sm, _, err := fs.LoadNextMsg("foo.>", true, 1, nil) 4089 require_NoError(t, err) 4090 require_True(t, sm.subj == "foo.bar.1") 4091 4092 // Make sure mb.fss does not have the entry for foo.bar.0 4093 fs.mu.Lock() 4094 mb := fs.blks[0] 4095 fs.mu.Unlock() 4096 mb.mu.RLock() 4097 ss := mb.fss["foo.bar.0"] 4098 mb.mu.RUnlock() 4099 4100 if ss != nil { 4101 t.Fatalf("Expected no state for %q, but got %+v\n", "foo.bar.0", ss) 4102 } 4103 }) 4104 } 4105 4106 // NOTE: We do not use fss files anymore, but leaving test in place. 4107 func TestFileStoreNoFSSAfterRecover(t *testing.T) { 4108 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4109 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 4110 created := time.Now() 4111 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4112 require_NoError(t, err) 4113 defer fs.Stop() 4114 4115 n, msg := 100, []byte("no fss for you!") 4116 for i := 0; i < n; i++ { 4117 _, _, err := fs.StoreMsg(_EMPTY_, nil, msg) 4118 require_NoError(t, err) 4119 } 4120 4121 state := fs.State() 4122 require_True(t, state.Msgs == uint64(n)) 4123 4124 fs.Stop() 4125 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4126 require_NoError(t, err) 4127 defer fs.Stop() 4128 4129 // Make sure we did not load the block trying to generate fss. 4130 fs.mu.RLock() 4131 mb := fs.blks[0] 4132 fs.mu.RUnlock() 4133 4134 mb.mu.Lock() 4135 defer mb.mu.Unlock() 4136 4137 if mb.fss != nil { 4138 t.Fatalf("Expected no fss post recover") 4139 } 4140 }) 4141 } 4142 4143 func TestFileStoreFSSCloseAndKeepOnExpireOnRecoverBug(t *testing.T) { 4144 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4145 ttl := 100 * time.Millisecond 4146 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage, MaxAge: ttl} 4147 created := time.Now() 4148 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4149 require_NoError(t, err) 4150 defer fs.Stop() 4151 4152 _, _, err = fs.StoreMsg("foo", nil, nil) 4153 require_NoError(t, err) 4154 4155 fs.Stop() 4156 time.Sleep(2 * ttl) 4157 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4158 require_NoError(t, err) 4159 defer fs.Stop() 4160 4161 if state := fs.State(); state.NumSubjects != 0 { 4162 t.Fatalf("Expected no subjects with no messages, got %d", state.NumSubjects) 4163 } 4164 }) 4165 } 4166 4167 func TestFileStoreExpireOnRecoverSubjectAccounting(t *testing.T) { 4168 const msgLen = 19 4169 msg := bytes.Repeat([]byte("A"), msgLen) 4170 4171 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4172 fcfg.BlockSize = 100 4173 ttl := 200 * time.Millisecond 4174 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage, MaxAge: ttl} 4175 created := time.Now() 4176 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4177 require_NoError(t, err) 4178 defer fs.Stop() 4179 4180 // These are in first block. 4181 fs.StoreMsg("A", nil, msg) 4182 fs.StoreMsg("B", nil, msg) 4183 time.Sleep(ttl / 2) 4184 // This one in 2nd block. 4185 fs.StoreMsg("C", nil, msg) 4186 4187 fs.Stop() 4188 time.Sleep(ttl/2 + 10*time.Millisecond) 4189 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4190 require_NoError(t, err) 4191 defer fs.Stop() 4192 4193 // Make sure we take into account PSIM when throwing a whole block away. 4194 if state := fs.State(); state.NumSubjects != 1 { 4195 t.Fatalf("Expected 1 subject, got %d", state.NumSubjects) 4196 } 4197 }) 4198 } 4199 4200 func TestFileStoreFSSExpireNumPendingBug(t *testing.T) { 4201 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4202 cexp := 100 * time.Millisecond 4203 fcfg.CacheExpire = cexp 4204 cfg := StreamConfig{Name: "zzz", Subjects: []string{"KV.>"}, MaxMsgsPer: 1, Storage: FileStorage} 4205 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4206 require_NoError(t, err) 4207 defer fs.Stop() 4208 4209 // Let FSS meta expire. 4210 time.Sleep(2 * cexp) 4211 4212 _, _, err = fs.StoreMsg("KV.X", nil, []byte("Y")) 4213 require_NoError(t, err) 4214 4215 if fss := fs.FilteredState(1, "KV.X"); fss.Msgs != 1 { 4216 t.Fatalf("Expected only 1 msg, got %d", fss.Msgs) 4217 } 4218 }) 4219 } 4220 4221 // https://github.com/nats-io/nats-server/issues/3484 4222 func TestFileStoreFilteredFirstMatchingBug(t *testing.T) { 4223 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4224 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo.>"}, Storage: FileStorage} 4225 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4226 require_NoError(t, err) 4227 defer fs.Stop() 4228 4229 _, _, err = fs.StoreMsg("foo.foo", nil, []byte("A")) 4230 require_NoError(t, err) 4231 4232 _, _, err = fs.StoreMsg("foo.foo", nil, []byte("B")) 4233 require_NoError(t, err) 4234 4235 _, _, err = fs.StoreMsg("foo.foo", nil, []byte("C")) 4236 require_NoError(t, err) 4237 4238 fs.mu.RLock() 4239 mb := fs.lmb 4240 fs.mu.RUnlock() 4241 4242 mb.mu.Lock() 4243 // Simulate swapping out the fss state and reading it back in with only one subject 4244 // present in the block. 4245 if mb.fss != nil { 4246 mb.fss = nil 4247 } 4248 // Now load info back in. 4249 mb.generatePerSubjectInfo() 4250 mb.mu.Unlock() 4251 4252 // Now add in a different subject. 4253 _, _, err = fs.StoreMsg("foo.bar", nil, []byte("X")) 4254 require_NoError(t, err) 4255 4256 // Now see if a filtered load would incorrectly succeed. 4257 sm, _, err := fs.LoadNextMsg("foo.foo", false, 4, nil) 4258 if err == nil || sm != nil { 4259 t.Fatalf("Loaded filtered message with wrong subject, wanted %q got %q", "foo.foo", sm.subj) 4260 } 4261 }) 4262 } 4263 4264 func TestFileStoreOutOfSpaceRebuildState(t *testing.T) { 4265 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4266 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 4267 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4268 require_NoError(t, err) 4269 defer fs.Stop() 4270 4271 _, _, err = fs.StoreMsg("foo", nil, []byte("A")) 4272 require_NoError(t, err) 4273 4274 _, _, err = fs.StoreMsg("bar", nil, []byte("B")) 4275 require_NoError(t, err) 4276 4277 // Grab state. 4278 state := fs.State() 4279 ss := fs.SubjectsState(">") 4280 4281 // Set mock out of space error to trip. 4282 fs.mu.RLock() 4283 mb := fs.lmb 4284 fs.mu.RUnlock() 4285 4286 mb.mu.Lock() 4287 mb.mockWriteErr = true 4288 mb.mu.Unlock() 4289 4290 _, _, err = fs.StoreMsg("baz", nil, []byte("C")) 4291 require_Error(t, err, errors.New("mock write error")) 4292 4293 nstate := fs.State() 4294 nss := fs.SubjectsState(">") 4295 4296 if !reflect.DeepEqual(state, nstate) { 4297 t.Fatalf("State expected to be\n %+v\nvs\n %+v", state, nstate) 4298 } 4299 4300 if !reflect.DeepEqual(ss, nss) { 4301 t.Fatalf("Subject state expected to be\n %+v\nvs\n %+v", ss, nss) 4302 } 4303 }) 4304 } 4305 4306 func TestFileStoreRebuildStateProperlyWithMaxMsgsPerSubject(t *testing.T) { 4307 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4308 fcfg.BlockSize = 4096 4309 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo", "bar", "baz"}, Storage: FileStorage, MaxMsgsPer: 1} 4310 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4311 require_NoError(t, err) 4312 defer fs.Stop() 4313 4314 // Send one to baz at beginning. 4315 _, _, err = fs.StoreMsg("baz", nil, nil) 4316 require_NoError(t, err) 4317 4318 ns := 1000 4319 for i := 1; i <= ns; i++ { 4320 _, _, err := fs.StoreMsg("foo", nil, nil) 4321 require_NoError(t, err) 4322 _, _, err = fs.StoreMsg("bar", nil, nil) 4323 require_NoError(t, err) 4324 } 4325 4326 var ss StreamState 4327 fs.FastState(&ss) 4328 if ss.NumSubjects != 3 { 4329 t.Fatalf("Expected NumSubjects of 3, got %d", ss.NumSubjects) 4330 } 4331 if ss.Msgs != 3 { 4332 t.Fatalf("Expected NumMsgs of 3, got %d", ss.Msgs) 4333 } 4334 }) 4335 } 4336 4337 func TestFileStoreUpdateMaxMsgsPerSubject(t *testing.T) { 4338 cfg := StreamConfig{ 4339 Name: "TEST", 4340 Storage: FileStorage, 4341 Subjects: []string{"foo"}, 4342 MaxMsgsPer: 10, 4343 } 4344 4345 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4346 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4347 require_NoError(t, err) 4348 defer fs.Stop() 4349 4350 // Make sure this is honored on an update. 4351 cfg.MaxMsgsPer = 50 4352 err = fs.UpdateConfig(&cfg) 4353 require_NoError(t, err) 4354 4355 numStored := 22 4356 for i := 0; i < numStored; i++ { 4357 _, _, err = fs.StoreMsg("foo", nil, nil) 4358 require_NoError(t, err) 4359 } 4360 4361 ss := fs.SubjectsState("foo")["foo"] 4362 if ss.Msgs != uint64(numStored) { 4363 t.Fatalf("Expected to have %d stored, got %d", numStored, ss.Msgs) 4364 } 4365 4366 // Now make sure we trunk if setting to lower value. 4367 cfg.MaxMsgsPer = 10 4368 err = fs.UpdateConfig(&cfg) 4369 require_NoError(t, err) 4370 4371 ss = fs.SubjectsState("foo")["foo"] 4372 if ss.Msgs != 10 { 4373 t.Fatalf("Expected to have %d stored, got %d", 10, ss.Msgs) 4374 } 4375 }) 4376 } 4377 4378 func TestFileStoreBadFirstAndFailedExpireAfterRestart(t *testing.T) { 4379 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4380 fcfg.BlockSize = 256 4381 ttl := time.Second 4382 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage, MaxAge: ttl} 4383 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4384 require_NoError(t, err) 4385 defer fs.Stop() 4386 4387 // With block size of 256 and subject and message below, seq 8 starts new block. 4388 // Will double check and fail test if not the case since test depends on this. 4389 subj, msg := "foo", []byte("ZZ") 4390 // These are all instant and will expire after 1 sec. 4391 start := time.Now() 4392 for i := 0; i < 7; i++ { 4393 _, _, err := fs.StoreMsg(subj, nil, msg) 4394 require_NoError(t, err) 4395 } 4396 4397 // Put two more after a delay. 4398 time.Sleep(1500 * time.Millisecond) 4399 seq, _, err := fs.StoreMsg(subj, nil, msg) 4400 require_NoError(t, err) 4401 _, _, err = fs.StoreMsg(subj, nil, msg) 4402 require_NoError(t, err) 4403 4404 // Make sure that sequence 8 is first in second block, and break test if that is not true. 4405 fs.mu.RLock() 4406 lmb := fs.lmb 4407 fs.mu.RUnlock() 4408 lmb.mu.RLock() 4409 first := lmb.first.seq 4410 lmb.mu.RUnlock() 4411 require_True(t, first == 8) 4412 4413 // Instantly remove first one from second block. 4414 // On restart this will trigger expire on recover which will set fs.FirstSeq to the deleted one. 4415 fs.RemoveMsg(seq) 4416 4417 // Stop the filstore and wait til first block expires. 4418 fs.Stop() 4419 time.Sleep(ttl - time.Since(start) + (time.Second)) 4420 fs, err = newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4421 require_NoError(t, err) 4422 defer fs.Stop() 4423 4424 // Check that state is correct for first message which should be 9 and have a proper timestamp. 4425 var state StreamState 4426 fs.FastState(&state) 4427 ts := state.FirstTime 4428 require_True(t, state.Msgs == 1) 4429 require_True(t, state.FirstSeq == 9) 4430 require_True(t, !state.FirstTime.IsZero()) 4431 4432 // Wait and make sure expire timer is still working properly. 4433 time.Sleep(2 * ttl) 4434 fs.FastState(&state) 4435 require_Equal(t, state.Msgs, 0) 4436 require_Equal(t, state.FirstSeq, 10) 4437 require_Equal(t, state.LastSeq, 9) 4438 require_Equal(t, state.LastTime, ts) 4439 }) 4440 } 4441 4442 func TestFileStoreCompactAllWithDanglingLMB(t *testing.T) { 4443 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4444 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 4445 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4446 require_NoError(t, err) 4447 defer fs.Stop() 4448 4449 subj, msg := "foo", []byte("ZZ") 4450 for i := 0; i < 100; i++ { 4451 _, _, err := fs.StoreMsg(subj, nil, msg) 4452 require_NoError(t, err) 4453 } 4454 4455 fs.RemoveMsg(100) 4456 purged, err := fs.Compact(100) 4457 require_NoError(t, err) 4458 require_True(t, purged == 99) 4459 4460 _, _, err = fs.StoreMsg(subj, nil, msg) 4461 require_NoError(t, err) 4462 }) 4463 } 4464 4465 func TestFileStoreStateWithBlkFirstDeleted(t *testing.T) { 4466 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4467 fcfg.BlockSize = 4096 4468 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 4469 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4470 require_NoError(t, err) 4471 defer fs.Stop() 4472 4473 subj, msg := "foo", []byte("Hello World") 4474 toStore := 500 4475 for i := 0; i < toStore; i++ { 4476 _, _, err := fs.StoreMsg(subj, nil, msg) 4477 require_NoError(t, err) 4478 } 4479 4480 // Delete some messages from the beginning of an interior block. 4481 fs.mu.RLock() 4482 require_True(t, len(fs.blks) > 2) 4483 fseq := fs.blks[1].first.seq 4484 fs.mu.RUnlock() 4485 4486 // Now start from first seq of second blk and delete 10 msgs 4487 for seq := fseq; seq < fseq+10; seq++ { 4488 removed, err := fs.RemoveMsg(seq) 4489 require_NoError(t, err) 4490 require_True(t, removed) 4491 } 4492 4493 // This bug was in normal detailed state. But check fast state too. 4494 var fstate StreamState 4495 fs.FastState(&fstate) 4496 require_True(t, fstate.NumDeleted == 10) 4497 state := fs.State() 4498 require_True(t, state.NumDeleted == 10) 4499 }) 4500 } 4501 4502 func TestFileStoreMsgBlkFailOnKernelFaultLostDataReporting(t *testing.T) { 4503 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4504 fcfg.BlockSize = 4096 4505 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 4506 created := time.Now() 4507 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4508 require_NoError(t, err) 4509 defer fs.Stop() 4510 4511 subj, msg := "foo", []byte("Hello World") 4512 toStore := 500 4513 for i := 0; i < toStore; i++ { 4514 _, _, err := fs.StoreMsg(subj, nil, msg) 4515 require_NoError(t, err) 4516 } 4517 4518 // We want to make sure all of the scenarios report lost data properly. 4519 // Will run 3 scenarios, 1st block, last block, interior block. 4520 // The new system does not detect byzantine behavior by default on creating the store. 4521 // A LoadMsg() of checkMsgs() call will be needed now. 4522 4523 // First block 4524 fs.mu.RLock() 4525 require_True(t, len(fs.blks) > 0) 4526 mfn := fs.blks[0].mfn 4527 fs.mu.RUnlock() 4528 4529 fs.Stop() 4530 4531 require_NoError(t, os.Remove(mfn)) 4532 4533 // Restart. 4534 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4535 require_NoError(t, err) 4536 defer fs.Stop() 4537 4538 _, err = fs.LoadMsg(1, nil) 4539 require_Error(t, err, errNoBlkData) 4540 4541 // Load will rebuild fs itself async.. 4542 checkFor(t, time.Second, 50*time.Millisecond, func() error { 4543 if state := fs.State(); state.Lost != nil { 4544 return nil 4545 } 4546 return errors.New("no ld yet") 4547 }) 4548 4549 state := fs.State() 4550 require_True(t, state.FirstSeq == 94) 4551 require_True(t, state.Lost != nil) 4552 require_True(t, len(state.Lost.Msgs) == 93) 4553 4554 // Last block 4555 fs.mu.RLock() 4556 require_True(t, len(fs.blks) > 0) 4557 require_True(t, fs.lmb != nil) 4558 mfn = fs.lmb.mfn 4559 fs.mu.RUnlock() 4560 4561 fs.Stop() 4562 4563 require_NoError(t, os.Remove(mfn)) 4564 4565 // Restart. 4566 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4567 require_NoError(t, err) 4568 defer fs.Stop() 4569 4570 state = fs.State() 4571 require_True(t, state.FirstSeq == 94) 4572 require_True(t, state.LastSeq == 500) // Make sure we do not lose last seq. 4573 require_True(t, state.NumDeleted == 35) // These are interiors 4574 require_True(t, state.Lost != nil) 4575 require_True(t, len(state.Lost.Msgs) == 35) 4576 4577 // Interior block. 4578 fs.mu.RLock() 4579 require_True(t, len(fs.blks) > 3) 4580 mfn = fs.blks[len(fs.blks)-3].mfn 4581 fs.mu.RUnlock() 4582 4583 fs.Stop() 4584 4585 require_NoError(t, os.Remove(mfn)) 4586 4587 // Restart. 4588 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 4589 require_NoError(t, err) 4590 defer fs.Stop() 4591 4592 // Need checkMsgs to catch interior one. 4593 require_True(t, fs.checkMsgs() != nil) 4594 4595 state = fs.State() 4596 require_True(t, state.FirstSeq == 94) 4597 require_True(t, state.LastSeq == 500) // Make sure we do not lose last seq. 4598 require_True(t, state.NumDeleted == 128) 4599 require_True(t, state.Lost != nil) 4600 require_True(t, len(state.Lost.Msgs) == 93) 4601 }) 4602 } 4603 4604 func TestFileStoreAllFilteredStateWithDeleted(t *testing.T) { 4605 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4606 fcfg.BlockSize = 1024 4607 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 4608 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4609 require_NoError(t, err) 4610 defer fs.Stop() 4611 4612 subj, msg := "foo", []byte("Hello World") 4613 for i := 0; i < 100; i++ { 4614 _, _, err := fs.StoreMsg(subj, nil, msg) 4615 require_NoError(t, err) 4616 } 4617 4618 remove := func(seqs ...uint64) { 4619 for _, seq := range seqs { 4620 ok, err := fs.RemoveMsg(seq) 4621 require_NoError(t, err) 4622 require_True(t, ok) 4623 } 4624 } 4625 4626 checkFilteredState := func(start, msgs, first, last int) { 4627 fss := fs.FilteredState(uint64(start), _EMPTY_) 4628 if fss.Msgs != uint64(msgs) { 4629 t.Fatalf("Expected %d msgs, got %d", msgs, fss.Msgs) 4630 } 4631 if fss.First != uint64(first) { 4632 t.Fatalf("Expected %d to be first, got %d", first, fss.First) 4633 } 4634 if fss.Last != uint64(last) { 4635 t.Fatalf("Expected %d to be last, got %d", last, fss.Last) 4636 } 4637 } 4638 4639 checkFilteredState(1, 100, 1, 100) 4640 remove(2) 4641 checkFilteredState(2, 98, 3, 100) 4642 remove(3, 4, 5) 4643 checkFilteredState(2, 95, 6, 100) 4644 checkFilteredState(6, 95, 6, 100) 4645 remove(8, 10, 12, 14, 16, 18) 4646 checkFilteredState(7, 88, 7, 100) 4647 4648 // Now check when purged that we return first and last sequences properly. 4649 fs.Purge() 4650 checkFilteredState(0, 0, 101, 100) 4651 }) 4652 } 4653 4654 func TestFileStoreStreamTruncateResetMultiBlock(t *testing.T) { 4655 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4656 fcfg.BlockSize = 128 4657 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage} 4658 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4659 require_NoError(t, err) 4660 defer fs.Stop() 4661 4662 subj, msg := "foo", []byte("Hello World") 4663 for i := 0; i < 1000; i++ { 4664 _, _, err := fs.StoreMsg(subj, nil, msg) 4665 require_NoError(t, err) 4666 } 4667 fs.syncBlocks() 4668 require_True(t, fs.numMsgBlocks() == 500) 4669 4670 // Reset everything 4671 require_NoError(t, fs.Truncate(0)) 4672 require_True(t, fs.numMsgBlocks() == 0) 4673 4674 state := fs.State() 4675 require_Equal(t, state.Msgs, 0) 4676 require_Equal(t, state.Bytes, 0) 4677 require_Equal(t, state.FirstSeq, 0) 4678 require_Equal(t, state.LastSeq, 0) 4679 require_Equal(t, state.NumSubjects, 0) 4680 require_Equal(t, state.NumDeleted, 0) 4681 4682 for i := 0; i < 1000; i++ { 4683 _, _, err := fs.StoreMsg(subj, nil, msg) 4684 require_NoError(t, err) 4685 } 4686 fs.syncBlocks() 4687 4688 state = fs.State() 4689 require_Equal(t, state.Msgs, 1000) 4690 require_Equal(t, state.Bytes, 44000) 4691 require_Equal(t, state.FirstSeq, 1) 4692 require_Equal(t, state.LastSeq, 1000) 4693 require_Equal(t, state.NumSubjects, 1) 4694 require_Equal(t, state.NumDeleted, 0) 4695 }) 4696 } 4697 4698 func TestFileStoreStreamCompactMultiBlockSubjectInfo(t *testing.T) { 4699 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4700 fcfg.BlockSize = 128 4701 cfg := StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage} 4702 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4703 require_NoError(t, err) 4704 defer fs.Stop() 4705 4706 for i := 0; i < 1000; i++ { 4707 subj := fmt.Sprintf("foo.%d", i) 4708 _, _, err := fs.StoreMsg(subj, nil, []byte("Hello World")) 4709 require_NoError(t, err) 4710 } 4711 require_True(t, fs.numMsgBlocks() == 500) 4712 4713 // Compact such that we know we throw blocks away from the beginning. 4714 deleted, err := fs.Compact(501) 4715 require_NoError(t, err) 4716 require_True(t, deleted == 500) 4717 require_True(t, fs.numMsgBlocks() == 250) 4718 4719 // Make sure we adjusted for subjects etc. 4720 state := fs.State() 4721 require_True(t, state.NumSubjects == 500) 4722 }) 4723 } 4724 4725 func TestFileStoreSubjectsTotals(t *testing.T) { 4726 // No need for all permutations here. 4727 storeDir := t.TempDir() 4728 fcfg := FileStoreConfig{StoreDir: storeDir} 4729 fs, err := newFileStore(fcfg, StreamConfig{Name: "zzz", Subjects: []string{"*.*"}, Storage: FileStorage}) 4730 require_NoError(t, err) 4731 defer fs.Stop() 4732 4733 fmap := make(map[int]int) 4734 bmap := make(map[int]int) 4735 4736 var m map[int]int 4737 var ft string 4738 4739 for i := 0; i < 10_000; i++ { 4740 // Flip coin for prefix 4741 if rand.Intn(2) == 0 { 4742 ft, m = "foo", fmap 4743 } else { 4744 ft, m = "bar", bmap 4745 } 4746 dt := rand.Intn(100) 4747 subj := fmt.Sprintf("%s.%d", ft, dt) 4748 m[dt]++ 4749 4750 _, _, err := fs.StoreMsg(subj, nil, []byte("Hello World")) 4751 require_NoError(t, err) 4752 } 4753 4754 // Now test SubjectsTotal 4755 for dt, total := range fmap { 4756 subj := fmt.Sprintf("foo.%d", dt) 4757 m := fs.SubjectsTotals(subj) 4758 if m[subj] != uint64(total) { 4759 t.Fatalf("Expected %q to have %d total, got %d", subj, total, m[subj]) 4760 } 4761 } 4762 4763 // Check fmap. 4764 if st := fs.SubjectsTotals("foo.*"); len(st) != len(fmap) { 4765 t.Fatalf("Expected %d subjects for %q, got %d", len(fmap), "foo.*", len(st)) 4766 } else { 4767 expected := 0 4768 for _, n := range fmap { 4769 expected += n 4770 } 4771 received := uint64(0) 4772 for _, n := range st { 4773 received += n 4774 } 4775 if received != uint64(expected) { 4776 t.Fatalf("Expected %d total but got %d", expected, received) 4777 } 4778 } 4779 4780 // Check bmap. 4781 if st := fs.SubjectsTotals("bar.*"); len(st) != len(bmap) { 4782 t.Fatalf("Expected %d subjects for %q, got %d", len(bmap), "bar.*", len(st)) 4783 } else { 4784 expected := 0 4785 for _, n := range bmap { 4786 expected += n 4787 } 4788 received := uint64(0) 4789 for _, n := range st { 4790 received += n 4791 } 4792 if received != uint64(expected) { 4793 t.Fatalf("Expected %d total but got %d", expected, received) 4794 } 4795 } 4796 4797 // All with pwc match. 4798 if st, expected := fs.SubjectsTotals("*.*"), len(bmap)+len(fmap); len(st) != expected { 4799 t.Fatalf("Expected %d subjects for %q, got %d", expected, "*.*", len(st)) 4800 } 4801 } 4802 4803 func TestFileStoreConsumerStoreEncodeAfterRestart(t *testing.T) { 4804 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4805 fs, err := newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 4806 require_NoError(t, err) 4807 defer fs.Stop() 4808 4809 o, err := fs.ConsumerStore("o22", &ConsumerConfig{AckPolicy: AckExplicit}) 4810 require_NoError(t, err) 4811 4812 state := &ConsumerState{} 4813 state.Delivered.Consumer = 22 4814 state.Delivered.Stream = 22 4815 state.AckFloor.Consumer = 11 4816 state.AckFloor.Stream = 11 4817 err = o.Update(state) 4818 require_NoError(t, err) 4819 4820 fs.Stop() 4821 4822 fs, err = newFileStoreWithCreated(fcfg, StreamConfig{Name: "zzz", Storage: FileStorage}, time.Now(), prf(&fcfg), nil) 4823 require_NoError(t, err) 4824 defer fs.Stop() 4825 4826 o, err = fs.ConsumerStore("o22", &ConsumerConfig{AckPolicy: AckExplicit}) 4827 require_NoError(t, err) 4828 4829 if o.(*consumerFileStore).state.Delivered != state.Delivered { 4830 t.Fatalf("Consumer state is wrong %+v vs %+v", o.(*consumerFileStore).state, state) 4831 } 4832 if o.(*consumerFileStore).state.AckFloor != state.AckFloor { 4833 t.Fatalf("Consumer state is wrong %+v vs %+v", o.(*consumerFileStore).state, state) 4834 } 4835 }) 4836 } 4837 4838 func TestFileStoreNumPendingLargeNumBlks(t *testing.T) { 4839 // No need for all permutations here. 4840 storeDir := t.TempDir() 4841 fcfg := FileStoreConfig{ 4842 StoreDir: storeDir, 4843 BlockSize: 128, // Small on purpose to create alot of blks. 4844 } 4845 fs, err := newFileStore(fcfg, StreamConfig{Name: "zzz", Subjects: []string{"zzz"}, Storage: FileStorage}) 4846 require_NoError(t, err) 4847 defer fs.Stop() 4848 4849 subj, msg := "zzz", bytes.Repeat([]byte("X"), 100) 4850 numMsgs := 10_000 4851 4852 for i := 0; i < numMsgs; i++ { 4853 fs.StoreMsg(subj, nil, msg) 4854 } 4855 4856 start := time.Now() 4857 total, _ := fs.NumPending(4000, "zzz", false) 4858 require_LessThan(t, time.Since(start), 15*time.Millisecond) 4859 require_Equal(t, total, 6001) 4860 4861 start = time.Now() 4862 total, _ = fs.NumPending(6000, "zzz", false) 4863 require_LessThan(t, time.Since(start), 25*time.Millisecond) 4864 require_Equal(t, total, 4001) 4865 4866 // Now delete a message in first half and second half. 4867 fs.RemoveMsg(1000) 4868 fs.RemoveMsg(9000) 4869 4870 start = time.Now() 4871 total, _ = fs.NumPending(4000, "zzz", false) 4872 require_LessThan(t, time.Since(start), 50*time.Millisecond) 4873 require_Equal(t, total, 6000) 4874 4875 start = time.Now() 4876 total, _ = fs.NumPending(6000, "zzz", false) 4877 require_LessThan(t, time.Since(start), 50*time.Millisecond) 4878 require_Equal(t, total, 4000) 4879 } 4880 4881 func TestFileStoreSkipMsgAndNumBlocks(t *testing.T) { 4882 // No need for all permutations here. 4883 storeDir := t.TempDir() 4884 fcfg := FileStoreConfig{ 4885 StoreDir: storeDir, 4886 BlockSize: 128, // Small on purpose to create alot of blks. 4887 } 4888 fs, err := newFileStore(fcfg, StreamConfig{Name: "zzz", Subjects: []string{"zzz"}, Storage: FileStorage}) 4889 require_NoError(t, err) 4890 defer fs.Stop() 4891 4892 subj, msg := "zzz", bytes.Repeat([]byte("X"), 100) 4893 numMsgs := 10_000 4894 4895 fs.StoreMsg(subj, nil, msg) 4896 for i := 0; i < numMsgs; i++ { 4897 fs.SkipMsg() 4898 } 4899 fs.StoreMsg(subj, nil, msg) 4900 require_True(t, fs.numMsgBlocks() == 2) 4901 } 4902 4903 func TestFileStoreRestoreEncryptedWithNoKeyFuncFails(t *testing.T) { 4904 // No need for all permutations here. 4905 fcfg := FileStoreConfig{StoreDir: t.TempDir(), Cipher: AES} 4906 cfg := StreamConfig{Name: "zzz", Subjects: []string{"zzz"}, Storage: FileStorage} 4907 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4908 require_NoError(t, err) 4909 defer fs.Stop() 4910 4911 subj, msg := "zzz", bytes.Repeat([]byte("X"), 100) 4912 numMsgs := 100 4913 for i := 0; i < numMsgs; i++ { 4914 fs.StoreMsg(subj, nil, msg) 4915 } 4916 4917 fs.Stop() 4918 4919 // Make sure if we try to restore with no prf (key) that it fails. 4920 _, err = newFileStoreWithCreated(fcfg, cfg, time.Now(), nil, nil) 4921 require_Error(t, err, errNoMainKey) 4922 } 4923 4924 func TestFileStoreInitialFirstSeq(t *testing.T) { 4925 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 4926 cfg := StreamConfig{Name: "zzz", Storage: FileStorage, FirstSeq: 1000} 4927 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 4928 require_NoError(t, err) 4929 defer fs.Stop() 4930 4931 seq, _, err := fs.StoreMsg("A", nil, []byte("OK")) 4932 require_NoError(t, err) 4933 if seq != 1000 { 4934 t.Fatalf("Message should have been sequence 1000 but was %d", seq) 4935 } 4936 4937 seq, _, err = fs.StoreMsg("B", nil, []byte("OK")) 4938 require_NoError(t, err) 4939 if seq != 1001 { 4940 t.Fatalf("Message should have been sequence 1001 but was %d", seq) 4941 } 4942 4943 var state StreamState 4944 fs.FastState(&state) 4945 switch { 4946 case state.Msgs != 2: 4947 t.Fatalf("Expected 2 messages, got %d", state.Msgs) 4948 case state.FirstSeq != 1000: 4949 t.Fatalf("Expected first seq 1000, got %d", state.FirstSeq) 4950 case state.LastSeq != 1001: 4951 t.Fatalf("Expected last seq 1001, got %d", state.LastSeq) 4952 } 4953 }) 4954 } 4955 4956 func TestFileStoreRecaluclateFirstForSubjBug(t *testing.T) { 4957 fs, err := newFileStore(FileStoreConfig{StoreDir: t.TempDir()}, StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 4958 require_NoError(t, err) 4959 defer fs.Stop() 4960 4961 fs.StoreMsg("foo", nil, nil) // 1 4962 fs.StoreMsg("bar", nil, nil) // 2 4963 fs.StoreMsg("foo", nil, nil) // 3 4964 4965 // Now remove first 2.. 4966 fs.RemoveMsg(1) 4967 fs.RemoveMsg(2) 4968 4969 // Now grab first (and only) block. 4970 fs.mu.RLock() 4971 mb := fs.blks[0] 4972 fs.mu.RUnlock() 4973 4974 // Since we lazy update the first, simulate that we have not updated it as of yet. 4975 ss := &SimpleState{Msgs: 1, First: 1, Last: 3, firstNeedsUpdate: true} 4976 4977 mb.mu.Lock() 4978 defer mb.mu.Unlock() 4979 4980 // Flush the cache. 4981 mb.clearCacheAndOffset() 4982 // Now call with start sequence of 1, the old one 4983 // This will panic without the fix. 4984 mb.recalculateFirstForSubj("foo", 1, ss) 4985 // Make sure it was update properly. 4986 require_True(t, *ss == SimpleState{Msgs: 1, First: 3, Last: 3, firstNeedsUpdate: false}) 4987 } 4988 4989 func TestFileStoreKeepWithDeletedMsgsBug(t *testing.T) { 4990 fs, err := newFileStore(FileStoreConfig{StoreDir: t.TempDir()}, StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 4991 require_NoError(t, err) 4992 defer fs.Stop() 4993 4994 msg := bytes.Repeat([]byte("A"), 19) 4995 for i := 0; i < 5; i++ { 4996 fs.StoreMsg("A", nil, msg) 4997 fs.StoreMsg("B", nil, msg) 4998 } 4999 5000 n, err := fs.PurgeEx("A", 0, 0) 5001 require_NoError(t, err) 5002 require_True(t, n == 5) 5003 5004 // Purge with keep. 5005 n, err = fs.PurgeEx(_EMPTY_, 0, 2) 5006 require_NoError(t, err) 5007 require_True(t, n == 3) 5008 } 5009 5010 func TestFileStoreRestartWithExpireAndLockingBug(t *testing.T) { 5011 sd := t.TempDir() 5012 scfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 5013 fs, err := newFileStore(FileStoreConfig{StoreDir: sd}, scfg) 5014 require_NoError(t, err) 5015 defer fs.Stop() 5016 5017 // 20 total 5018 msg := []byte("HELLO WORLD") 5019 for i := 0; i < 10; i++ { 5020 fs.StoreMsg("A", nil, msg) 5021 fs.StoreMsg("B", nil, msg) 5022 } 5023 fs.Stop() 5024 5025 // Now change config underneath of so we will do expires at startup. 5026 scfg.MaxMsgs = 15 5027 scfg.MaxMsgsPer = 2 5028 newCfg := FileStreamInfo{Created: fs.cfg.Created, StreamConfig: scfg} 5029 5030 // Replace 5031 fs.cfg = newCfg 5032 require_NoError(t, fs.writeStreamMeta()) 5033 5034 fs, err = newFileStore(FileStoreConfig{StoreDir: sd}, scfg) 5035 require_NoError(t, err) 5036 defer fs.Stop() 5037 } 5038 5039 // Test that loads from lmb under lots of writes do not return errPartialCache. 5040 func TestFileStoreErrPartialLoad(t *testing.T) { 5041 fs, err := newFileStore(FileStoreConfig{StoreDir: t.TempDir()}, StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 5042 require_NoError(t, err) 5043 defer fs.Stop() 5044 5045 put := func(num int) { 5046 for i := 0; i < num; i++ { 5047 fs.StoreMsg("Z", nil, []byte("ZZZZZZZZZZZZZ")) 5048 } 5049 } 5050 5051 put(100) 5052 5053 // Dump cache of lmb. 5054 clearCache := func() { 5055 fs.mu.RLock() 5056 lmb := fs.lmb 5057 fs.mu.RUnlock() 5058 lmb.mu.Lock() 5059 lmb.clearCache() 5060 lmb.mu.Unlock() 5061 } 5062 clearCache() 5063 5064 qch := make(chan struct{}) 5065 defer close(qch) 5066 5067 for i := 0; i < 10; i++ { 5068 go func() { 5069 for { 5070 select { 5071 case <-qch: 5072 return 5073 default: 5074 put(5) 5075 } 5076 } 5077 }() 5078 } 5079 5080 time.Sleep(100 * time.Millisecond) 5081 5082 var smv StoreMsg 5083 for i := 0; i < 10_000; i++ { 5084 fs.mu.RLock() 5085 lmb := fs.lmb 5086 fs.mu.RUnlock() 5087 lmb.mu.Lock() 5088 first, last := fs.lmb.first.seq, fs.lmb.last.seq 5089 if i%100 == 0 { 5090 lmb.clearCache() 5091 } 5092 lmb.mu.Unlock() 5093 5094 if spread := int(last - first); spread > 0 { 5095 seq := first + uint64(rand.Intn(spread)) 5096 _, err = fs.LoadMsg(seq, &smv) 5097 require_NoError(t, err) 5098 } 5099 } 5100 } 5101 5102 func TestFileStoreErrPartialLoadOnSyncClose(t *testing.T) { 5103 fs, err := newFileStore( 5104 FileStoreConfig{StoreDir: t.TempDir(), BlockSize: 500}, 5105 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}, 5106 ) 5107 require_NoError(t, err) 5108 defer fs.Stop() 5109 5110 // This yields an internal record length of 50 bytes. So 10 msgs per blk. 5111 msgLen := 19 5112 msg := bytes.Repeat([]byte("A"), msgLen) 5113 5114 // Load up half the block. 5115 for _, subj := range []string{"A", "B", "C", "D", "E"} { 5116 fs.StoreMsg(subj, nil, msg) 5117 } 5118 5119 // Now simulate the sync timer closing the last block. 5120 fs.mu.RLock() 5121 lmb := fs.lmb 5122 fs.mu.RUnlock() 5123 require_True(t, lmb != nil) 5124 5125 lmb.mu.Lock() 5126 lmb.expireCacheLocked() 5127 lmb.dirtyCloseWithRemove(false) 5128 lmb.mu.Unlock() 5129 5130 fs.StoreMsg("Z", nil, msg) 5131 _, err = fs.LoadMsg(1, nil) 5132 require_NoError(t, err) 5133 } 5134 5135 func TestFileStoreSyncIntervals(t *testing.T) { 5136 fcfg := FileStoreConfig{StoreDir: t.TempDir(), SyncInterval: 250 * time.Millisecond} 5137 fs, err := newFileStore(fcfg, StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 5138 require_NoError(t, err) 5139 defer fs.Stop() 5140 5141 checkSyncFlag := func(expected bool) { 5142 fs.mu.RLock() 5143 lmb := fs.lmb 5144 fs.mu.RUnlock() 5145 lmb.mu.RLock() 5146 syncNeeded := lmb.needSync 5147 lmb.mu.RUnlock() 5148 if syncNeeded != expected { 5149 t.Fatalf("Expected needSync to be %v", expected) 5150 } 5151 } 5152 5153 checkSyncFlag(false) 5154 fs.StoreMsg("Z", nil, []byte("hello")) 5155 checkSyncFlag(true) 5156 time.Sleep(400 * time.Millisecond) 5157 checkSyncFlag(false) 5158 fs.Stop() 5159 5160 // Now check always 5161 fcfg.SyncInterval = 10 * time.Second 5162 fcfg.SyncAlways = true 5163 fs, err = newFileStore(fcfg, StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 5164 require_NoError(t, err) 5165 defer fs.Stop() 5166 5167 checkSyncFlag(false) 5168 fs.StoreMsg("Z", nil, []byte("hello")) 5169 checkSyncFlag(false) 5170 } 5171 5172 // https://github.com/nats-io/nats-server/issues/4529 5173 // Run this wuth --race and you will see the unlocked access that probably caused this. 5174 func TestFileStoreRecalcFirstSequenceBug(t *testing.T) { 5175 fcfg := FileStoreConfig{StoreDir: t.TempDir()} 5176 fs, err := newFileStore(fcfg, StreamConfig{Name: "zzz", Subjects: []string{"*"}, MaxMsgsPer: 2, Storage: FileStorage}) 5177 require_NoError(t, err) 5178 defer fs.Stop() 5179 5180 msg := bytes.Repeat([]byte("A"), 22) 5181 5182 for _, subj := range []string{"A", "A", "B", "B"} { 5183 fs.StoreMsg(subj, nil, msg) 5184 } 5185 // Make sure the buffer is cleared. 5186 clearLMBCache := func() { 5187 fs.mu.RLock() 5188 mb := fs.lmb 5189 fs.mu.RUnlock() 5190 mb.mu.Lock() 5191 mb.clearCacheAndOffset() 5192 mb.mu.Unlock() 5193 } 5194 5195 clearLMBCache() 5196 5197 // Do first here. 5198 fs.StoreMsg("A", nil, msg) 5199 5200 var wg sync.WaitGroup 5201 start := make(chan bool) 5202 5203 wg.Add(1) 5204 go func() { 5205 defer wg.Done() 5206 <-start 5207 for i := 0; i < 1_000; i++ { 5208 fs.LoadLastMsg("A", nil) 5209 clearLMBCache() 5210 } 5211 }() 5212 5213 wg.Add(1) 5214 go func() { 5215 defer wg.Done() 5216 <-start 5217 for i := 0; i < 1_000; i++ { 5218 fs.StoreMsg("A", nil, msg) 5219 } 5220 }() 5221 5222 close(start) 5223 wg.Wait() 5224 } 5225 5226 /////////////////////////////////////////////////////////////////////////// 5227 // New WAL based architecture tests 5228 /////////////////////////////////////////////////////////////////////////// 5229 5230 func TestFileStoreFullStateBasics(t *testing.T) { 5231 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 5232 fcfg.BlockSize = 100 5233 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 5234 created := time.Now() 5235 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5236 require_NoError(t, err) 5237 defer fs.Stop() 5238 5239 // This yields an internal record length of 50 bytes. So 2 msgs per blk. 5240 subj, msgLen, recLen := "A", 19, uint64(50) 5241 msgA := bytes.Repeat([]byte("A"), msgLen) 5242 msgZ := bytes.Repeat([]byte("Z"), msgLen) 5243 5244 // Send 2 msgs and stop, check for presence of our full state file. 5245 fs.StoreMsg(subj, nil, msgA) 5246 fs.StoreMsg(subj, nil, msgZ) 5247 require_True(t, fs.numMsgBlocks() == 1) 5248 5249 // Make sure there is a full state file after we do a stop. 5250 fs.Stop() 5251 5252 sfile := filepath.Join(fcfg.StoreDir, msgDir, streamStreamStateFile) 5253 if _, err := os.Stat(sfile); err != nil { 5254 t.Fatalf("Expected stream state file but got %v", err) 5255 } 5256 5257 // Read it in and make sure len > 0. 5258 buf, err := os.ReadFile(sfile) 5259 require_NoError(t, err) 5260 require_True(t, len(buf) > 0) 5261 5262 // Now make sure we recover properly. 5263 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5264 require_NoError(t, err) 5265 defer fs.Stop() 5266 5267 // Make sure there are no old idx or fss files. 5268 matches, err := filepath.Glob(filepath.Join(fcfg.StoreDir, msgDir, "%d.fss")) 5269 require_NoError(t, err) 5270 require_True(t, len(matches) == 0) 5271 matches, err = filepath.Glob(filepath.Join(fcfg.StoreDir, msgDir, "%d.idx")) 5272 require_NoError(t, err) 5273 require_True(t, len(matches) == 0) 5274 5275 state := fs.State() 5276 require_Equal(t, state.Msgs, 2) 5277 require_Equal(t, state.FirstSeq, 1) 5278 require_Equal(t, state.LastSeq, 2) 5279 5280 // Now make sure we can read in values. 5281 var smv StoreMsg 5282 sm, err := fs.LoadMsg(1, &smv) 5283 require_NoError(t, err) 5284 require_True(t, bytes.Equal(sm.msg, msgA)) 5285 5286 sm, err = fs.LoadMsg(2, &smv) 5287 require_NoError(t, err) 5288 require_True(t, bytes.Equal(sm.msg, msgZ)) 5289 5290 // Now add in 1 more here to split the lmb. 5291 fs.StoreMsg(subj, nil, msgZ) 5292 5293 // Now stop the filestore and replace the old stream state and make sure we recover correctly. 5294 fs.Stop() 5295 5296 // Regrab the stream state 5297 buf, err = os.ReadFile(sfile) 5298 require_NoError(t, err) 5299 5300 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5301 require_NoError(t, err) 5302 defer fs.Stop() 5303 5304 // Add in one more. 5305 fs.StoreMsg(subj, nil, msgZ) 5306 fs.Stop() 5307 5308 // Put old stream state back with only 3. 5309 err = os.WriteFile(sfile, buf, defaultFilePerms) 5310 require_NoError(t, err) 5311 5312 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5313 require_NoError(t, err) 5314 defer fs.Stop() 5315 5316 state = fs.State() 5317 require_Equal(t, state.Msgs, 4) 5318 require_Equal(t, state.Bytes, 4*recLen) 5319 require_Equal(t, state.FirstSeq, 1) 5320 require_Equal(t, state.LastSeq, 4) 5321 require_Equal(t, fs.numMsgBlocks(), 2) 5322 5323 // Make sure we are tracking subjects correctly. 5324 fs.mu.RLock() 5325 info, _ := fs.psim.Find(stringToBytes(subj)) 5326 psi := *info 5327 fs.mu.RUnlock() 5328 5329 require_Equal(t, psi.total, 4) 5330 require_Equal(t, psi.fblk, 1) 5331 require_Equal(t, psi.lblk, 2) 5332 5333 // Store 1 more 5334 fs.StoreMsg(subj, nil, msgA) 5335 fs.Stop() 5336 // Put old stream state back with only 3. 5337 err = os.WriteFile(sfile, buf, defaultFilePerms) 5338 require_NoError(t, err) 5339 5340 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5341 require_NoError(t, err) 5342 defer fs.Stop() 5343 5344 state = fs.State() 5345 require_Equal(t, state.Msgs, 5) 5346 require_Equal(t, state.FirstSeq, 1) 5347 require_Equal(t, state.LastSeq, 5) 5348 require_Equal(t, fs.numMsgBlocks(), 3) 5349 // Make sure we are tracking subjects correctly. 5350 fs.mu.RLock() 5351 info, _ = fs.psim.Find(stringToBytes(subj)) 5352 psi = *info 5353 fs.mu.RUnlock() 5354 require_Equal(t, psi.total, 5) 5355 require_Equal(t, psi.fblk, 1) 5356 require_Equal(t, psi.lblk, 3) 5357 }) 5358 } 5359 5360 func TestFileStoreFullStatePurge(t *testing.T) { 5361 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 5362 fcfg.BlockSize = 132 // Leave room for tombstones. 5363 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 5364 created := time.Now() 5365 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5366 require_NoError(t, err) 5367 defer fs.Stop() 5368 5369 // This yields an internal record length of 50 bytes. So 2 msgs per blk. 5370 subj, msg := "A", bytes.Repeat([]byte("A"), 19) 5371 5372 // Should be 2 per block, so 5 blocks. 5373 for i := 0; i < 10; i++ { 5374 fs.StoreMsg(subj, nil, msg) 5375 } 5376 n, err := fs.Purge() 5377 require_NoError(t, err) 5378 require_Equal(t, n, 10) 5379 state := fs.State() 5380 fs.Stop() 5381 5382 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5383 require_NoError(t, err) 5384 defer fs.Stop() 5385 5386 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5387 t.Fatalf("Restore state after purge does not match:\n%+v\n%+v", 5388 state, newState) 5389 } 5390 5391 // Add in more 10 more total, some B some C. 5392 for i := 0; i < 5; i++ { 5393 fs.StoreMsg("B", nil, msg) 5394 fs.StoreMsg("C", nil, msg) 5395 } 5396 5397 n, err = fs.PurgeEx("B", 0, 0) 5398 require_NoError(t, err) 5399 require_Equal(t, n, 5) 5400 5401 state = fs.State() 5402 fs.Stop() 5403 5404 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5405 require_NoError(t, err) 5406 defer fs.Stop() 5407 5408 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5409 t.Fatalf("Restore state after purge does not match:\n%+v\n%+v", 5410 state, newState) 5411 } 5412 5413 // Purge with keep. 5414 n, err = fs.PurgeEx(_EMPTY_, 0, 2) 5415 require_NoError(t, err) 5416 require_Equal(t, n, 3) 5417 5418 state = fs.State() 5419 5420 // Do some quick checks here, keep had a bug. 5421 require_Equal(t, state.Msgs, 2) 5422 require_Equal(t, state.FirstSeq, 18) 5423 require_Equal(t, state.LastSeq, 20) 5424 5425 fs.Stop() 5426 5427 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5428 require_NoError(t, err) 5429 defer fs.Stop() 5430 5431 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5432 t.Fatalf("Restore state after purge does not match:\n%+v\n%+v", 5433 state, newState) 5434 } 5435 5436 // Make sure we can survive a purge with no full stream state and have the correct first sequence. 5437 // This used to be provided by the idx file and is now tombstones and the full stream state snapshot. 5438 n, err = fs.Purge() 5439 require_NoError(t, err) 5440 require_Equal(t, n, 2) 5441 state = fs.State() 5442 fs.Stop() 5443 5444 sfile := filepath.Join(fcfg.StoreDir, msgDir, streamStreamStateFile) 5445 os.Remove(sfile) 5446 5447 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5448 require_NoError(t, err) 5449 defer fs.Stop() 5450 5451 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5452 t.Fatalf("Restore state after purge does not match:\n%+v\n%+v", 5453 state, newState) 5454 } 5455 }) 5456 } 5457 5458 func TestFileStoreFullStateTestUserRemoveWAL(t *testing.T) { 5459 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 5460 fcfg.BlockSize = 132 // Leave room for tombstones. 5461 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 5462 created := time.Now() 5463 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5464 require_NoError(t, err) 5465 defer fs.Stop() 5466 5467 // This yields an internal record length of 50 bytes. So 2 msgs per blk. 5468 msgLen := 19 5469 msgA := bytes.Repeat([]byte("A"), msgLen) 5470 msgZ := bytes.Repeat([]byte("Z"), msgLen) 5471 5472 // Store 2 msgs and delete first. 5473 fs.StoreMsg("A", nil, msgA) 5474 fs.StoreMsg("Z", nil, msgZ) 5475 fs.RemoveMsg(1) 5476 5477 // Check we can load things properly since the block will have a tombstone now for seq 1. 5478 sm, err := fs.LoadMsg(2, nil) 5479 require_NoError(t, err) 5480 require_True(t, bytes.Equal(sm.msg, msgZ)) 5481 5482 require_Equal(t, fs.numMsgBlocks(), 1) 5483 state := fs.State() 5484 fs.Stop() 5485 5486 // Grab the state from this stop. 5487 sfile := filepath.Join(fcfg.StoreDir, msgDir, streamStreamStateFile) 5488 buf, err := os.ReadFile(sfile) 5489 require_NoError(t, err) 5490 5491 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5492 require_NoError(t, err) 5493 defer fs.Stop() 5494 5495 // Check we can load things properly since the block will have a tombstone now for seq 1. 5496 _, err = fs.LoadMsg(2, nil) 5497 require_NoError(t, err) 5498 _, err = fs.LoadMsg(1, nil) 5499 require_Error(t, err, ErrStoreMsgNotFound) 5500 5501 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5502 t.Fatalf("Restore state does not match:\n%+v\n%+v", 5503 state, newState) 5504 } 5505 require_True(t, !state.FirstTime.IsZero()) 5506 5507 // Store 2 more msgs and delete 2 & 4. 5508 fs.StoreMsg("A", nil, msgA) 5509 fs.StoreMsg("Z", nil, msgZ) 5510 fs.RemoveMsg(2) 5511 fs.RemoveMsg(4) 5512 5513 state = fs.State() 5514 require_Equal(t, len(state.Deleted), state.NumDeleted) 5515 fs.Stop() 5516 5517 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5518 require_NoError(t, err) 5519 defer fs.Stop() 5520 5521 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5522 t.Fatalf("Restore state does not match:\n%+v\n%+v", 5523 state, newState) 5524 } 5525 require_True(t, !state.FirstTime.IsZero()) 5526 5527 // Now close again and put back old stream state. 5528 // This will test that we can remember user deletes by placing tombstones in the lmb/wal. 5529 fs.Stop() 5530 err = os.WriteFile(sfile, buf, defaultFilePerms) 5531 require_NoError(t, err) 5532 5533 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5534 require_NoError(t, err) 5535 defer fs.Stop() 5536 5537 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5538 t.Fatalf("Restore state does not match:\n%+v\n%+v", 5539 state, newState) 5540 } 5541 require_True(t, !state.FirstTime.IsZero()) 5542 }) 5543 } 5544 5545 func TestFileStoreFullStateTestSysRemovals(t *testing.T) { 5546 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 5547 fcfg.BlockSize = 100 5548 cfg := StreamConfig{ 5549 Name: "zzz", 5550 Subjects: []string{"*"}, 5551 MaxMsgs: 10, 5552 MaxMsgsPer: 1, 5553 Storage: FileStorage, 5554 } 5555 created := time.Now() 5556 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5557 require_NoError(t, err) 5558 defer fs.Stop() 5559 5560 // This yields an internal record length of 50 bytes. So 2 msgs per blk. 5561 msgLen := 19 5562 msg := bytes.Repeat([]byte("A"), msgLen) 5563 5564 for _, subj := range []string{"A", "B", "A", "B"} { 5565 fs.StoreMsg(subj, nil, msg) 5566 } 5567 5568 state := fs.State() 5569 require_Equal(t, state.Msgs, 2) 5570 require_Equal(t, state.FirstSeq, 3) 5571 require_Equal(t, state.LastSeq, 4) 5572 fs.Stop() 5573 5574 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5575 require_NoError(t, err) 5576 defer fs.Stop() 5577 5578 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5579 t.Fatalf("Restore state after purge does not match:\n%+v\n%+v", 5580 state, newState) 5581 } 5582 5583 for _, subj := range []string{"C", "D", "E", "F", "G", "H", "I", "J"} { 5584 fs.StoreMsg(subj, nil, msg) 5585 } 5586 5587 state = fs.State() 5588 require_Equal(t, state.Msgs, 10) 5589 require_Equal(t, state.FirstSeq, 3) 5590 require_Equal(t, state.LastSeq, 12) 5591 fs.Stop() 5592 5593 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5594 require_NoError(t, err) 5595 defer fs.Stop() 5596 5597 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5598 t.Fatalf("Restore state after purge does not match:\n%+v\n%+v", 5599 state, newState) 5600 } 5601 5602 // Goes over limit 5603 fs.StoreMsg("ZZZ", nil, msg) 5604 5605 state = fs.State() 5606 require_Equal(t, state.Msgs, 10) 5607 require_Equal(t, state.FirstSeq, 4) 5608 require_Equal(t, state.LastSeq, 13) 5609 fs.Stop() 5610 5611 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5612 require_NoError(t, err) 5613 defer fs.Stop() 5614 5615 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5616 t.Fatalf("Restore state after purge does not match:\n%+v\n%+v", 5617 state, newState) 5618 } 5619 }) 5620 } 5621 5622 func TestFileStoreSelectBlockWithFirstSeqRemovals(t *testing.T) { 5623 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 5624 fcfg.BlockSize = 100 5625 cfg := StreamConfig{ 5626 Name: "zzz", 5627 Subjects: []string{"*"}, 5628 MaxMsgsPer: 1, 5629 Storage: FileStorage, 5630 } 5631 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 5632 require_NoError(t, err) 5633 defer fs.Stop() 5634 5635 // This yields an internal record length of 50 bytes. So 2 msgs per blk. 5636 msgLen := 19 5637 msg := bytes.Repeat([]byte("A"), msgLen) 5638 5639 subjects := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+@$^" 5640 // We need over 32 blocks to kick in binary search. So 32*2+1 (65) msgs to get 33 blocks. 5641 for i := 0; i < 32*2+1; i++ { 5642 subj := string(subjects[i]) 5643 fs.StoreMsg(subj, nil, msg) 5644 } 5645 require_Equal(t, fs.numMsgBlocks(), 33) 5646 5647 // Now we want to delete the first msg of each block to move the first sequence. 5648 // Want to do this via system removes, not user initiated moves. 5649 for i := 0; i < len(subjects); i += 2 { 5650 subj := string(subjects[i]) 5651 fs.StoreMsg(subj, nil, msg) 5652 } 5653 5654 var ss StreamState 5655 fs.FastState(&ss) 5656 5657 // We want to make sure that select always returns an index and a non-nil mb. 5658 for seq := ss.FirstSeq; seq <= ss.LastSeq; seq++ { 5659 fs.mu.RLock() 5660 index, mb := fs.selectMsgBlockWithIndex(seq) 5661 fs.mu.RUnlock() 5662 require_True(t, index >= 0) 5663 require_True(t, mb != nil) 5664 require_Equal(t, (seq-1)/2, uint64(index)) 5665 } 5666 }) 5667 } 5668 5669 func TestFileStoreMsgBlockHolesAndIndexing(t *testing.T) { 5670 fs, err := newFileStore( 5671 FileStoreConfig{StoreDir: t.TempDir()}, 5672 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage, MaxMsgsPer: 1}, 5673 ) 5674 require_NoError(t, err) 5675 defer fs.Stop() 5676 5677 // Grab the message block by hand and manipulate at that level. 5678 mb := fs.getFirstBlock() 5679 writeMsg := func(subj string, seq uint64) { 5680 rl := fileStoreMsgSize(subj, nil, []byte(subj)) 5681 require_NoError(t, mb.writeMsgRecord(rl, seq, subj, nil, []byte(subj), time.Now().UnixNano(), true)) 5682 fs.rebuildState(nil) 5683 } 5684 readMsg := func(seq uint64, expectedSubj string) { 5685 // Clear cache so we load back in from disk and need to properly process any holes. 5686 ld, tombs, err := mb.rebuildState() 5687 require_NoError(t, err) 5688 require_Equal(t, ld, nil) 5689 require_Equal(t, len(tombs), 0) 5690 fs.rebuildState(nil) 5691 sm, _, err := mb.fetchMsg(seq, nil) 5692 require_NoError(t, err) 5693 require_Equal(t, sm.subj, expectedSubj) 5694 require_True(t, bytes.Equal(sm.buf[:len(expectedSubj)], []byte(expectedSubj))) 5695 } 5696 5697 writeMsg("A", 2) 5698 require_Equal(t, mb.first.seq, 2) 5699 require_Equal(t, mb.last.seq, 2) 5700 5701 writeMsg("B", 4) 5702 require_Equal(t, mb.first.seq, 2) 5703 require_Equal(t, mb.last.seq, 4) 5704 5705 writeMsg("C", 12) 5706 5707 readMsg(4, "B") 5708 require_True(t, mb.dmap.Exists(3)) 5709 5710 readMsg(12, "C") 5711 readMsg(2, "A") 5712 5713 // Check that we get deleted for the right ones etc. 5714 checkDeleted := func(seq uint64) { 5715 _, _, err = mb.fetchMsg(seq, nil) 5716 require_Error(t, err, ErrStoreMsgNotFound, errDeletedMsg) 5717 mb.mu.RLock() 5718 shouldExist, exists := seq >= mb.first.seq, mb.dmap.Exists(seq) 5719 mb.mu.RUnlock() 5720 if shouldExist { 5721 require_True(t, exists) 5722 } 5723 } 5724 checkDeleted(1) 5725 checkDeleted(3) 5726 for seq := 5; seq < 12; seq++ { 5727 checkDeleted(uint64(seq)) 5728 } 5729 } 5730 5731 func TestFileStoreMsgBlockCompactionAndHoles(t *testing.T) { 5732 fs, err := newFileStore( 5733 FileStoreConfig{StoreDir: t.TempDir()}, 5734 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage, MaxMsgsPer: 1}, 5735 ) 5736 require_NoError(t, err) 5737 defer fs.Stop() 5738 5739 msg := bytes.Repeat([]byte("Z"), 1024) 5740 for _, subj := range []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"} { 5741 fs.StoreMsg(subj, nil, msg) 5742 } 5743 // Leave first one but delete the rest. 5744 for seq := uint64(2); seq < 10; seq++ { 5745 fs.RemoveMsg(seq) 5746 } 5747 require_Equal(t, fs.numMsgBlocks(), 1) 5748 mb := fs.getFirstBlock() 5749 require_NotNil(t, mb) 5750 5751 _, ub, _ := fs.Utilization() 5752 5753 // Do compaction, should remove all excess now. 5754 mb.mu.Lock() 5755 mb.compact() 5756 mb.mu.Unlock() 5757 5758 ta, ua, _ := fs.Utilization() 5759 require_Equal(t, ub, ua) 5760 require_Equal(t, ta, ua) 5761 } 5762 5763 func TestFileStoreRemoveLastNoDoubleTombstones(t *testing.T) { 5764 fs, err := newFileStore( 5765 FileStoreConfig{StoreDir: t.TempDir()}, 5766 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage, MaxMsgsPer: 1}, 5767 ) 5768 require_NoError(t, err) 5769 defer fs.Stop() 5770 5771 fs.StoreMsg("A", nil, []byte("hello")) 5772 fs.mu.Lock() 5773 fs.removeMsgViaLimits(1) 5774 fs.mu.Unlock() 5775 5776 require_Equal(t, fs.numMsgBlocks(), 1) 5777 mb := fs.getFirstBlock() 5778 require_NotNil(t, mb) 5779 mb.loadMsgs() 5780 rbytes, _, err := fs.Utilization() 5781 require_NoError(t, err) 5782 require_Equal(t, rbytes, emptyRecordLen) 5783 } 5784 5785 func TestFileStoreFullStateMultiBlockPastWAL(t *testing.T) { 5786 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 5787 fcfg.BlockSize = 100 5788 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage} 5789 created := time.Now() 5790 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5791 require_NoError(t, err) 5792 defer fs.Stop() 5793 5794 // This yields an internal record length of 50 bytes. So 2 msgs per blk. 5795 msgLen := 19 5796 msgA := bytes.Repeat([]byte("A"), msgLen) 5797 msgZ := bytes.Repeat([]byte("Z"), msgLen) 5798 5799 // Store 2 msgs 5800 fs.StoreMsg("A", nil, msgA) 5801 fs.StoreMsg("B", nil, msgZ) 5802 require_Equal(t, fs.numMsgBlocks(), 1) 5803 fs.Stop() 5804 5805 // Grab the state from this stop. 5806 sfile := filepath.Join(fcfg.StoreDir, msgDir, streamStreamStateFile) 5807 buf, err := os.ReadFile(sfile) 5808 require_NoError(t, err) 5809 5810 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5811 require_NoError(t, err) 5812 defer fs.Stop() 5813 5814 // Store 6 more msgs. 5815 fs.StoreMsg("C", nil, msgA) 5816 fs.StoreMsg("D", nil, msgZ) 5817 fs.StoreMsg("E", nil, msgA) 5818 fs.StoreMsg("F", nil, msgZ) 5819 fs.StoreMsg("G", nil, msgA) 5820 fs.StoreMsg("H", nil, msgZ) 5821 require_Equal(t, fs.numMsgBlocks(), 4) 5822 state := fs.State() 5823 fs.Stop() 5824 5825 // Put back old stream state. 5826 // This will test that we properly walk multiple blocks past where we snapshotted state. 5827 err = os.WriteFile(sfile, buf, defaultFilePerms) 5828 require_NoError(t, err) 5829 5830 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5831 require_NoError(t, err) 5832 defer fs.Stop() 5833 5834 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5835 t.Fatalf("Restore state does not match:\n%+v\n%+v", 5836 state, newState) 5837 } 5838 require_True(t, !state.FirstTime.IsZero()) 5839 }) 5840 } 5841 5842 // This tests we can successfully recover without having to rebuild the whole stream from a mid block index.db marker 5843 // when they updated block has a removed entry. 5844 // TODO(dlc) - This test will force a rebuild atm, leaving here for later. 5845 func TestFileStoreFullStateMidBlockPastWAL(t *testing.T) { 5846 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 5847 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage, MaxMsgsPer: 1} 5848 created := time.Now() 5849 fs, err := newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5850 require_NoError(t, err) 5851 defer fs.Stop() 5852 5853 // This yields an internal record length of 50 bytes. So 2 msgs per blk. 5854 msg := bytes.Repeat([]byte("Z"), 19) 5855 5856 // Store 5 msgs 5857 fs.StoreMsg("A", nil, msg) 5858 fs.StoreMsg("B", nil, msg) 5859 fs.StoreMsg("C", nil, msg) 5860 fs.StoreMsg("D", nil, msg) 5861 fs.StoreMsg("E", nil, msg) 5862 require_Equal(t, fs.numMsgBlocks(), 1) 5863 fs.Stop() 5864 5865 // Grab the state from this stop. 5866 sfile := filepath.Join(fcfg.StoreDir, msgDir, streamStreamStateFile) 5867 buf, err := os.ReadFile(sfile) 5868 require_NoError(t, err) 5869 5870 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5871 require_NoError(t, err) 5872 defer fs.Stop() 5873 5874 // Store 5 more messages, then remove seq 2, "B". 5875 fs.StoreMsg("F", nil, msg) 5876 fs.StoreMsg("G", nil, msg) 5877 fs.StoreMsg("H", nil, msg) 5878 fs.StoreMsg("I", nil, msg) 5879 fs.StoreMsg("J", nil, msg) 5880 fs.RemoveMsg(2) 5881 5882 require_Equal(t, fs.numMsgBlocks(), 1) 5883 state := fs.State() 5884 fs.Stop() 5885 5886 // Put back old stream state. 5887 // This will test that we properly walk multiple blocks past where we snapshotted state. 5888 err = os.WriteFile(sfile, buf, defaultFilePerms) 5889 require_NoError(t, err) 5890 5891 fs, err = newFileStoreWithCreated(fcfg, cfg, created, prf(&fcfg), nil) 5892 require_NoError(t, err) 5893 defer fs.Stop() 5894 5895 if newState := fs.State(); !reflect.DeepEqual(state, newState) { 5896 t.Fatalf("Restore state does not match:\n%+v\n%+v", 5897 state, newState) 5898 } 5899 }) 5900 } 5901 5902 func TestFileStoreCompactingBlocksOnSync(t *testing.T) { 5903 testFileStoreAllPermutations(t, func(t *testing.T, fcfg FileStoreConfig) { 5904 fcfg.BlockSize = 1000 // 20 msgs per block. 5905 fcfg.SyncInterval = 100 * time.Millisecond 5906 cfg := StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage, MaxMsgsPer: 1} 5907 fs, err := newFileStoreWithCreated(fcfg, cfg, time.Now(), prf(&fcfg), nil) 5908 require_NoError(t, err) 5909 defer fs.Stop() 5910 5911 // This yields an internal record length of 50 bytes. So 20 msgs per blk. 5912 msg := bytes.Repeat([]byte("Z"), 19) 5913 subjects := "ABCDEFGHIJKLMNOPQRST" 5914 for _, subj := range subjects { 5915 fs.StoreMsg(string(subj), nil, msg) 5916 } 5917 require_Equal(t, fs.numMsgBlocks(), 1) 5918 total, reported, err := fs.Utilization() 5919 require_NoError(t, err) 5920 5921 require_Equal(t, total, reported) 5922 5923 // Now start removing, since we are small this should not kick in any inline logic. 5924 // Remove all interior messages, leave 1 and 20. So write B-S 5925 for i := 1; i < 19; i++ { 5926 fs.StoreMsg(string(subjects[i]), nil, msg) 5927 } 5928 require_Equal(t, fs.numMsgBlocks(), 2) 5929 5930 blkUtil := func() (uint64, uint64) { 5931 fs.mu.RLock() 5932 fmb := fs.blks[0] 5933 fs.mu.RUnlock() 5934 fmb.mu.RLock() 5935 defer fmb.mu.RUnlock() 5936 return fmb.rbytes, fmb.bytes 5937 } 5938 5939 total, reported = blkUtil() 5940 require_Equal(t, reported, 100) 5941 // Raw bytes will be 1000, but due to compression could be less. 5942 if fcfg.Compression != NoCompression { 5943 require_True(t, total > reported) 5944 } else { 5945 require_Equal(t, total, 1000) 5946 } 5947 5948 // Make sure the sync interval when kicked in compacts down to rbytes == 100. 5949 checkFor(t, time.Second, 100*time.Millisecond, func() error { 5950 if total, reported := blkUtil(); total <= reported { 5951 return nil 5952 } 5953 return fmt.Errorf("Not compacted yet, raw %v vs reported %v", 5954 friendlyBytes(total), friendlyBytes(reported)) 5955 }) 5956 }) 5957 } 5958 5959 // Make sure a call to Compact() updates PSIM correctly. 5960 func TestFileStoreCompactAndPSIMWhenDeletingBlocks(t *testing.T) { 5961 fs, err := newFileStore( 5962 FileStoreConfig{StoreDir: t.TempDir(), BlockSize: 512}, 5963 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 5964 require_NoError(t, err) 5965 defer fs.Stop() 5966 5967 subj, msg := "A", bytes.Repeat([]byte("ABC"), 33) // ~100bytes 5968 5969 // Add in 10 As 5970 for i := 0; i < 10; i++ { 5971 fs.StoreMsg(subj, nil, msg) 5972 } 5973 require_Equal(t, fs.numMsgBlocks(), 4) 5974 5975 // Should leave 1. 5976 n, err := fs.Compact(10) 5977 require_NoError(t, err) 5978 require_Equal(t, n, 9) 5979 require_Equal(t, fs.numMsgBlocks(), 1) 5980 5981 fs.mu.RLock() 5982 info, _ := fs.psim.Find(stringToBytes(subj)) 5983 psi := *info 5984 fs.mu.RUnlock() 5985 5986 require_Equal(t, psi.total, 1) 5987 require_Equal(t, psi.fblk, psi.lblk) 5988 } 5989 5990 func TestFileStoreTrackSubjLenForPSIM(t *testing.T) { 5991 sd := t.TempDir() 5992 fs, err := newFileStore( 5993 FileStoreConfig{StoreDir: sd}, 5994 StreamConfig{Name: "zzz", Subjects: []string{">"}, Storage: FileStorage}) 5995 require_NoError(t, err) 5996 defer fs.Stop() 5997 5998 // Place 1000 msgs with varying subjects. 5999 // Make sure we track the subject length properly. 6000 smap := make(map[string]int, 1000) 6001 buf := make([]byte, 10) 6002 for i := 0; i < 1000; i++ { 6003 var b strings.Builder 6004 // 1-6 tokens. 6005 numTokens := rand.Intn(6) + 1 6006 for i := 0; i < numTokens; i++ { 6007 tlen := rand.Intn(4) + 2 6008 tok := buf[:tlen] 6009 crand.Read(tok) 6010 b.WriteString(hex.EncodeToString(tok)) 6011 if i != numTokens-1 { 6012 b.WriteString(".") 6013 } 6014 } 6015 subj := b.String() 6016 // Avoid dupes since will cause check to fail after we delete messages. 6017 if _, ok := smap[subj]; ok { 6018 continue 6019 } 6020 smap[subj] = len(subj) 6021 fs.StoreMsg(subj, nil, nil) 6022 } 6023 6024 check := func() { 6025 t.Helper() 6026 var total int 6027 for _, slen := range smap { 6028 total += slen 6029 } 6030 fs.mu.RLock() 6031 tsl := fs.tsl 6032 fs.mu.RUnlock() 6033 require_Equal(t, tsl, total) 6034 } 6035 6036 check() 6037 6038 // Delete ~half 6039 var smv StoreMsg 6040 for i := 0; i < 500; i++ { 6041 seq := uint64(rand.Intn(1000) + 1) 6042 sm, err := fs.LoadMsg(seq, &smv) 6043 if err != nil { 6044 continue 6045 } 6046 fs.RemoveMsg(seq) 6047 delete(smap, sm.subj) 6048 } 6049 6050 check() 6051 6052 // Make sure we can recover same after restart. 6053 fs.Stop() 6054 fs, err = newFileStore( 6055 FileStoreConfig{StoreDir: sd}, 6056 StreamConfig{Name: "zzz", Subjects: []string{">"}, Storage: FileStorage}) 6057 require_NoError(t, err) 6058 defer fs.Stop() 6059 6060 check() 6061 6062 // Drain the rest through purge. 6063 fs.Purge() 6064 smap = nil 6065 check() 6066 } 6067 6068 // This was used to make sure our estimate was correct, but not needed normally. 6069 func TestFileStoreLargeFullStatePSIM(t *testing.T) { 6070 t.Skip() 6071 6072 sd := t.TempDir() 6073 fs, err := newFileStore( 6074 FileStoreConfig{StoreDir: sd}, 6075 StreamConfig{Name: "zzz", Subjects: []string{">"}, Storage: FileStorage}) 6076 require_NoError(t, err) 6077 defer fs.Stop() 6078 6079 buf := make([]byte, 20) 6080 for i := 0; i < 100_000; i++ { 6081 var b strings.Builder 6082 // 1-6 tokens. 6083 numTokens := rand.Intn(6) + 1 6084 for i := 0; i < numTokens; i++ { 6085 tlen := rand.Intn(8) + 2 6086 tok := buf[:tlen] 6087 crand.Read(tok) 6088 b.WriteString(hex.EncodeToString(tok)) 6089 if i != numTokens-1 { 6090 b.WriteString(".") 6091 } 6092 } 6093 subj := b.String() 6094 fs.StoreMsg(subj, nil, nil) 6095 } 6096 fs.Stop() 6097 } 6098 6099 func TestFileStoreLargeFullStateMetaCleanup(t *testing.T) { 6100 sd := t.TempDir() 6101 fs, err := newFileStore( 6102 FileStoreConfig{StoreDir: sd}, 6103 StreamConfig{Name: "zzz", Subjects: []string{">"}, Storage: FileStorage}) 6104 require_NoError(t, err) 6105 defer fs.Stop() 6106 6107 subj, msg := "foo.bar.baz", bytes.Repeat([]byte("ABC"), 33) // ~100bytes 6108 for i := 0; i < 1000; i++ { 6109 fs.StoreMsg(subj, nil, nil) 6110 } 6111 fs.Stop() 6112 6113 mdir := filepath.Join(sd, msgDir) 6114 idxFile := filepath.Join(mdir, "1.idx") 6115 fssFile := filepath.Join(mdir, "1.fss") 6116 require_NoError(t, os.WriteFile(idxFile, msg, defaultFilePerms)) 6117 require_NoError(t, os.WriteFile(fssFile, msg, defaultFilePerms)) 6118 6119 fs, err = newFileStore( 6120 FileStoreConfig{StoreDir: sd}, 6121 StreamConfig{Name: "zzz", Subjects: []string{">"}, Storage: FileStorage}) 6122 require_NoError(t, err) 6123 defer fs.Stop() 6124 6125 checkFor(t, time.Second, 50*time.Millisecond, func() error { 6126 if _, err := os.Stat(idxFile); err == nil { 6127 return errors.New("idx file still exists") 6128 } 6129 if _, err := os.Stat(fssFile); err == nil { 6130 return errors.New("fss file still exists") 6131 } 6132 return nil 6133 }) 6134 } 6135 6136 func TestFileStoreIndexDBExistsAfterShutdown(t *testing.T) { 6137 sd := t.TempDir() 6138 fs, err := newFileStore( 6139 FileStoreConfig{StoreDir: sd}, 6140 StreamConfig{Name: "zzz", Subjects: []string{">"}, Storage: FileStorage}) 6141 require_NoError(t, err) 6142 defer fs.Stop() 6143 6144 subj := "foo.bar.baz" 6145 for i := 0; i < 1000; i++ { 6146 fs.StoreMsg(subj, nil, nil) 6147 } 6148 6149 idxFile := filepath.Join(sd, msgDir, streamStreamStateFile) 6150 6151 fs.mu.Lock() 6152 fs.dirty = 1 6153 if err := os.Remove(idxFile); err != nil && !errors.Is(err, os.ErrNotExist) { 6154 t.Fatal(err) 6155 } 6156 fs.mu.Unlock() 6157 6158 fs.Stop() 6159 6160 checkFor(t, time.Second, 50*time.Millisecond, func() error { 6161 if _, err := os.Stat(idxFile); err != nil { 6162 return fmt.Errorf("%q doesn't exist", idxFile) 6163 } 6164 return nil 6165 }) 6166 } 6167 6168 // https://github.com/nats-io/nats-server/issues/4842 6169 func TestFileStoreSubjectCorruption(t *testing.T) { 6170 sd, blkSize := t.TempDir(), uint64(2*1024*1024) 6171 fs, err := newFileStore( 6172 FileStoreConfig{StoreDir: sd, BlockSize: blkSize}, 6173 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6174 require_NoError(t, err) 6175 defer fs.Stop() 6176 6177 numSubjects := 100 6178 msgs := [][]byte{bytes.Repeat([]byte("ABC"), 333), bytes.Repeat([]byte("ABC"), 888), bytes.Repeat([]byte("ABC"), 555)} 6179 for i := 0; i < 10_000; i++ { 6180 subj := fmt.Sprintf("foo.%d", rand.Intn(numSubjects)+1) 6181 msg := msgs[rand.Intn(len(msgs))] 6182 fs.StoreMsg(subj, nil, msg) 6183 } 6184 fs.Stop() 6185 6186 require_NoError(t, os.Remove(filepath.Join(sd, msgDir, streamStreamStateFile))) 6187 6188 fs, err = newFileStore( 6189 FileStoreConfig{StoreDir: sd, BlockSize: blkSize}, 6190 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6191 require_NoError(t, err) 6192 defer fs.Stop() 6193 6194 for subj := range fs.SubjectsTotals(">") { 6195 var n int 6196 _, err := fmt.Sscanf(subj, "foo.%d", &n) 6197 require_NoError(t, err) 6198 } 6199 } 6200 6201 // Since 2.10 we no longer have fss, and the approach for calculating NumPending would branch 6202 // based on the old fss metadata being present. This meant that calculating NumPending in >= 2.10.x 6203 // would load all blocks to complete. This test makes sure we do not do that anymore. 6204 func TestFileStoreNumPendingLastBySubject(t *testing.T) { 6205 sd, blkSize := t.TempDir(), uint64(1024) 6206 fs, err := newFileStore( 6207 FileStoreConfig{StoreDir: sd, BlockSize: blkSize}, 6208 StreamConfig{Name: "zzz", Subjects: []string{"foo.*.*"}, Storage: FileStorage}) 6209 require_NoError(t, err) 6210 defer fs.Stop() 6211 6212 numSubjects := 20 6213 msg := bytes.Repeat([]byte("ABC"), 25) 6214 for i := 1; i <= 1000; i++ { 6215 subj := fmt.Sprintf("foo.%d.%d", rand.Intn(numSubjects)+1, i) 6216 fs.StoreMsg(subj, nil, msg) 6217 } 6218 // Each block has ~8 msgs. 6219 require_True(t, fs.numMsgBlocks() > 100) 6220 6221 calcCacheLoads := func() (cloads uint64) { 6222 fs.mu.RLock() 6223 defer fs.mu.RUnlock() 6224 for _, mb := range fs.blks { 6225 mb.mu.RLock() 6226 cloads += mb.cloads 6227 mb.mu.RUnlock() 6228 } 6229 return cloads 6230 } 6231 6232 total, _ := fs.NumPending(0, "foo.*.*", true) 6233 require_Equal(t, total, 1000) 6234 // Make sure no blocks were loaded to calculate this as a new consumer. 6235 require_Equal(t, calcCacheLoads(), 0) 6236 6237 checkResult := func(sseq, np uint64, filter string) { 6238 t.Helper() 6239 var checkTotal uint64 6240 var smv StoreMsg 6241 for seq := sseq; seq <= 1000; seq++ { 6242 sm, err := fs.LoadMsg(seq, &smv) 6243 require_NoError(t, err) 6244 if subjectIsSubsetMatch(sm.subj, filter) { 6245 checkTotal++ 6246 } 6247 } 6248 require_Equal(t, np, checkTotal) 6249 } 6250 6251 // Make sure partials work properly. 6252 for _, filter := range []string{"foo.10.*", "*.22.*", "*.*.222", "foo.5.999", "*.2.*"} { 6253 sseq := uint64(rand.Intn(250) + 200) // Between 200-450 6254 total, _ = fs.NumPending(sseq, filter, true) 6255 checkResult(sseq, total, filter) 6256 } 6257 } 6258 6259 // We had a bug that could cause internal memory corruption of the psim keys in memory 6260 // which could have been written to disk via index.db. 6261 func TestFileStoreCorruptPSIMOnDisk(t *testing.T) { 6262 sd := t.TempDir() 6263 fs, err := newFileStore( 6264 FileStoreConfig{StoreDir: sd}, 6265 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6266 require_NoError(t, err) 6267 defer fs.Stop() 6268 6269 fs.StoreMsg("foo.bar", nil, []byte("ABC")) 6270 fs.StoreMsg("foo.baz", nil, []byte("XYZ")) 6271 6272 // Force bad subject. 6273 fs.mu.Lock() 6274 psi, _ := fs.psim.Find(stringToBytes("foo.bar")) 6275 bad := make([]byte, 7) 6276 crand.Read(bad) 6277 fs.psim.Insert(bad, *psi) 6278 fs.psim.Delete(stringToBytes("foo.bar")) 6279 fs.dirty++ 6280 fs.mu.Unlock() 6281 6282 // Restart 6283 fs.Stop() 6284 fs, err = newFileStore( 6285 FileStoreConfig{StoreDir: sd}, 6286 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6287 require_NoError(t, err) 6288 defer fs.Stop() 6289 6290 sm, err := fs.LoadLastMsg("foo.bar", nil) 6291 require_NoError(t, err) 6292 require_True(t, bytes.Equal(sm.msg, []byte("ABC"))) 6293 6294 sm, err = fs.LoadLastMsg("foo.baz", nil) 6295 require_NoError(t, err) 6296 require_True(t, bytes.Equal(sm.msg, []byte("XYZ"))) 6297 } 6298 6299 func TestFileStorePurgeExBufPool(t *testing.T) { 6300 sd := t.TempDir() 6301 fs, err := newFileStore( 6302 FileStoreConfig{StoreDir: sd, BlockSize: 1024}, 6303 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6304 require_NoError(t, err) 6305 defer fs.Stop() 6306 6307 msg := bytes.Repeat([]byte("ABC"), 33) // ~100bytes 6308 for i := 0; i < 1000; i++ { 6309 fs.StoreMsg("foo.foo", nil, msg) 6310 fs.StoreMsg("foo.bar", nil, msg) 6311 } 6312 6313 p, err := fs.PurgeEx("foo.bar", 1, 0) 6314 require_NoError(t, err) 6315 require_Equal(t, p, 1000) 6316 6317 // Now make sure we do not have all of the msg blocks cache's loaded. 6318 var loaded int 6319 fs.mu.RLock() 6320 for _, mb := range fs.blks { 6321 mb.mu.RLock() 6322 if mb.cacheAlreadyLoaded() { 6323 loaded++ 6324 } 6325 mb.mu.RUnlock() 6326 } 6327 fs.mu.RUnlock() 6328 require_Equal(t, loaded, 1) 6329 } 6330 6331 func TestFileStoreFSSMeta(t *testing.T) { 6332 sd := t.TempDir() 6333 fs, err := newFileStore( 6334 FileStoreConfig{StoreDir: sd, BlockSize: 100, CacheExpire: 200 * time.Millisecond, SyncInterval: time.Second}, 6335 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 6336 require_NoError(t, err) 6337 defer fs.Stop() 6338 6339 // This yields an internal record length of 50 bytes. So 2 msgs per blk with subject len of 1, e.g. "A" or "Z". 6340 msg := bytes.Repeat([]byte("Z"), 19) 6341 6342 // Should leave us with |A-Z| |Z-Z| |Z-Z| |Z-A| 6343 fs.StoreMsg("A", nil, msg) 6344 for i := 0; i < 6; i++ { 6345 fs.StoreMsg("Z", nil, msg) 6346 } 6347 fs.StoreMsg("A", nil, msg) 6348 6349 // Let cache's expire before PurgeEx which will load them back in. 6350 time.Sleep(250 * time.Millisecond) 6351 6352 p, err := fs.PurgeEx("A", 1, 0) 6353 require_NoError(t, err) 6354 require_Equal(t, p, 2) 6355 6356 // Make sure cache is not loaded but fss state still is. 6357 var stillHasCache, noFSS bool 6358 fs.mu.RLock() 6359 for _, mb := range fs.blks { 6360 mb.mu.RLock() 6361 stillHasCache = stillHasCache || mb.cacheAlreadyLoaded() 6362 noFSS = noFSS || mb.fssNotLoaded() 6363 mb.mu.RUnlock() 6364 } 6365 fs.mu.RUnlock() 6366 6367 require_False(t, stillHasCache) 6368 require_False(t, noFSS) 6369 6370 // Let fss expire via syncInterval. 6371 time.Sleep(time.Second) 6372 6373 fs.mu.RLock() 6374 for _, mb := range fs.blks { 6375 mb.mu.RLock() 6376 noFSS = noFSS || mb.fssNotLoaded() 6377 mb.mu.RUnlock() 6378 } 6379 fs.mu.RUnlock() 6380 6381 require_True(t, noFSS) 6382 } 6383 6384 func TestFileStoreExpireCacheOnLinearWalk(t *testing.T) { 6385 sd := t.TempDir() 6386 expire := 250 * time.Millisecond 6387 fs, err := newFileStore( 6388 FileStoreConfig{StoreDir: sd, CacheExpire: expire}, 6389 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 6390 require_NoError(t, err) 6391 defer fs.Stop() 6392 6393 // This yields an internal record length of 50 bytes. 6394 subj, msg := "Z", bytes.Repeat([]byte("Z"), 19) 6395 6396 // Store 10 messages, so 5 blocks. 6397 for i := 0; i < 10; i++ { 6398 fs.StoreMsg(subj, nil, msg) 6399 } 6400 // Let them all expire. This way we load as we walk and can test that we expire all blocks without 6401 // needing to worry about last write times blocking forced expiration. 6402 time.Sleep(expire) 6403 6404 checkNoCache := func() { 6405 t.Helper() 6406 fs.mu.RLock() 6407 var stillHasCache bool 6408 for _, mb := range fs.blks { 6409 mb.mu.RLock() 6410 stillHasCache = stillHasCache || mb.cacheAlreadyLoaded() 6411 mb.mu.RUnlock() 6412 } 6413 fs.mu.RUnlock() 6414 require_False(t, stillHasCache) 6415 } 6416 6417 // Walk forward. 6418 var smv StoreMsg 6419 for seq := uint64(1); seq <= 10; seq++ { 6420 _, err := fs.LoadMsg(seq, &smv) 6421 require_NoError(t, err) 6422 } 6423 checkNoCache() 6424 6425 // No test walking backwards. We have this scenario when we search for starting points for sourced streams. 6426 // Noticed some memory bloat when we have to search many blocks looking for a source that may be closer to the 6427 // beginning of the stream (infrequently updated sourced stream). 6428 for seq := uint64(10); seq >= 1; seq-- { 6429 _, err := fs.LoadMsg(seq, &smv) 6430 require_NoError(t, err) 6431 } 6432 checkNoCache() 6433 6434 // Now make sure still expires properly on linear scans with deleted msgs. 6435 // We want to make sure we track linear updates even if message deleted. 6436 _, err = fs.RemoveMsg(2) 6437 require_NoError(t, err) 6438 _, err = fs.RemoveMsg(9) 6439 require_NoError(t, err) 6440 6441 // Walk forward. 6442 for seq := uint64(1); seq <= 10; seq++ { 6443 _, err := fs.LoadMsg(seq, &smv) 6444 if seq == 2 || seq == 9 { 6445 require_Error(t, err, errDeletedMsg) 6446 } else { 6447 require_NoError(t, err) 6448 } 6449 } 6450 checkNoCache() 6451 } 6452 6453 func TestFileStoreSkipMsgs(t *testing.T) { 6454 fs, err := newFileStore( 6455 FileStoreConfig{StoreDir: t.TempDir(), BlockSize: 1024}, 6456 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 6457 require_NoError(t, err) 6458 defer fs.Stop() 6459 6460 // Test on empty FS first. 6461 // Make sure wrong starting sequence fails. 6462 err = fs.SkipMsgs(10, 100) 6463 require_Error(t, err, ErrSequenceMismatch) 6464 6465 err = fs.SkipMsgs(1, 100) 6466 require_NoError(t, err) 6467 6468 state := fs.State() 6469 require_Equal(t, state.FirstSeq, 101) 6470 require_Equal(t, state.LastSeq, 100) 6471 require_Equal(t, fs.numMsgBlocks(), 1) 6472 6473 // Now add alot. 6474 err = fs.SkipMsgs(101, 100_000) 6475 require_NoError(t, err) 6476 state = fs.State() 6477 require_Equal(t, state.FirstSeq, 100_101) 6478 require_Equal(t, state.LastSeq, 100_100) 6479 require_Equal(t, fs.numMsgBlocks(), 1) 6480 6481 // Now add in a message, and then skip to check dmap. 6482 fs, err = newFileStore( 6483 FileStoreConfig{StoreDir: t.TempDir(), BlockSize: 1024}, 6484 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 6485 require_NoError(t, err) 6486 defer fs.Stop() 6487 6488 fs.StoreMsg("foo", nil, nil) 6489 err = fs.SkipMsgs(2, 10) 6490 require_NoError(t, err) 6491 state = fs.State() 6492 require_Equal(t, state.FirstSeq, 1) 6493 require_Equal(t, state.LastSeq, 11) 6494 require_Equal(t, state.Msgs, 1) 6495 require_Equal(t, state.NumDeleted, 10) 6496 require_Equal(t, len(state.Deleted), 10) 6497 6498 // Check Fast State too. 6499 state.Deleted = nil 6500 fs.FastState(&state) 6501 require_Equal(t, state.FirstSeq, 1) 6502 require_Equal(t, state.LastSeq, 11) 6503 require_Equal(t, state.Msgs, 1) 6504 require_Equal(t, state.NumDeleted, 10) 6505 } 6506 6507 func TestFileStoreOptimizeFirstLoadNextMsgWithSequenceZero(t *testing.T) { 6508 sd := t.TempDir() 6509 fs, err := newFileStore( 6510 FileStoreConfig{StoreDir: sd, BlockSize: 4096}, 6511 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6512 require_NoError(t, err) 6513 defer fs.Stop() 6514 6515 msg := bytes.Repeat([]byte("ZZZ"), 33) // ~100bytes 6516 6517 for i := 0; i < 5000; i++ { 6518 fs.StoreMsg("foo.A", nil, msg) 6519 } 6520 // This will create alot of blocks, ~167. 6521 // Just used to check that we do not load these in when searching. 6522 // Now add in 10 for foo.bar at the end. 6523 for i := 0; i < 10; i++ { 6524 fs.StoreMsg("foo.B", nil, msg) 6525 } 6526 // The bug would not be visible on running server per se since we would have had fss loaded 6527 // and that sticks around a bit longer, we would use that to skip over the early blocks. So stop 6528 // and restart the filestore. 6529 fs.Stop() 6530 fs, err = newFileStore( 6531 FileStoreConfig{StoreDir: sd, BlockSize: 4096}, 6532 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6533 require_NoError(t, err) 6534 defer fs.Stop() 6535 6536 // Now fetch the next message for foo.B but set starting sequence to 0. 6537 _, nseq, err := fs.LoadNextMsg("foo.B", false, 0, nil) 6538 require_NoError(t, err) 6539 require_Equal(t, nseq, 5001) 6540 // Now check how many blks are loaded, should be only 1. 6541 require_Equal(t, fs.cacheLoads(), 1) 6542 } 6543 6544 func TestFileStoreWriteFullStateHighSubjectCardinality(t *testing.T) { 6545 t.Skip() 6546 6547 sd := t.TempDir() 6548 fs, err := newFileStore( 6549 FileStoreConfig{StoreDir: sd, BlockSize: 4096}, 6550 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6551 require_NoError(t, err) 6552 defer fs.Stop() 6553 6554 msg := []byte{1, 2, 3} 6555 6556 for i := 0; i < 1_000_000; i++ { 6557 subj := fmt.Sprintf("subj_%d", i) 6558 _, _, err := fs.StoreMsg(subj, nil, msg) 6559 require_NoError(t, err) 6560 } 6561 6562 start := time.Now() 6563 require_NoError(t, fs.writeFullState()) 6564 t.Logf("Took %s to writeFullState", time.Since(start)) 6565 } 6566 6567 func TestFileStoreEraseMsgWithDbitSlots(t *testing.T) { 6568 fs, err := newFileStore( 6569 FileStoreConfig{StoreDir: t.TempDir()}, 6570 StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage}) 6571 require_NoError(t, err) 6572 defer fs.Stop() 6573 6574 fs.StoreMsg("foo", nil, []byte("abd")) 6575 for i := 0; i < 10; i++ { 6576 fs.SkipMsg() 6577 } 6578 fs.StoreMsg("foo", nil, []byte("abd")) 6579 // Now grab that first block and compact away the skips which will 6580 // introduce dbits into our idx. 6581 fs.mu.RLock() 6582 mb := fs.blks[0] 6583 fs.mu.RUnlock() 6584 // Compact. 6585 mb.mu.Lock() 6586 mb.compact() 6587 mb.mu.Unlock() 6588 6589 removed, err := fs.EraseMsg(1) 6590 require_NoError(t, err) 6591 require_True(t, removed) 6592 } 6593 6594 func TestFileStoreEraseMsgWithAllTrailingDbitSlots(t *testing.T) { 6595 fs, err := newFileStore( 6596 FileStoreConfig{StoreDir: t.TempDir()}, 6597 StreamConfig{Name: "zzz", Subjects: []string{"foo"}, Storage: FileStorage}) 6598 require_NoError(t, err) 6599 defer fs.Stop() 6600 6601 fs.StoreMsg("foo", nil, []byte("abc")) 6602 fs.StoreMsg("foo", nil, []byte("abcdefg")) 6603 6604 for i := 0; i < 10; i++ { 6605 fs.SkipMsg() 6606 } 6607 // Now grab that first block and compact away the skips which will 6608 // introduce dbits into our idx. 6609 fs.mu.RLock() 6610 mb := fs.blks[0] 6611 fs.mu.RUnlock() 6612 // Compact. 6613 mb.mu.Lock() 6614 mb.compact() 6615 mb.mu.Unlock() 6616 6617 removed, err := fs.EraseMsg(2) 6618 require_NoError(t, err) 6619 require_True(t, removed) 6620 } 6621 6622 func TestFileStoreMultiLastSeqs(t *testing.T) { 6623 fs, err := newFileStore( 6624 FileStoreConfig{StoreDir: t.TempDir(), BlockSize: 256}, // Make block size small to test multiblock selections with maxSeq 6625 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6626 require_NoError(t, err) 6627 defer fs.Stop() 6628 6629 msg := []byte("abc") 6630 for i := 0; i < 33; i++ { 6631 fs.StoreMsg("foo.foo", nil, msg) 6632 fs.StoreMsg("foo.bar", nil, msg) 6633 fs.StoreMsg("foo.baz", nil, msg) 6634 } 6635 for i := 0; i < 33; i++ { 6636 fs.StoreMsg("bar.foo", nil, msg) 6637 fs.StoreMsg("bar.bar", nil, msg) 6638 fs.StoreMsg("bar.baz", nil, msg) 6639 } 6640 6641 checkResults := func(seqs, expected []uint64) { 6642 t.Helper() 6643 if len(seqs) != len(expected) { 6644 t.Fatalf("Expected %+v got %+v", expected, seqs) 6645 } 6646 for i := range seqs { 6647 if seqs[i] != expected[i] { 6648 t.Fatalf("Expected %+v got %+v", expected, seqs) 6649 } 6650 } 6651 } 6652 6653 // UpTo sequence 3. Tests block split. 6654 seqs, err := fs.MultiLastSeqs([]string{"foo.*"}, 3, -1) 6655 require_NoError(t, err) 6656 checkResults(seqs, []uint64{1, 2, 3}) 6657 // Up to last sequence of the stream. 6658 seqs, err = fs.MultiLastSeqs([]string{"foo.*"}, 0, -1) 6659 require_NoError(t, err) 6660 checkResults(seqs, []uint64{97, 98, 99}) 6661 // Check for bar.* at the end. 6662 seqs, err = fs.MultiLastSeqs([]string{"bar.*"}, 0, -1) 6663 require_NoError(t, err) 6664 checkResults(seqs, []uint64{196, 197, 198}) 6665 // This should find nothing. 6666 seqs, err = fs.MultiLastSeqs([]string{"bar.*"}, 99, -1) 6667 require_NoError(t, err) 6668 checkResults(seqs, nil) 6669 6670 // Do multiple subjects explicitly. 6671 seqs, err = fs.MultiLastSeqs([]string{"foo.foo", "foo.bar", "foo.baz"}, 3, -1) 6672 require_NoError(t, err) 6673 checkResults(seqs, []uint64{1, 2, 3}) 6674 seqs, err = fs.MultiLastSeqs([]string{"foo.foo", "foo.bar", "foo.baz"}, 0, -1) 6675 require_NoError(t, err) 6676 checkResults(seqs, []uint64{97, 98, 99}) 6677 seqs, err = fs.MultiLastSeqs([]string{"bar.foo", "bar.bar", "bar.baz"}, 0, -1) 6678 require_NoError(t, err) 6679 checkResults(seqs, []uint64{196, 197, 198}) 6680 seqs, err = fs.MultiLastSeqs([]string{"bar.foo", "bar.bar", "bar.baz"}, 99, -1) 6681 require_NoError(t, err) 6682 checkResults(seqs, nil) 6683 6684 // Check single works 6685 seqs, err = fs.MultiLastSeqs([]string{"foo.foo"}, 3, -1) 6686 require_NoError(t, err) 6687 checkResults(seqs, []uint64{1}) 6688 6689 // Now test that we properly de-duplicate between filters. 6690 seqs, err = fs.MultiLastSeqs([]string{"foo.*", "foo.bar"}, 3, -1) 6691 require_NoError(t, err) 6692 checkResults(seqs, []uint64{1, 2, 3}) 6693 seqs, err = fs.MultiLastSeqs([]string{"bar.>", "bar.bar", "bar.baz"}, 0, -1) 6694 require_NoError(t, err) 6695 checkResults(seqs, []uint64{196, 197, 198}) 6696 6697 // All 6698 seqs, err = fs.MultiLastSeqs([]string{">"}, 0, -1) 6699 require_NoError(t, err) 6700 checkResults(seqs, []uint64{97, 98, 99, 196, 197, 198}) 6701 seqs, err = fs.MultiLastSeqs([]string{">"}, 99, -1) 6702 require_NoError(t, err) 6703 checkResults(seqs, []uint64{97, 98, 99}) 6704 } 6705 6706 func TestFileStoreMultiLastSeqsMaxAllowed(t *testing.T) { 6707 fs, err := newFileStore( 6708 FileStoreConfig{StoreDir: t.TempDir()}, 6709 StreamConfig{Name: "zzz", Subjects: []string{"foo.*"}, Storage: FileStorage}) 6710 require_NoError(t, err) 6711 defer fs.Stop() 6712 6713 msg := []byte("abc") 6714 for i := 1; i <= 100; i++ { 6715 fs.StoreMsg(fmt.Sprintf("foo.%d", i), nil, msg) 6716 } 6717 // Test that if we specify maxAllowed that we get the correct error. 6718 seqs, err := fs.MultiLastSeqs([]string{"foo.*"}, 0, 10) 6719 require_True(t, seqs == nil) 6720 require_Error(t, err, ErrTooManyResults) 6721 } 6722 6723 /////////////////////////////////////////////////////////////////////////// 6724 // Benchmarks 6725 /////////////////////////////////////////////////////////////////////////// 6726 6727 func Benchmark_FileStoreSelectMsgBlock(b *testing.B) { 6728 // We use small block size to create lots of blocks for this test. 6729 fs, err := newFileStore( 6730 FileStoreConfig{StoreDir: b.TempDir(), BlockSize: 128}, 6731 StreamConfig{Name: "zzz", Subjects: []string{"*"}, Storage: FileStorage}) 6732 if err != nil { 6733 b.Fatalf("Unexpected error: %v", err) 6734 } 6735 defer fs.Stop() 6736 6737 subj, msg := "A", bytes.Repeat([]byte("ABC"), 33) // ~100bytes 6738 6739 // Add in a bunch of blocks. 6740 for i := 0; i < 1000; i++ { 6741 fs.StoreMsg(subj, nil, msg) 6742 } 6743 if fs.numMsgBlocks() < 1000 { 6744 b.Fatalf("Expected at least 1000 blocks, got %d", fs.numMsgBlocks()) 6745 } 6746 6747 fs.mu.RLock() 6748 defer fs.mu.RUnlock() 6749 6750 b.ResetTimer() 6751 for i := 0; i < b.N; i++ { 6752 _, mb := fs.selectMsgBlockWithIndex(1) 6753 if mb == nil { 6754 b.Fatalf("Expected a non-nil mb") 6755 } 6756 } 6757 b.StopTimer() 6758 }