Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2013-03-24 17:17:42 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2013-03-24 17:17:42 (GMT)
commita978a14bae22d7322196a73bf2e5bfff69a971ea (patch)
treebbdaf11ab0ab4f5d9302f5d83715d5c3e71c9562
parent7f66d8739502a6c959d0db05990b7f2f74fa36ee (diff)
Sync local contexts only on changes
-rwxr-xr-xsugar-network-client4
-rw-r--r--sugar_network/client/clones.py46
-rw-r--r--sugar_network/client/commands.py11
-rwxr-xr-xtests/units/client/clones.py64
-rwxr-xr-xtests/units/client/online_commands.py50
5 files changed, 93 insertions, 82 deletions
diff --git a/sugar-network-client b/sugar-network-client
index b8d8437..bad15da 100755
--- a/sugar-network-client
+++ b/sugar-network-client
@@ -72,7 +72,7 @@ class Application(application.Daemon):
volume = Volume(client.path('db'))
try:
- ClientCommands(volume).populate()
+ volume.populate()
clones.populate(volume['context'], client.activity_dirs.value)
finally:
volume.close()
@@ -119,7 +119,7 @@ class Application(application.Daemon):
self.accept()
def final_start():
- commands.populate()
+ volume.populate()
self.jobs.spawn(clones.monitor, volume['context'],
client.activity_dirs.value)
diff --git a/sugar_network/client/clones.py b/sugar_network/client/clones.py
index aedeb0f..ad78cc7 100644
--- a/sugar_network/client/clones.py
+++ b/sugar_network/client/clones.py
@@ -21,6 +21,7 @@ import logging
from os.path import join, exists, lexists, relpath, dirname, basename, isdir
from os.path import abspath, islink
+from sugar_network import db
from sugar_network.client.spec import Spec
from sugar_network.toolkit.inotify import Inotify, \
IN_DELETE_SELF, IN_CREATE, IN_DELETE, IN_CLOSE_WRITE, \
@@ -43,24 +44,6 @@ def walk(context):
yield os.readlink(path)
-def ensure_clones(context):
- root = _context_path(context, '')
- if not exists(root):
- return False
-
- found = False
-
- for filename in os.listdir(root):
- path = join(root, filename)
- if lexists(path):
- if not exists(path):
- os.unlink(path)
- else:
- found = True
-
- return found
-
-
def wipeout(context):
for path in walk(context):
_logger.info('Wipe out %r implementation from %r', context, path)
@@ -98,9 +81,12 @@ class _Inotify(Inotify):
self._mime_dir = join(xdg_data_home, 'mime')
def setup(self, paths):
+ mtime = 0
for path in paths:
path = abspath(path)
- if not exists(path):
+ if exists(path):
+ mtime = max(mtime, os.stat(path).st_mtime)
+ else:
if not os.access(dirname(path), os.W_OK):
_logger.warning('No permissions to create %s '
'directory, do not monitor it', path)
@@ -108,6 +94,28 @@ class _Inotify(Inotify):
os.makedirs(path)
self._roots.append(_Root(self, path))
+ if mtime <= self._contexts.mtime:
+ return
+
+ docs, __ = self._contexts.find(limit=db.MAX_LIMIT, clone=[1, 2])
+ for context in docs:
+ root = _context_path(context.guid, '')
+ found = False
+ if exists(root):
+ for filename in os.listdir(root):
+ path = join(root, filename)
+ if lexists(path):
+ if not exists(path):
+ os.unlink(path)
+ else:
+ found = True
+ break
+ if found:
+ if context['clone'] != 2:
+ self._contexts.update(context.guid, clone=2)
+ else:
+ self._contexts.update(context.guid, clone=0)
+
def serve_forever(self):
while True:
coroutine.select([self.fileno()], [], [])
diff --git a/sugar_network/client/commands.py b/sugar_network/client/commands.py
index a6f2eaa..b7ffc33 100644
--- a/sugar_network/client/commands.py
+++ b/sugar_network/client/commands.py
@@ -66,17 +66,6 @@ class ClientCommands(db.CommandsProcessor, Commands, journal.Commands):
self._remote_urls.append(client.api_url.value)
self._jobs.spawn(self._wait_for_connectivity)
- def populate(self):
- self._home.volume.populate()
- contexts = self._home.volume['context']
- docs, __ = contexts.find(limit=db.MAX_LIMIT, clone=[1, 2])
- for context in docs:
- if clones.ensure_clones(context.guid):
- if context['clone'] != 2:
- self._checkin_context(context.guid, {'clone': 2})
- else:
- self._checkin_context(context.guid, {'clone': 0})
-
def close(self):
self._jobs.kill()
self._got_offline()
diff --git a/tests/units/client/clones.py b/tests/units/client/clones.py
index 2c41d43..626715c 100755
--- a/tests/units/client/clones.py
+++ b/tests/units/client/clones.py
@@ -354,6 +354,70 @@ class CloneTest(tests.Test):
assert not lexists('share/mime/packages/%s.xml' % hashed_path)
assert not lexists('share/mime/application/x-foo-bar.xml')
+ def test_Sync(self):
+ volume = Volume('client')
+ volume['context'].create({
+ 'guid': 'context1',
+ 'type': 'activity',
+ 'title': 'title',
+ 'summary': 'summary',
+ 'description': 'description',
+ 'clone': 0,
+ })
+ volume['context'].create({
+ 'guid': 'context2',
+ 'type': 'activity',
+ 'title': 'title',
+ 'summary': 'summary',
+ 'description': 'description',
+ 'clone': 1,
+ })
+ volume['context'].create({
+ 'guid': 'context3',
+ 'type': 'activity',
+ 'title': 'title',
+ 'summary': 'summary',
+ 'description': 'description',
+ 'clone': 2,
+ })
+
+ os.makedirs('Activities')
+ os.utime('Activities', (volume['context'].mtime + 1, volume['context'].mtime + 1))
+
+ self.touch(clones._context_path('context1', 'clone'))
+ self.touch(clones._context_path('context2', 'clone'))
+ clones.populate(volume['context'], ['Activities'])
+
+ self.assertEqual(0, volume['context'].get('context1')['clone'])
+ self.assertEqual(2, volume['context'].get('context2')['clone'])
+ self.assertEqual(0, volume['context'].get('context3')['clone'])
+
+ def test_SyncByMtime(self):
+ volume = Volume('client')
+ volume['context'].create({
+ 'guid': 'context',
+ 'type': 'activity',
+ 'title': 'title',
+ 'summary': 'summary',
+ 'description': 'description',
+ 'clone': 2,
+ })
+
+ os.makedirs('Activities')
+ os.utime('Activities', (2, 2))
+
+ volume['context'].mtime = 3
+ clones.populate(volume['context'], ['Activities'])
+ self.assertEqual(2, volume['context'].get('context')['clone'])
+
+ volume['context'].mtime = 2
+ clones.populate(volume['context'], ['Activities'])
+ self.assertEqual(2, volume['context'].get('context')['clone'])
+
+ volume['context'].mtime = 1
+ clones.populate(volume['context'], ['Activities'])
+ self.assertEqual(0, volume['context'].get('context')['clone'])
+
if __name__ == '__main__':
tests.main()
diff --git a/tests/units/client/online_commands.py b/tests/units/client/online_commands.py
index 121d53f..6f1bcdd 100755
--- a/tests/units/client/online_commands.py
+++ b/tests/units/client/online_commands.py
@@ -938,56 +938,6 @@ class OnlineCommandsTest(tests.Test):
{'favorite': True, 'clone': 2},
ipc.get(['artifact', guid], reply=['favorite', 'clone']))
- def test_populate_HomeVolumeEvents(self):
- volume = Volume('client')
- volume['context'].create({
- 'guid': 'context1',
- 'type': 'activity',
- 'title': 'title',
- 'summary': 'summary',
- 'description': 'description',
- 'clone': 0,
- })
- volume['context'].create({
- 'guid': 'context2',
- 'type': 'activity',
- 'title': 'title',
- 'summary': 'summary',
- 'description': 'description',
- 'clone': 1,
- })
- volume['context'].create({
- 'guid': 'context3',
- 'type': 'activity',
- 'title': 'title',
- 'summary': 'summary',
- 'description': 'description',
- 'clone': 2,
- })
-
- self.start_master()
- cp = ClientCommands(volume)
- self.wait_for_events(cp, event='inline', state='online').wait()
- assert cp.inline()
-
- def events_cb():
- for event in cp.subscribe():
- if event.startswith('data: '):
- events.append(json.loads(event[6:]))
- events = []
- coroutine.spawn(events_cb)
- coroutine.dispatch()
-
- self.touch(clones._context_path('context1', 'clone'))
- self.touch(clones._context_path('context2', 'clone'))
- cp.populate()
-
- self.assertEqual([
- {'event': 'update', 'document': 'context', 'guid': 'context2', 'props': {'clone': 2}},
- {'event': 'update', 'document': 'context', 'guid': 'context3', 'props': {'clone': 0}},
- ],
- events)
-
def test_HomeVolumeEvents(self):
self.home_volume = self.start_online_client()
ipc = IPCClient()