diff --git a/src/allmydata/interfaces.py b/src/allmydata/interfaces.py
index 31fc61444..e495c759a 100644
--- a/src/allmydata/interfaces.py
+++ b/src/allmydata/interfaces.py
@@ -417,6 +417,7 @@ class IStorageBroker(Interface):
public attributes::
service_name: the type of service provided, like 'storage'
+ announcement_time: when we first heard about this service
last_connect_time: when we last established a connection
last_loss_time: when we last lost a connection
diff --git a/src/allmydata/storage_client.py b/src/allmydata/storage_client.py
index 81dc00427..dd9780f23 100644
--- a/src/allmydata/storage_client.py
+++ b/src/allmydata/storage_client.py
@@ -168,6 +168,7 @@ class NativeStorageServer:
the their version information. I remember information about when we were
last connected too, even if we aren't currently connected.
+ @ivar announcement_time: when we first heard about this service
@ivar last_connect_time: when we last established a connection
@ivar last_loss_time: when we last lost a connection
@@ -215,6 +216,7 @@ class NativeStorageServer:
self._long_description = tubid_s
self._short_description = tubid_s[:6]
+ self.announcement_time = time.time()
self.last_connect_time = None
self.last_loss_time = None
self.remote_host = None
@@ -265,11 +267,8 @@ class NativeStorageServer:
return self.last_connect_time
def get_last_loss_time(self):
return self.last_loss_time
- def get_last_received_data_time(self):
- if self.rref is None:
- return None
- else:
- return self.rref.getDataLastReceivedAt()
+ def get_announcement_time(self):
+ return self.announcement_time
def get_available_space(self):
version = self.get_version()
diff --git a/src/allmydata/test/common_util.py b/src/allmydata/test/common_util.py
index 47dbe59a3..e51ab8b00 100644
--- a/src/allmydata/test/common_util.py
+++ b/src/allmydata/test/common_util.py
@@ -173,24 +173,6 @@ class TestMixin(SignalMixin):
if required_to_quiesce and active:
self.fail("Reactor was still active when it was required to be quiescent.")
-
-class TimezoneMixin(object):
-
- def setTimezone(self, timezone):
- unset = object()
- originalTimezone = os.environ.get('TZ', unset)
- def restoreTimezone():
- if originalTimezone is unset:
- del os.environ['TZ']
- time.tzset()
- else:
- os.environ['TZ'] = originalTimezone
- time.tzset()
- os.environ['TZ'] = timezone
- time.tzset()
- self.addCleanup(restoreTimezone)
-
-
try:
import win32file
import win32con
diff --git a/src/allmydata/test/test_util.py b/src/allmydata/test/test_util.py
index 5fe2fbd03..adaec89f3 100644
--- a/src/allmydata/test/test_util.py
+++ b/src/allmydata/test/test_util.py
@@ -1021,40 +1021,6 @@ class TimeFormat(unittest.TestCase):
test_format_time_y2038.todo = "This test is known to fail on systems with 32-bit time_t."
- def test_format_delta(self):
- time_1 = 1389812723
- time_5s_delta = 1389812728
- time_28m7s_delta = 1389814410
- time_1h_delta = 1389816323
- time_1d21h46m49s_delta = 1389977532
-
- self.failUnlessEqual(
- time_format.format_delta(time_1, time_1), '0s')
-
- self.failUnlessEqual(
- time_format.format_delta(time_1, time_5s_delta), '5s')
- self.failUnlessEqual(
- time_format.format_delta(time_1, time_28m7s_delta), '28m 7s')
- self.failUnlessEqual(
- time_format.format_delta(time_1, time_1h_delta), '1h 0m 0s')
- self.failUnlessEqual(
- time_format.format_delta(time_1, time_1d21h46m49s_delta), '1d 21h 46m 49s')
-
- self.failUnlessEqual(
- time_format.format_delta(time_1d21h46m49s_delta, time_1), '-')
-
- # time_1 with a decimal fraction will make the delta 1s less
- time_1decimal = 1389812723.383963
-
- self.failUnlessEqual(
- time_format.format_delta(time_1decimal, time_5s_delta), '4s')
- self.failUnlessEqual(
- time_format.format_delta(time_1decimal, time_28m7s_delta), '28m 6s')
- self.failUnlessEqual(
- time_format.format_delta(time_1decimal, time_1h_delta), '59m 59s')
- self.failUnlessEqual(
- time_format.format_delta(time_1decimal, time_1d21h46m49s_delta), '1d 21h 46m 48s')
-
class CacheDir(unittest.TestCase):
def test_basic(self):
basedir = "test_util/CacheDir/test_basic"
diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index 5b151ecb6..723ae7ac6 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -172,28 +172,21 @@ class FakeHistory:
return []
class FakeDisplayableServer(StubServer):
- def __init__(self, serverid, nickname, connected,
- last_connect_time, last_loss_time, last_rx_time):
+ def __init__(self, serverid, nickname):
StubServer.__init__(self, serverid)
self.announcement = {"my-version": "allmydata-tahoe-fake",
"service-name": "storage",
"nickname": nickname}
- self.connected = connected
- self.last_loss_time = last_loss_time
- self.last_rx_time = last_rx_time
- self.last_connect_time = last_connect_time
def is_connected(self):
- return self.connected
+ return True
def get_permutation_seed(self):
return ""
def get_remote_host(self):
return ""
def get_last_loss_time(self):
- return self.last_loss_time
- def get_last_received_data_time(self):
- return self.last_rx_time
- def get_last_connect_time(self):
- return self.last_connect_time
+ return None
+ def get_announcement_time(self):
+ return None
def get_announcement(self):
return self.announcement
def get_nickname(self):
@@ -249,13 +242,7 @@ class FakeClient(Client):
self.storage_broker = StorageFarmBroker(None, permute_peers=True)
# fake knowledge of another server
self.storage_broker.test_add_server("other_nodeid",
- FakeDisplayableServer(
- serverid="other_nodeid", nickname=u"other_nickname \u263B", connected = True,
- last_connect_time = 10, last_loss_time = 20, last_rx_time = 30))
- self.storage_broker.test_add_server("disconnected_nodeid",
- FakeDisplayableServer(
- serverid="other_nodeid", nickname=u"disconnected_nickname \u263B", connected = False,
- last_connect_time = 15, last_loss_time = 25, last_rx_time = 35))
+ FakeDisplayableServer("other_nodeid", u"other_nickname \u263B"))
self.introducer_client = None
self.history = FakeHistory()
self.uploader = FakeUploader()
@@ -281,16 +268,14 @@ class FakeClient(Client):
MUTABLE_SIZELIMIT = FakeMutableFileNode.MUTABLE_SIZELIMIT
-class WebMixin(testutil.TimezoneMixin):
+class WebMixin(object):
def setUp(self):
- self.setTimezone('UTC-13:00')
self.s = FakeClient()
self.s.startService()
self.staticdir = self.mktemp()
self.clock = Clock()
- self.fakeTime = 86460 # 1d 0h 1m 0s
self.ws = webish.WebishServer(self.s, "0", staticdir=self.staticdir,
- clock=self.clock, now_fn=lambda:self.fakeTime)
+ clock=self.clock)
self.ws.setServiceParent(self.s)
self.webish_port = self.ws.getPortnum()
self.webish_url = self.ws.getURL()
@@ -616,6 +601,7 @@ class WebMixin(testutil.TimezoneMixin):
self.fail("%s was supposed to Error(302), not get '%s'" %
(which, res))
+
class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixin, unittest.TestCase):
def test_create(self):
pass
@@ -633,11 +619,6 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
res_u = res.decode('utf-8')
self.failUnlessIn(u'
fake_nickname \u263A | ', res_u)
self.failUnlessIn(u'other_nickname \u263B
', res_u)
- self.failUnlessIn(u'Connected to 1\n of 2 known storage servers', res_u)
- self.failUnlessIn(u'\n 1d\u00A00h\u00A00m\u00A050s', res_u)
- self.failUnlessIn(u'\n 1d\u00A00h\u00A00m\u00A035s', res_u)
- self.failUnlessIn(u'1d\u00A00h\u00A00m\u00A030s | ', res_u)
- self.failUnlessIn(u'1d\u00A00h\u00A00m\u00A025s | ', res_u)
self.failUnlessIn(u'\u00A9 Tahoe-LAFS Software Foundation', res_u)
self.failUnlessIn('Available | ', res)
self.failUnlessIn('123.5kB', res)
diff --git a/src/allmydata/util/time_format.py b/src/allmydata/util/time_format.py
index a6fe3ec72..c481adc37 100644
--- a/src/allmydata/util/time_format.py
+++ b/src/allmydata/util/time_format.py
@@ -66,27 +66,3 @@ def parse_date(s):
# day
return int(iso_utc_time_to_seconds(s + "T00:00:00"))
-def format_delta(time_1, time_2):
- if time_1 is None:
- return "N/A"
- if time_1 > time_2:
- return '-'
- delta = int(time_2 - time_1)
- seconds = delta % 60
- delta -= seconds
- minutes = (delta / 60) % 60
- delta -= minutes * 60
- hours = delta / (60*60) % 24
- delta -= hours * 24
- days = delta / (24*60*60)
- if not days:
- if not hours:
- if not minutes:
- return "%ss" % (seconds)
- else:
- return "%sm %ss" % (minutes, seconds)
- else:
- return "%sh %sm %ss" % (hours, minutes, seconds)
- else:
- return "%sd %sh %sm %ss" % (days, hours, minutes, seconds)
-
diff --git a/src/allmydata/web/common.py b/src/allmydata/web/common.py
index 5cfe84d9a..b8e6d5b44 100644
--- a/src/allmydata/web/common.py
+++ b/src/allmydata/web/common.py
@@ -15,7 +15,7 @@ from allmydata.interfaces import ExistingChildError, NoSuchChildError, \
MustBeReadonlyError, MustNotBeUnknownRWError, SDMF_VERSION, MDMF_VERSION
from allmydata.mutable.common import UnrecoverableFileError
from allmydata.util import abbreviate
-from allmydata.util.time_format import format_time, format_delta
+from allmydata.util.time_format import format_time
from allmydata.util.encodingutil import to_str, quote_output
@@ -213,15 +213,9 @@ def text_plain(text, ctx):
def spaces_to_nbsp(text):
return unicode(text).replace(u' ', u'\u00A0')
-def render_time_delta(time_1, time_2):
- return spaces_to_nbsp(format_delta(time_1, time_2))
-
def render_time(t):
return spaces_to_nbsp(format_time(time.localtime(t)))
-def render_time_attr(t):
- return format_time(time.localtime(t))
-
class WebError(Exception):
def __init__(self, text, code=http.BAD_REQUEST):
self.text = text
diff --git a/src/allmydata/web/root.py b/src/allmydata/web/root.py
index d8d789cf3..c46a6dd5f 100644
--- a/src/allmydata/web/root.py
+++ b/src/allmydata/web/root.py
@@ -14,7 +14,7 @@ from allmydata.interfaces import IFileNode
from allmydata.web import filenode, directory, unlinked, status, operations
from allmydata.web import storage
from allmydata.web.common import abbreviate_size, getxmlfile, WebError, \
- get_arg, RenderMixin, get_format, get_mutable_type, render_time_delta, render_time, render_time_attr
+ get_arg, RenderMixin, get_format, get_mutable_type, render_time
class URIHandler(RenderMixin, rend.Page):
@@ -138,13 +138,12 @@ class Root(rend.Page):
"no": "Disconnected",
}
- def __init__(self, client, clock=None, now_fn=None):
+ def __init__(self, client, clock=None):
rend.Page.__init__(self, client)
self.client = client
# If set, clock is a twisted.internet.task.Clock that the tests
# use to test ophandle expiration.
self.child_operations = operations.OphandleTable(clock)
- self.now_fn = now_fn
try:
s = client.getServiceNamed("storage")
except KeyError:
@@ -283,7 +282,7 @@ class Root(rend.Page):
ctx.fillSlots("peerid", server.get_longname())
ctx.fillSlots("nickname", server.get_nickname())
rhost = server.get_remote_host()
- if server.is_connected():
+ if rhost:
if nodeid == self.client.nodeid:
rhost_s = "(loopback)"
elif isinstance(rhost, address.IPv4Address):
@@ -291,37 +290,29 @@ class Root(rend.Page):
else:
rhost_s = str(rhost)
addr = rhost_s
- service_connection_status = "yes"
- last_connect_time = server.get_last_connect_time()
- service_connection_status_rel_time = render_time_delta(last_connect_time, self.now_fn())
- service_connection_status_abs_time = render_time_attr(last_connect_time)
+ connected = "yes"
+ since = server.get_last_connect_time()
else:
addr = "N/A"
- service_connection_status = "no"
- last_loss_time = server.get_last_loss_time()
- service_connection_status_rel_time = render_time_delta(last_loss_time, self.now_fn())
- service_connection_status_abs_time = render_time_attr(last_loss_time)
-
- last_received_data_time = server.get_last_received_data_time()
- last_received_data_rel_time = render_time_delta(last_received_data_time, self.now_fn())
- last_received_data_abs_time = render_time_attr(last_received_data_time)
-
+ connected = "no"
+ since = server.get_last_loss_time()
+ announced = server.get_announcement_time()
announcement = server.get_announcement()
version = announcement["my-version"]
+ service_name = announcement["service-name"]
available_space = server.get_available_space()
if available_space is None:
available_space = "N/A"
else:
available_space = abbreviate_size(available_space)
ctx.fillSlots("address", addr)
- ctx.fillSlots("service_connection_status", service_connection_status)
- ctx.fillSlots("service_connection_status_alt", self._connectedalts[service_connection_status])
+ ctx.fillSlots("connected", connected)
+ ctx.fillSlots("connected_alt", self._connectedalts[connected])
ctx.fillSlots("connected-bool", bool(rhost))
- ctx.fillSlots("service_connection_status_abs_time", service_connection_status_abs_time)
- ctx.fillSlots("service_connection_status_rel_time", service_connection_status_rel_time)
- ctx.fillSlots("last_received_data_abs_time", last_received_data_abs_time)
- ctx.fillSlots("last_received_data_rel_time", last_received_data_rel_time)
+ ctx.fillSlots("since", render_time(since))
+ ctx.fillSlots("announced", render_time(announced))
ctx.fillSlots("version", version)
+ ctx.fillSlots("service_name", service_name)
ctx.fillSlots("available_space", available_space)
return ctx.tag
diff --git a/src/allmydata/web/static/css/new-tahoe.css b/src/allmydata/web/static/css/new-tahoe.css
index 8ab7f47d6..175c3e337 100644
--- a/src/allmydata/web/static/css/new-tahoe.css
+++ b/src/allmydata/web/static/css/new-tahoe.css
@@ -77,12 +77,3 @@ body {
float: left;
margin: 5px;
}
-
-.nickname-and-peerid .timestamp {
- float: right;
-}
-
-a.timestamp {
- color: inherit;
- text-decoration:none;
-}
diff --git a/src/allmydata/web/welcome.xhtml b/src/allmydata/web/welcome.xhtml
index ca2387672..3e23fc736 100644
--- a/src/allmydata/web/welcome.xhtml
+++ b/src/allmydata/web/welcome.xhtml
@@ -1,5 +1,4 @@
-
+
@@ -170,24 +169,27 @@
Nickname |
Address |
- Last RX |
+ Service |
+ Since |
+ Announced |
Version |
Available |
- img/connected-.png
-
+ img/connected-.png
|
|
- |
+ |
+ |
+ |
|
|
- You are not presently connected to any peers |
+ You are not presently connected to any peers |
diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py
index b26b34da3..e2029feec 100644
--- a/src/allmydata/webish.py
+++ b/src/allmydata/webish.py
@@ -129,14 +129,14 @@ class WebishServer(service.MultiService):
name = "webish"
def __init__(self, client, webport, nodeurl_path=None, staticdir=None,
- clock=None, now_fn=time.time):
+ clock=None):
service.MultiService.__init__(self)
# the 'data' argument to all render() methods default to the Client
# the 'clock' argument to root.Root is, if set, a
# twisted.internet.task.Clock that is provided by the unit tests
# so that they can test features that involve the passage of
# time in a deterministic manner.
- self.root = root.Root(client, clock, now_fn)
+ self.root = root.Root(client, clock)
self.buildServer(webport, nodeurl_path, staticdir)
if self.root.child_operations:
self.site.remember(self.root.child_operations, IOpHandleTable)