# Test a simple WAL file that consists of a single segment with a clean WAL
# tail. This is what we'd expect from a graceful process exit in a non-failover
# scenario.

define logNum=000001
batch count=3 size=1024 seq=1
batch count=2 size=30 seq=20
batch count=50 size=512000 seq=21 sync
----
created "000001.log"
0..1035: batch #1
1035..1076: batch #20
1076..513252: batch #21

read logNum=000001
----
r.NextRecord() = (rr, (000001.log: 0), <nil>)
  io.ReadAll(rr) = ("0100000000000000030000004892e32448351fc1f9e2d52044496ca2cd51999f... <1024-byte record>", <nil>)
  BatchHeader: [seqNum=1,count=3]
r.NextRecord() = (rr, (000001.log: 1035), <nil>)
  io.ReadAll(rr) = ("14000000000000000200000067b3235a4a9a000000000000000000000000", <nil>)
  BatchHeader: [seqNum=20,count=2]
r.NextRecord() = (rr, (000001.log: 1076), <nil>)
  io.ReadAll(rr) = ("150000000000000032000000fcbdf64fad60c5383b3f201ec0b234ca2f21a4f7... <512000-byte record>", <nil>)
  BatchHeader: [seqNum=21,count=50]
r.NextRecord() = (rr, (000001.log: 513252), EOF)

# Add a new physical file for the same logical log, this one with a batch that
# only contains a LogData. This exercises a subtlety in which a sequence number
# is repeated. The LogData batch with zero count should be skipped. The record
# with a batch with a nonzero count and the same sequence number should be
# surfaced.

define logNum=000001 logNameIndex=001
batch count=2 seq=22 size=412
batch count=0 seq=24 size=64
batch count=1 seq=24 size=100
----
created "000001-001.log"
0..423: batch #22
423..498: batch #24
498..609: batch #24

read logNum=000001
----
r.NextRecord() = (rr, (000001.log: 0), <nil>)
  io.ReadAll(rr) = ("0100000000000000030000004892e32448351fc1f9e2d52044496ca2cd51999f... <1024-byte record>", <nil>)
  BatchHeader: [seqNum=1,count=3]
r.NextRecord() = (rr, (000001.log: 1035), <nil>)
  io.ReadAll(rr) = ("14000000000000000200000067b3235a4a9a000000000000000000000000", <nil>)
  BatchHeader: [seqNum=20,count=2]
r.NextRecord() = (rr, (000001.log: 1076), <nil>)
  io.ReadAll(rr) = ("150000000000000032000000fcbdf64fad60c5383b3f201ec0b234ca2f21a4f7... <512000-byte record>", <nil>)
  BatchHeader: [seqNum=21,count=50]
r.NextRecord() = (rr, (000001-001.log: 0), 513252 from previous files, <nil>)
  io.ReadAll(rr) = ("160000000000000002000000eb2b0fd29c3e15ed510704c8c9ae977d8e6df815... <412-byte record>", <nil>)
  BatchHeader: [seqNum=22,count=2]
r.NextRecord() = (rr, (000001-001.log: 498), 513252 from previous files, <nil>)
  io.ReadAll(rr) = ("1800000000000000010000004c163720a7957d7d24986efbc7e26d6194d09fdc... <100-byte record>", <nil>)
  BatchHeader: [seqNum=24,count=1]
r.NextRecord() = (rr, (000001-001.log: 609), 513252 from previous files, EOF)

# Test a recycled log file. Recycle 000001.log as 000002.log. This time, do not
# exit cleanly. This simulates a hard process exit (eg, during a fatal shutdown,
# power failure, etc).

define logNum=000002 recycleFilename=000001.log close-unclean
batch count=10 size=100 seq=10 sync
batch count=22 size=150 seq=20 sync
batch count=1 size=64000 seq=42 sync
----
recycled "000001.log" as "000002.log"
0..111: batch #10
111..272: batch #20
272..64294: batch #42

# Reading a recycled log file with an unclean close can result in an error at
# the tail of the file; eg, "invalid chunk." This is okay and ignored by Open as
# long as the WAL is the most recent one. Older WALs are requried to have "clean
# closes".

read logNum=000002
----
r.NextRecord() = (rr, (000002.log: 0), <nil>)
  io.ReadAll(rr) = ("0a000000000000000a000000afd43820144bc9d4446adeaacc407cd91c971e79... <100-byte record>", <nil>)
  BatchHeader: [seqNum=10,count=10]
r.NextRecord() = (rr, (000002.log: 111), <nil>)
  io.ReadAll(rr) = ("140000000000000016000000fe05c7d6c9bbd0d55b0da8b6943848245b384bf1... <150-byte record>", <nil>)
  BatchHeader: [seqNum=20,count=22]
r.NextRecord() = (rr, (000002.log: 272), <nil>)
  io.ReadAll(rr) = ("2a0000000000000001000000ec8367c42ebf0ffad5c57ece37b18559ba95ad78... <64000-byte record>", <nil>)
  BatchHeader: [seqNum=42,count=1]
r.NextRecord() = (rr, (000002.log: 64294), pebble/record: unexpected EOF)

# Test a typical failure scenario. Start off with a recycled log file (000003)
# that would be on the primary device. It closes "unclean" because we're unable
# to sync the EOF trailer due to the stall.

define logNum=000003 recycleFilename=000002.log close-unclean
batch count=10 size=100 seq=10 sync
batch count=22 size=150 seq=20
batch count=1 size=20 seq=42 sync
----
recycled "000002.log" as "000003.log"
0..111: batch #10
111..272: batch #20
272..303: batch #42

# Then the WAL fails over to a new physical WAL file on a new device. The last
# two batches of previous WAL are duplicated.

define logNum=000003 logNameIndex=001
batch count=22 size=150 seq=20
batch count=1 size=20 seq=42 sync
batch count=3 size=80 seq=43 sync
batch count=9 size=2055 seq=46 sync
----
created "000003-001.log"
0..161: batch #20
161..192: batch #42
192..283: batch #43
283..2349: batch #46

# Reading the log file should transparently deduplicate the repeated batches.

read logNum=000003
----
r.NextRecord() = (rr, (000003.log: 0), <nil>)
  io.ReadAll(rr) = ("0a000000000000000a00000062ab232e0552e5fd6091f6e21102bf30aaa79627... <100-byte record>", <nil>)
  BatchHeader: [seqNum=10,count=10]
r.NextRecord() = (rr, (000003.log: 111), <nil>)
  io.ReadAll(rr) = ("140000000000000016000000966b624625070dadfd22ddb0d5d7cc582718a5d6... <150-byte record>", <nil>)
  BatchHeader: [seqNum=20,count=22]
r.NextRecord() = (rr, (000003.log: 272), <nil>)
  io.ReadAll(rr) = ("2a00000000000000010000000000000000000000", <nil>)
  BatchHeader: [seqNum=42,count=1]
r.NextRecord() = (rr, (000003-001.log: 192), 303 from previous files, <nil>)
  io.ReadAll(rr) = ("2b0000000000000003000000f3eb964c6fd7dd151f60c3031282d500dad32aad... <80-byte record>", <nil>)
  BatchHeader: [seqNum=43,count=3]
r.NextRecord() = (rr, (000003-001.log: 283), 303 from previous files, <nil>)
  io.ReadAll(rr) = ("2e00000000000000090000004d9b33adaebf7365f3192f4e20106a03e9241a88... <2055-byte record>", <nil>)
  BatchHeader: [seqNum=46,count=9]
r.NextRecord() = (rr, (000003-001.log: 2349), 303 from previous files, EOF)

# Extend logical log file 000003 with another log file, the result of failing
# back to the original the device. This time do an "unclean" close.

define logNum=000003 logNameIndex=002 unclean-close
batch count=3 size=80 seq=43 sync
batch count=9 size=2055 seq=46 sync
batch count=2 size=205 seq=55 sync
----
created "000003-002.log"
0..91: batch #43
91..2157: batch #46
2157..2373: batch #55

read logNum=000003
----
r.NextRecord() = (rr, (000003.log: 0), <nil>)
  io.ReadAll(rr) = ("0a000000000000000a00000062ab232e0552e5fd6091f6e21102bf30aaa79627... <100-byte record>", <nil>)
  BatchHeader: [seqNum=10,count=10]
r.NextRecord() = (rr, (000003.log: 111), <nil>)
  io.ReadAll(rr) = ("140000000000000016000000966b624625070dadfd22ddb0d5d7cc582718a5d6... <150-byte record>", <nil>)
  BatchHeader: [seqNum=20,count=22]
r.NextRecord() = (rr, (000003.log: 272), <nil>)
  io.ReadAll(rr) = ("2a00000000000000010000000000000000000000", <nil>)
  BatchHeader: [seqNum=42,count=1]
r.NextRecord() = (rr, (000003-001.log: 192), 303 from previous files, <nil>)
  io.ReadAll(rr) = ("2b0000000000000003000000f3eb964c6fd7dd151f60c3031282d500dad32aad... <80-byte record>", <nil>)
  BatchHeader: [seqNum=43,count=3]
r.NextRecord() = (rr, (000003-001.log: 283), 303 from previous files, <nil>)
  io.ReadAll(rr) = ("2e00000000000000090000004d9b33adaebf7365f3192f4e20106a03e9241a88... <2055-byte record>", <nil>)
  BatchHeader: [seqNum=46,count=9]
r.NextRecord() = (rr, (000003-002.log: 2157), 2652 from previous files, <nil>)
  io.ReadAll(rr) = ("3700000000000000020000000f17a02ef83a97ceae6703f0d784c2497a2021a5... <205-byte record>", <nil>)
  BatchHeader: [seqNum=55,count=2]
r.NextRecord() = (rr, (000003-002.log: 2373), 2652 from previous files, EOF)

# Test reading a log file that does not exist.

read logNum=000004
----
log with logNum 4 not found

# Test a corrupted log file that encodes a record too small to be a valid batch.
# The second "batch" only has a length of 5.

define logNum=000004
batch count=1 seq=1 size=20 sync
batch size=5 sync
----
created "000004.log"
0..31: batch #1
31..47: batch #0

# Reading the corrupt batch should error with a corruption error.

read logNum=000004
----
r.NextRecord() = (rr, (000004.log: 0), <nil>)
  io.ReadAll(rr) = ("0100000000000000010000000000000000000000", <nil>)
  BatchHeader: [seqNum=1,count=1]
r.NextRecord() = (rr, (000004.log: 31), pebble: corrupt log file logNum=4, logNameIndex=000: invalid batch)

# Test a two segment log file where the second log file ends in garbage. The
# invalid chunk error of the final log file should be propagated up.

define logNum=000005 unclean-close
batch count=1 seq=95225 size=592 sync
batch count=9 seq=95226 size=295 sync
batch count=8 seq=95235 size=2525 sync
batch count=256 seq=95243 size=2566 sync
----
created "000005.log"
0..603: batch #95225
603..909: batch #95226
909..3445: batch #95235
3445..6022: batch #95243

define logNum=000005 logNameIndex=001 unclean-close
batch count=2 seq=95499 size=44 sync
batch count=5 seq=95501 size=416 sync
batch count=29 seq=95506 size=199 sync
write-garbage size=353 sync
----
created "000005-001.log"
0..55: batch #95499
55..482: batch #95501
482..692: batch #95506
692..1045: write-garbage

read logNum=000005
----
r.NextRecord() = (rr, (000005.log: 0), <nil>)
  io.ReadAll(rr) = ("f97301000000000001000000602fdb1fc7d9daaa4dd5741e5a8b07423f81d57e... <592-byte record>", <nil>)
  BatchHeader: [seqNum=95225,count=1]
r.NextRecord() = (rr, (000005.log: 603), <nil>)
  io.ReadAll(rr) = ("fa73010000000000090000000d66c9a18891d4184fbe38847d0bcb41bc8a90ad... <295-byte record>", <nil>)
  BatchHeader: [seqNum=95226,count=9]
r.NextRecord() = (rr, (000005.log: 909), <nil>)
  io.ReadAll(rr) = ("037401000000000008000000216c49c3f49c595e80076b1d6d9480cff3a8d44a... <2525-byte record>", <nil>)
  BatchHeader: [seqNum=95235,count=8]
r.NextRecord() = (rr, (000005.log: 3445), <nil>)
  io.ReadAll(rr) = ("0b7401000000000000010000313db6e445a8213e7224d87caf90dcfe6eecf25a... <2566-byte record>", <nil>)
  BatchHeader: [seqNum=95243,count=256]
r.NextRecord() = (rr, (000005-001.log: 0), 6022 from previous files, <nil>)
  io.ReadAll(rr) = ("0b75010000000000020000003faf62c0166a4c4efa66d3c426c1979f1ada38c0... <44-byte record>", <nil>)
  BatchHeader: [seqNum=95499,count=2]
r.NextRecord() = (rr, (000005-001.log: 55), 6022 from previous files, <nil>)
  io.ReadAll(rr) = ("0d7501000000000005000000d75a82a2d367f7b2e5ee4288d2c0d654985f68d2... <416-byte record>", <nil>)
  BatchHeader: [seqNum=95501,count=5]
r.NextRecord() = (rr, (000005-001.log: 482), 6022 from previous files, <nil>)
  io.ReadAll(rr) = ("12750100000000001d0000007575c6296b096226e5e78b9760aa7c2ecfa913b6... <199-byte record>", <nil>)
  BatchHeader: [seqNum=95506,count=29]
r.NextRecord() = (rr, (000005-001.log: 692), 6022 from previous files, pebble/record: unexpected EOF)

# Read again, this time pretending we found a third segment with the
# logNameIndex=002. This helps exercise error conditions switching to a new
# file.

read logNum=000005 forceLogNameIndexes=(002)
----
r.NextRecord() = (rr, (000005.log: 0), <nil>)
  io.ReadAll(rr) = ("f97301000000000001000000602fdb1fc7d9daaa4dd5741e5a8b07423f81d57e... <592-byte record>", <nil>)
  BatchHeader: [seqNum=95225,count=1]
r.NextRecord() = (rr, (000005.log: 603), <nil>)
  io.ReadAll(rr) = ("fa73010000000000090000000d66c9a18891d4184fbe38847d0bcb41bc8a90ad... <295-byte record>", <nil>)
  BatchHeader: [seqNum=95226,count=9]
r.NextRecord() = (rr, (000005.log: 909), <nil>)
  io.ReadAll(rr) = ("037401000000000008000000216c49c3f49c595e80076b1d6d9480cff3a8d44a... <2525-byte record>", <nil>)
  BatchHeader: [seqNum=95235,count=8]
r.NextRecord() = (rr, (000005.log: 3445), <nil>)
  io.ReadAll(rr) = ("0b7401000000000000010000313db6e445a8213e7224d87caf90dcfe6eecf25a... <2566-byte record>", <nil>)
  BatchHeader: [seqNum=95243,count=256]
r.NextRecord() = (rr, (000005-001.log: 0), 6022 from previous files, <nil>)
  io.ReadAll(rr) = ("0b75010000000000020000003faf62c0166a4c4efa66d3c426c1979f1ada38c0... <44-byte record>", <nil>)
  BatchHeader: [seqNum=95499,count=2]
r.NextRecord() = (rr, (000005-001.log: 55), 6022 from previous files, <nil>)
  io.ReadAll(rr) = ("0d7501000000000005000000d75a82a2d367f7b2e5ee4288d2c0d654985f68d2... <416-byte record>", <nil>)
  BatchHeader: [seqNum=95501,count=5]
r.NextRecord() = (rr, (000005-001.log: 482), 6022 from previous files, <nil>)
  io.ReadAll(rr) = ("12750100000000001d0000007575c6296b096226e5e78b9760aa7c2ecfa913b6... <199-byte record>", <nil>)
  BatchHeader: [seqNum=95506,count=29]
r.NextRecord() = (rr, (000005-002.log: 0), 6714 from previous files, opening WAL file segment "000005-002.log": open 000005-002.log: file does not exist)

# Test a scenario where 4 unique batches are split across three physical log
# files. The first log contains (b0, b1, b2), the second log (b1) and the third
# log (b1, b2, b3).

define logNum=000006 unclean-close
batch count=3 seq=535 size=395 sync
batch count=2 seq=538 size=93666 sync
batch count=1 seq=540 size=180 sync
----
created "000006.log"
0..406: batch #535
406..94105: batch #538
94105..94296: batch #540

define logNum=000006 logNameIndex=001 unclean-close
batch count=2 seq=538 size=93666 sync
----
created "000006-001.log"
0..93699: batch #538


define logNum=000006 logNameIndex=001 unclean-close
batch count=2 seq=538 size=93666 sync
batch count=1 seq=540 size=180 sync
batch count=5 seq=541 size=2055 sync
----
created "000006-001.log"
0..93699: batch #538
93699..93890: batch #540
93890..95956: batch #541

read logNum=000006
----
r.NextRecord() = (rr, (000006.log: 0), <nil>)
  io.ReadAll(rr) = ("17020000000000000300000080d4f05e2b4d5d702d779b34ebc6e3202c8b3680... <395-byte record>", <nil>)
  BatchHeader: [seqNum=535,count=3]
r.NextRecord() = (rr, (000006.log: 406), <nil>)
  io.ReadAll(rr) = ("1a020000000000000200000027ef83507c442f8cbb32867854dfc32ed6823042... <93666-byte record>", <nil>)
  BatchHeader: [seqNum=538,count=2]
r.NextRecord() = (rr, (000006.log: 94105), <nil>)
  io.ReadAll(rr) = ("1c0200000000000001000000f36197eb67e130dc302fed040b972901649d2813... <180-byte record>", <nil>)
  BatchHeader: [seqNum=540,count=1]
r.NextRecord() = (rr, (000006-001.log: 93890), 94296 from previous files, <nil>)
  io.ReadAll(rr) = ("1d020000000000000500000071ce0052b80db1237c9bfa873ecdba4a8cf6f94e... <2055-byte record>", <nil>)
  BatchHeader: [seqNum=541,count=5]
r.NextRecord() = (rr, (000006-001.log: 95956), 94296 from previous files, EOF)

# Test corrupting the tail of a batch that's large enough to be split into
# multiple reads. Regression test for #3865.

define logNum=000007 unclean-close
batch count=2 seq=95499 size=44 sync
batch count=5 seq=95501 size=416 sync
batch count=29 seq=95506 size=199 sync
batch count=19 seq=95535 size=45991 sync
corrupt-tail len=1020
----
created "000007.log"
0..55: batch #95499
55..482: batch #95501
482..692: batch #95506
692..46705: batch #95535
45685..46705: corrupt-tail

define logNum=000007 logNameIndex=001
batch count=19 seq=95535 size=45991 sync
batch count=19 seq=95554 size=292 sync
----
created "000007-001.log"
0..46013: batch #95535
46013..46316: batch #95554

read logNum=000007
----
r.NextRecord() = (rr, (000007.log: 0), <nil>)
  io.ReadAll(rr) = ("0b750100000000000200000012c40408ad4f401c0cf9c8bb22f284fdaba4c168... <44-byte record>", <nil>)
  BatchHeader: [seqNum=95499,count=2]
r.NextRecord() = (rr, (000007.log: 55), <nil>)
  io.ReadAll(rr) = ("0d7501000000000005000000e281b3f769f16b81bc03ae1df5036dd13742b46f... <416-byte record>", <nil>)
  BatchHeader: [seqNum=95501,count=5]
r.NextRecord() = (rr, (000007.log: 482), <nil>)
  io.ReadAll(rr) = ("12750100000000001d000000d66726e6403e80c59c6e3c71add1b77eb8b7bdd2... <199-byte record>", <nil>)
  BatchHeader: [seqNum=95506,count=29]
r.NextRecord() = (rr, (000007-001.log: 0), 692 from previous files, <nil>)
  io.ReadAll(rr) = ("2f7501000000000013000000130d8192532f4eade44dc7af7778d76fd3b28c90... <45991-byte record>", <nil>)
  BatchHeader: [seqNum=95535,count=19]
r.NextRecord() = (rr, (000007-001.log: 46013), 692 from previous files, <nil>)
  io.ReadAll(rr) = ("427501000000000013000000bb15abda06f4a71f4aeae5998fcfdb5e4dad7789... <292-byte record>", <nil>)
  BatchHeader: [seqNum=95554,count=19]
r.NextRecord() = (rr, (000007-001.log: 46316), 692 from previous files, EOF)
