diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2013-03-24 17:17:42 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2013-03-24 17:17:42 (GMT) |
commit | a978a14bae22d7322196a73bf2e5bfff69a971ea (patch) | |
tree | bbdaf11ab0ab4f5d9302f5d83715d5c3e71c9562 | |
parent | 7f66d8739502a6c959d0db05990b7f2f74fa36ee (diff) |
Sync local contexts only on changes
-rwxr-xr-x | sugar-network-client | 4 | ||||
-rw-r--r-- | sugar_network/client/clones.py | 46 | ||||
-rw-r--r-- | sugar_network/client/commands.py | 11 | ||||
-rwxr-xr-x | tests/units/client/clones.py | 64 | ||||
-rwxr-xr-x | tests/units/client/online_commands.py | 50 |
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() |