Skip to content

Commit

Permalink
download_metadata(): fix off-by-one error
Browse files Browse the repository at this point in the history
If the block starts after the end of the file, we don't need to download it.
  • Loading branch information
Nikratio committed Jul 21, 2023
1 parent 5b410fe commit ea9d640
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/s3ql/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ def download_metadata(
with open(db_file, 'w+b', buffering=0) as fh:
for (blockno, candidates) in block_list.items():
off = blockno * blocksize
if off > file_size and not failsafe:
if off >= file_size and not failsafe:
log.debug('download_metadata: skipping obsolete block %d', blockno)
continue
try:
Expand Down Expand Up @@ -551,6 +551,8 @@ def first_le_than(l: List[int], threshold: int):
if e <= threshold:
return e

raise ValueError('No element below %d in list of length %d' % (threshold, len(l)))


def get_available_seq_nos(backend: AbstractBackend) -> List[int]:
nos = []
Expand Down
31 changes: 31 additions & 0 deletions tests/t1_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,3 +343,34 @@ def test_expiration_downup(backend):
[None, 40, None], # block 3
]
_test_expiration(backend, contents_pre, contents_post, db_sizes=db_sizes, versions_to_keep=3)


@pytest.mark.parametrize("incremental", (True, False))
def test_download_shorter(backend, incremental):
# Test downloading older snapshot when the filesize has grown
sqlite3ext.reset()
params = FsAttributes(
metadata_block_size=BLOCKSIZE,
data_block_size=BLOCKSIZE,
seq_no=1,
)
with tempfile.NamedTemporaryFile() as tmpfh:
db = Connection(tmpfh.name, BLOCKSIZE)
db.execute("CREATE TABLE foo (id INT, data BLOB);")
for i in range(2):
db.execute("INSERT INTO foo VALUES(?, ?)", (i, DUMMY_DATA))

db.checkpoint()
upload_metadata(backend, db, params, incremental=incremental)
old_params = params.copy()
params.seq_no += 1

# Grow database
for i in range(2, 6):
db.execute("INSERT INTO foo VALUES(?, ?)", (i, DUMMY_DATA))
db.checkpoint()
upload_metadata(backend, db, params)
db.close()

with tempfile.NamedTemporaryFile() as tmpfh:
download_metadata(backend, tmpfh.name, old_params)

0 comments on commit ea9d640

Please sign in to comment.