mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-20 17:52:50 +00:00
expirer: change setup, config options, in preparation for adding tahoe.cfg controls
This commit is contained in:
parent
fffab0d724
commit
8eaee28550
@ -49,19 +49,25 @@ class LeaseCheckingCrawler(ShareCrawler):
|
||||
minimum_cycle_time = 12*60*60 # not more than twice per day
|
||||
|
||||
def __init__(self, server, statefile, historyfile,
|
||||
expiration_enabled, expiration_mode):
|
||||
expiration_enabled, mode,
|
||||
override_lease_duration, # used if expiration_mode=="age"
|
||||
date_cutoff, # used if expiration_mode=="date-cutoff"
|
||||
sharetypes):
|
||||
self.historyfile = historyfile
|
||||
self.expiration_enabled = expiration_enabled
|
||||
self.mode = expiration_mode
|
||||
if self.mode[0] not in ("age", "date-cutoff"):
|
||||
raise ValueError("garbage-collection mode '%s' must be 'age' or 'date-cutoff'" % self.mode[0])
|
||||
if self.mode[0] == "age":
|
||||
assert isinstance(expiration_mode[1], int) # seconds
|
||||
elif self.mode[0] == "date-cutoff":
|
||||
assert isinstance(expiration_mode[1], int) # seconds-since-epoch
|
||||
self.sharetypes_to_expire = ("mutable", "immutable")
|
||||
if len(self.mode) > 2:
|
||||
self.sharetypes_to_expire = self.mode[2]
|
||||
self.mode = mode
|
||||
self.override_lease_duration = None
|
||||
self.date_cutoff = None
|
||||
if self.mode == "age":
|
||||
assert isinstance(override_lease_duration, (int, type(None)))
|
||||
self.override_lease_duration = override_lease_duration # seconds
|
||||
elif self.mode == "date-cutoff":
|
||||
assert isinstance(date_cutoff, int) # seconds-since-epoch
|
||||
assert date_cutoff is not None
|
||||
self.date_cutoff = date_cutoff
|
||||
else:
|
||||
raise ValueError("GC mode '%s' must be 'age' or 'date-cutoff'" % mode)
|
||||
self.sharetypes_to_expire = sharetypes
|
||||
ShareCrawler.__init__(self, server, statefile)
|
||||
|
||||
def add_initial_state(self):
|
||||
@ -179,14 +185,15 @@ class LeaseCheckingCrawler(ShareCrawler):
|
||||
|
||||
# expired-or-not according to our configured age limit
|
||||
expired = False
|
||||
if self.mode[0] == "age":
|
||||
age_limit = self.mode[1]
|
||||
if self.mode == "age":
|
||||
age_limit = original_expiration_time
|
||||
if self.override_lease_duration is not None:
|
||||
age_limit = self.override_lease_duration
|
||||
if age > age_limit:
|
||||
expired = True
|
||||
else:
|
||||
assert self.mode[0] == "date-cutoff"
|
||||
date_cutoff = self.mode[1]
|
||||
if grant_renew_time < date_cutoff:
|
||||
assert self.mode == "date-cutoff"
|
||||
if grant_renew_time < self.date_cutoff:
|
||||
expired = True
|
||||
if sharetype not in self.sharetypes_to_expire:
|
||||
expired = False
|
||||
@ -269,7 +276,10 @@ class LeaseCheckingCrawler(ShareCrawler):
|
||||
now = time.time()
|
||||
h["cycle-start-finish-times"] = (start, now)
|
||||
h["expiration-enabled"] = self.expiration_enabled
|
||||
h["configured-expiration-mode"] = self.mode
|
||||
h["configured-expiration-mode"] = (self.mode,
|
||||
self.override_lease_duration,
|
||||
self.date_cutoff,
|
||||
self.sharetypes_to_expire)
|
||||
|
||||
s = self.state["cycle-to-date"]
|
||||
|
||||
@ -376,7 +386,10 @@ class LeaseCheckingCrawler(ShareCrawler):
|
||||
lah = so_far["lease-age-histogram"]
|
||||
so_far["lease-age-histogram"] = self.convert_lease_age_histogram(lah)
|
||||
so_far["expiration-enabled"] = self.expiration_enabled
|
||||
so_far["configured-expiration-mode"] = self.mode
|
||||
so_far["configured-expiration-mode"] = (self.mode,
|
||||
self.override_lease_duration,
|
||||
self.date_cutoff,
|
||||
self.sharetypes_to_expire)
|
||||
|
||||
so_far_sr = so_far["space-recovered"]
|
||||
remaining_sr = {}
|
||||
|
@ -41,7 +41,10 @@ class StorageServer(service.MultiService, Referenceable):
|
||||
discard_storage=False, readonly_storage=False,
|
||||
stats_provider=None,
|
||||
expiration_enabled=False,
|
||||
expiration_mode=("age", 31*24*60*60)):
|
||||
expiration_mode="age",
|
||||
expiration_override_lease_duration=None,
|
||||
expiration_date_cutoff=None,
|
||||
expiration_sharetypes=("mutable", "immutable")):
|
||||
service.MultiService.__init__(self)
|
||||
assert isinstance(nodeid, str)
|
||||
assert len(nodeid) == 20
|
||||
@ -82,22 +85,22 @@ class StorageServer(service.MultiService, Referenceable):
|
||||
"cancel": [],
|
||||
}
|
||||
self.add_bucket_counter()
|
||||
self.add_lease_checker(expiration_enabled, expiration_mode)
|
||||
|
||||
statefile = os.path.join(self.storedir, "lease_checker.state")
|
||||
historyfile = os.path.join(self.storedir, "lease_checker.history")
|
||||
klass = self.LeaseCheckerClass
|
||||
self.lease_checker = klass(self, statefile, historyfile,
|
||||
expiration_enabled, expiration_mode,
|
||||
expiration_override_lease_duration,
|
||||
expiration_date_cutoff,
|
||||
expiration_sharetypes)
|
||||
self.lease_checker.setServiceParent(self)
|
||||
|
||||
def add_bucket_counter(self):
|
||||
statefile = os.path.join(self.storedir, "bucket_counter.state")
|
||||
self.bucket_counter = BucketCountingCrawler(self, statefile)
|
||||
self.bucket_counter.setServiceParent(self)
|
||||
|
||||
def add_lease_checker(self, expiration_enabled, expiration_mode):
|
||||
statefile = os.path.join(self.storedir, "lease_checker.state")
|
||||
historyfile = os.path.join(self.storedir, "lease_checker.history")
|
||||
klass = self.LeaseCheckerClass
|
||||
self.lease_checker = klass(self, statefile, historyfile,
|
||||
expiration_enabled=expiration_enabled,
|
||||
expiration_mode=expiration_mode)
|
||||
self.lease_checker.setServiceParent(self)
|
||||
|
||||
def count(self, name, delta=1):
|
||||
if self.stats_provider:
|
||||
self.stats_provider.count("storage_server." + name, delta)
|
||||
|
@ -1753,7 +1753,8 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
# than 2000s old will be expired.
|
||||
ss = InstrumentedStorageServer(basedir, "\x00" * 20,
|
||||
expiration_enabled=True,
|
||||
expiration_mode=("age",2000))
|
||||
expiration_mode="age",
|
||||
expiration_override_lease_duration=2000)
|
||||
# make it start sooner than usual.
|
||||
lc = ss.lease_checker
|
||||
lc.slow_start = 0
|
||||
@ -1845,7 +1846,8 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
last = s["history"][0]
|
||||
|
||||
self.failUnlessEqual(last["expiration-enabled"], True)
|
||||
self.failUnlessEqual(last["configured-expiration-mode"], ("age",2000))
|
||||
self.failUnlessEqual(last["configured-expiration-mode"],
|
||||
("age", 2000, None, ("mutable", "immutable")))
|
||||
self.failUnlessEqual(last["leases-per-share-histogram"], {1: 2, 2: 2})
|
||||
|
||||
rec = last["space-recovered"]
|
||||
@ -1874,7 +1876,7 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
def _check_html(html):
|
||||
s = remove_tags(html)
|
||||
self.failUnlessIn("Expiration Enabled: expired leases will be removed", s)
|
||||
self.failUnlessIn("leases created or last renewed more than 33 minutes ago will be considered expired", s)
|
||||
self.failUnlessIn("Leases created or last renewed more than 33 minutes ago will be considered expired.", s)
|
||||
self.failUnlessIn(" recovered: 2 shares, 2 buckets (1 mutable / 1 immutable), ", s)
|
||||
d.addCallback(_check_html)
|
||||
return d
|
||||
@ -1888,7 +1890,8 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
then = int(now - 2000)
|
||||
ss = InstrumentedStorageServer(basedir, "\x00" * 20,
|
||||
expiration_enabled=True,
|
||||
expiration_mode=("date-cutoff",then))
|
||||
expiration_mode="date-cutoff",
|
||||
expiration_date_cutoff=then)
|
||||
# make it start sooner than usual.
|
||||
lc = ss.lease_checker
|
||||
lc.slow_start = 0
|
||||
@ -1985,7 +1988,8 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
|
||||
self.failUnlessEqual(last["expiration-enabled"], True)
|
||||
self.failUnlessEqual(last["configured-expiration-mode"],
|
||||
("date-cutoff",then))
|
||||
("date-cutoff", None, then,
|
||||
("mutable", "immutable")))
|
||||
self.failUnlessEqual(last["leases-per-share-histogram"],
|
||||
{1: 2, 2: 2})
|
||||
|
||||
@ -2017,8 +2021,8 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
self.failUnlessIn("Expiration Enabled:"
|
||||
" expired leases will be removed", s)
|
||||
date = time.strftime("%d-%b-%Y", time.gmtime(then))
|
||||
self.failUnlessIn("leases created or last renewed before %s"
|
||||
" will be considered expired" % date, s)
|
||||
self.failUnlessIn("Leases created or last renewed before %s"
|
||||
" will be considered expired." % date, s)
|
||||
self.failUnlessIn(" recovered: 2 shares, 2 buckets (1 mutable / 1 immutable), ", s)
|
||||
d.addCallback(_check_html)
|
||||
return d
|
||||
@ -2030,8 +2034,9 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
then = int(now - 2000)
|
||||
ss = StorageServer(basedir, "\x00" * 20,
|
||||
expiration_enabled=True,
|
||||
expiration_mode=("date-cutoff",
|
||||
then, ("immutable",)))
|
||||
expiration_mode="date-cutoff",
|
||||
expiration_date_cutoff=then,
|
||||
expiration_sharetypes=("immutable",))
|
||||
lc = ss.lease_checker
|
||||
lc.slow_start = 0
|
||||
webstatus = StorageStatus(ss)
|
||||
@ -2075,7 +2080,7 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
d.addCallback(lambda ign: self.render1(webstatus))
|
||||
def _check_html(html):
|
||||
s = remove_tags(html)
|
||||
self.failUnlessIn("only the following sharetypes will be expired: immutable Next crawl", s)
|
||||
self.failUnlessIn("The following sharetypes will be expired: immutable.", s)
|
||||
d.addCallback(_check_html)
|
||||
return d
|
||||
|
||||
@ -2086,8 +2091,9 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
then = int(now - 2000)
|
||||
ss = StorageServer(basedir, "\x00" * 20,
|
||||
expiration_enabled=True,
|
||||
expiration_mode=("date-cutoff",
|
||||
then, ("mutable",)))
|
||||
expiration_mode="date-cutoff",
|
||||
expiration_date_cutoff=then,
|
||||
expiration_sharetypes=("mutable",))
|
||||
lc = ss.lease_checker
|
||||
lc.slow_start = 0
|
||||
webstatus = StorageStatus(ss)
|
||||
@ -2131,7 +2137,7 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
d.addCallback(lambda ign: self.render1(webstatus))
|
||||
def _check_html(html):
|
||||
s = remove_tags(html)
|
||||
self.failUnlessIn("only the following sharetypes will be expired: mutable Next crawl", s)
|
||||
self.failUnlessIn("The following sharetypes will be expired: mutable.", s)
|
||||
d.addCallback(_check_html)
|
||||
return d
|
||||
|
||||
@ -2140,9 +2146,8 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
fileutil.make_dirs(basedir)
|
||||
e = self.failUnlessRaises(ValueError,
|
||||
StorageServer, basedir, "\x00" * 20,
|
||||
expiration_mode=("bogus", 0))
|
||||
self.failUnless("garbage-collection mode 'bogus'"
|
||||
" must be 'age' or 'date-cutoff'" in str(e), str(e))
|
||||
expiration_mode="bogus")
|
||||
self.failUnless("GC mode 'bogus' must be 'age' or 'date-cutoff'" in str(e), str(e))
|
||||
|
||||
def test_parse_duration(self):
|
||||
DAY = 24*60*60
|
||||
@ -2254,7 +2259,8 @@ class LeaseCrawler(unittest.TestCase, pollmixin.PollMixin, WebRenderingMixin):
|
||||
basedir = "storage/LeaseCrawler/no_st_blocks"
|
||||
fileutil.make_dirs(basedir)
|
||||
ss = No_ST_BLOCKS_StorageServer(basedir, "\x00" * 20,
|
||||
expiration_mode=("age",-1000))
|
||||
expiration_mode="age",
|
||||
expiration_override_lease_duration=-1000)
|
||||
# a negative expiration_time= means the "configured-"
|
||||
# space-recovered counts will be non-zero, since all shares will have
|
||||
# expired by then
|
||||
|
@ -128,19 +128,23 @@ class StorageStatus(rend.Page):
|
||||
return ctx.tag["Disabled: scan-only mode, no leases will be removed"]
|
||||
|
||||
def render_lease_expiration_mode(self, ctx, data):
|
||||
mode = self.storage.lease_checker.mode
|
||||
if mode[0] == "age":
|
||||
ctx.tag["leases created or last renewed more than %s ago "
|
||||
"will be considered expired"
|
||||
% abbreviate_time(mode[1])]
|
||||
lc = self.storage.lease_checker
|
||||
if lc.mode == "age":
|
||||
if lc.override_lease_duration is None:
|
||||
ctx.tag["Leases will expire naturally, probably 31 days after "
|
||||
"creation or renewal."]
|
||||
else:
|
||||
ctx.tag["Leases created or last renewed more than %s ago "
|
||||
"will be considered expired."
|
||||
% abbreviate_time(lc.override_lease_duration)]
|
||||
else:
|
||||
assert mode[0] == "date-cutoff"
|
||||
date = time.strftime("%d-%b-%Y", time.gmtime(mode[1]))
|
||||
ctx.tag["leases created or last renewed before %s "
|
||||
"will be considered expired" % date]
|
||||
if len(mode) > 2:
|
||||
ctx.tag[", and only the following sharetypes will be expired: ",
|
||||
sorted(mode[2])]
|
||||
assert lc.mode == "date-cutoff"
|
||||
date = time.strftime("%d-%b-%Y", time.gmtime(lc.date_cutoff))
|
||||
ctx.tag["Leases created or last renewed before %s "
|
||||
"will be considered expired." % date]
|
||||
if len(lc.mode) > 2:
|
||||
ctx.tag[" The following sharetypes will be expired: ",
|
||||
sorted(lc.sharetypes_to_expire), "."]
|
||||
return ctx.tag
|
||||
|
||||
def format_recovered(self, sr, a):
|
||||
|
Loading…
x
Reference in New Issue
Block a user