add a way to turn off implicit bucket lease renewal too

This commit is contained in:
Jean-Paul Calderone 2021-11-10 16:08:40 -05:00
parent 7faec6e5a0
commit 9af81d21c5
2 changed files with 98 additions and 11 deletions

View File

@ -57,9 +57,23 @@ DEFAULT_RENEWAL_TIME = 31 * 24 * 60 * 60
@implementer(RIStorageServer, IStatsProducer)
class StorageServer(service.MultiService, Referenceable):
"""
A filesystem-based implementation of ``RIStorageServer``.
:ivar bool _implicit_bucket_lease_renewal: If and only if this is ``True``
then ``allocate_buckets`` will renew leases on existing shares
associated with the storage index it operates on.
:ivar bool _implicit_slot_lease_renewal: If and only if this is ``True``
then ``slot_testv_and_readv_and_writev`` will renew leases on shares
associated with the slot it operates on.
"""
name = 'storage'
LeaseCheckerClass = LeaseCheckingCrawler
_implicit_bucket_lease_renewal = True
_implicit_slot_lease_renewal = True
def __init__(self, storedir, nodeid, reserved_space=0,
discard_storage=False, readonly_storage=False,
stats_provider=None,
@ -135,6 +149,29 @@ class StorageServer(service.MultiService, Referenceable):
def __repr__(self):
return "<StorageServer %s>" % (idlib.shortnodeid_b2a(self.my_nodeid),)
def set_implicit_bucket_lease_renewal(self, enabled):
# type: (bool) -> None
"""
Control the behavior of implicit lease renewal by *allocate_buckets*.
:param enabled: If and only if ``True`` then future *allocate_buckets*
calls will renew leases on shares that already exist in the bucket.
"""
self._implicit_bucket_lease_renewal = enabled
def set_implicit_slot_lease_renewal(self, enabled):
# type: (bool) -> None
"""
Control the behavior of implicit lease renewal by
*slot_testv_and_readv_and_writev*.
:param enabled: If and only if ``True`` then future
*slot_testv_and_readv_and_writev* calls will renew leases on
shares that still exist in the slot after the writev is applied
and which were touched by the writev.
"""
self._implicit_slot_lease_renewal = enabled
def have_shares(self):
# quick test to decide if we need to commit to an implicit
# permutation-seed or if we should use a new one
@ -319,6 +356,7 @@ class StorageServer(service.MultiService, Referenceable):
# file, they'll want us to hold leases for this file.
for (shnum, fn) in self._get_bucket_shares(storage_index):
alreadygot.add(shnum)
if self._implicit_bucket_lease_renewal:
sf = ShareFile(fn)
sf.add_or_renew_lease(lease_info)
@ -625,15 +663,10 @@ class StorageServer(service.MultiService, Referenceable):
secrets,
test_and_write_vectors,
read_vector,
renew_leases,
):
"""
Read data from shares and conditionally write some data to them.
:param bool renew_leases: If and only if this is ``True`` and the test
vectors pass then shares in this slot will also have an updated
lease applied to them.
See ``allmydata.interfaces.RIStorageServer`` for details about other
parameters and return value.
"""
@ -673,7 +706,7 @@ class StorageServer(service.MultiService, Referenceable):
test_and_write_vectors,
shares,
)
if renew_leases:
if self._implicit_slot_lease_renewal:
lease_info = self._make_lease_info(renew_secret, cancel_secret)
self._add_or_renew_leases(remaining_shares, lease_info)
@ -690,7 +723,6 @@ class StorageServer(service.MultiService, Referenceable):
secrets,
test_and_write_vectors,
read_vector,
renew_leases=True,
)
def _allocate_slot_share(self, bucketdir, secrets, sharenum,

View File

@ -608,6 +608,61 @@ class Server(unittest.TestCase):
for i,wb in writers.items():
wb.remote_abort()
def test_allocate_without_lease_renewal(self):
"""
``remote_allocate_buckets`` does not renew leases on existing shares if
``set_implicit_bucket_lease_renewal(False)`` is called first.
"""
first_lease = 456
second_lease = 543
storage_index = b"allocate"
clock = Clock()
clock.advance(first_lease)
ss = self.create(
"test_allocate_without_lease_renewal",
get_current_time=clock.seconds,
)
ss.set_implicit_bucket_lease_renewal(False)
# Put a share on there
already, writers = self.allocate(ss, storage_index, [0], 1)
(writer,) = writers.values()
writer.remote_write(0, b"x")
writer.remote_close()
# It should have a lease granted at the current time.
shares = dict(ss._get_bucket_shares(storage_index))
self.assertEqual(
[first_lease],
list(
lease.get_grant_renew_time_time()
for lease
in ShareFile(shares[0]).get_leases()
),
)
# Let some time pass so we can tell if the lease on share 0 is
# renewed.
clock.advance(second_lease)
# Put another share on there.
already, writers = self.allocate(ss, storage_index, [1], 1)
(writer,) = writers.values()
writer.remote_write(0, b"x")
writer.remote_close()
# The first share's lease expiration time is unchanged.
shares = dict(ss._get_bucket_shares(storage_index))
self.assertEqual(
[first_lease],
list(
lease.get_grant_renew_time_time()
for lease
in ShareFile(shares[0]).get_leases()
),
)
def test_bad_container_version(self):
ss = self.create("test_bad_container_version")
a,w = self.allocate(ss, b"si1", [0], 10)
@ -1408,9 +1463,10 @@ class MutableServer(unittest.TestCase):
def test_writev_without_renew_lease(self):
"""
The helper method ``slot_testv_and_readv_and_writev`` does not renew
leases if ``False`` is passed for the ``renew_leases`` parameter.
leases if ``set_implicit_bucket_lease_renewal(False)`` is called first.
"""
ss = self.create("test_writev_without_renew_lease")
ss.set_implicit_slot_lease_renewal(False)
storage_index = b"si2"
secrets = (
@ -1429,7 +1485,6 @@ class MutableServer(unittest.TestCase):
sharenum: ([], datav, None),
},
read_vector=[],
renew_leases=False,
)
leases = list(ss.get_slot_leases(storage_index))
self.assertEqual([], leases)