Merge lp:~facundo/ubuntuone-client/aq-memory-improvements into lp:ubuntuone-client

Proposed by Facundo Batista
Status: Merged
Approved by: dobey
Approved revision: 640
Merged at revision: 649
Proposed branch: lp:~facundo/ubuntuone-client/aq-memory-improvements
Merge into: lp:ubuntuone-client
Diff against target: 354 lines (+136/-85)
3 files modified
tests/syncdaemon/test_action_queue.py (+98/-29)
ubuntuone/syncdaemon/action_queue.py (+27/-47)
ubuntuone/syncdaemon/logger.py (+11/-9)
To merge this branch: bzr merge lp:~facundo/ubuntuone-client/aq-memory-improvements
Reviewer Review Type Date Requested Status
Guillermo Gonzalez Approve
John O'Brien (community) Approve
Review via email: mp+33269@code.launchpad.net

Commit message

Stop storing wrapped functions in every queued command.

Description of the change

Stop storing wrapped functions in every queued command.

For this, I heavily refactored the demark method. Tests included.

Also, fixed mklog to log correctly (and a little speedup).

To post a comment you must log in.
Revision history for this message
John O'Brien (jdobrien) wrote :

looks good, and all tests pass.... InlineCallbacks FTW!

review: Approve
Revision history for this message
Guillermo Gonzalez (verterok) wrote :

looks good!

review: Approve
Revision history for this message
dobey (dobey) wrote :
Download full text (7.5 KiB)

The attempt to merge lp:~facundo/ubuntuone-client/aq-memory-improvements into lp:ubuntuone-client failed.Below is the output from the failed tests.

/usr/bin/gnome-autogen.sh
checking for autoconf >= 2.53...
  testing autoconf2.50... not found.
  testing autoconf... found 2.67
checking for automake >= 1.10...
  testing automake-1.11... found 1.11.1
checking for libtool >= 1.5...
  testing libtoolize... found 2.2.6b
checking for intltool >= 0.30...
  testing intltoolize... found 0.41.1
checking for pkg-config >= 0.14.0...
  testing pkg-config... found 0.25
Checking for required M4 macros...
Checking for forbidden M4 macros...
Processing ./configure.ac
Running libtoolize...
libtoolize: putting auxiliary files in `.'.
libtoolize: copying file `./ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `m4'.
libtoolize: copying file `m4/libtool.m4'
libtoolize: copying file `m4/ltoptions.m4'
libtoolize: copying file `m4/ltsugar.m4'
libtoolize: copying file `m4/ltversion.m4'
libtoolize: copying file `m4/lt~obsolete.m4'
Running intltoolize...
Running aclocal-1.11...
Running autoconf...
Running autoheader...
Running automake-1.11...
Running ./configure --with-protocol=/var/cache/tarmac/ubuntuone-storage-protocol/trunk ...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking for library containing strerror... none required
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking dependency style of gcc... (cached) gcc3
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking for a sed that does not truncate output... /bin/sed
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for fgrep... /bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... yes
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries... pass_all
checking for ar... ar
check...

Read more...

Revision history for this message
dobey (dobey) wrote :

This should fix the dbus-docs failing problem during make dist:

=== modified file 'Makefile.am'
--- Makefile.am 2010-07-15 22:03:27 +0000
+++ Makefile.am 2010-08-23 14:35:33 +0000
@@ -76,7 +76,7 @@ test-coverage: logging.conf $(clientdefs

 check: lint test Makefile

-docs: Makefile
+docs: $(clientdefs_DATA) Makefile
  $(mkdir_p) docs
  if test "x$(builddir)" != "x$(srcdir)" -a -f "$(srcdir)/docs/syncdaemon_dbus_api.txt"; then \
   $(LN_S) "$(top_srcdir)/docs/syncdaemon_dbus_api.txt" "docs/syncdaemon_dbus_api.txt"; \

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/syncdaemon/test_action_queue.py'
2--- tests/syncdaemon/test_action_queue.py 2010-08-17 14:23:31 +0000
3+++ tests/syncdaemon/test_action_queue.py 2010-08-20 22:22:40 +0000
4@@ -55,6 +55,7 @@
5 DeltaList,
6 )
7 from ubuntuone.syncdaemon.event_queue import EventQueue, EVENTS
8+from ubuntuone.syncdaemon.marker import MDMarker
9
10
11 PATH = u'~/Documents/pdfs/moño/'
12@@ -1058,6 +1059,7 @@
13 def setUp(self):
14 """Set up."""
15 res = super(ActionQueueCommandTestCase, self).setUp()
16+ self.handler.setLevel(logging.DEBUG)
17
18 class MyCommand(ActionQueueCommand):
19 logged_attrs = ('a', 'b', 'c', 'd')
20@@ -1067,6 +1069,7 @@
21
22 request_queue = RequestQueue(name='fu', action_queue=self.action_queue)
23 self.cmd = MyCommand(request_queue)
24+ self.cmd.start_unqueued() # just for it to create its logger
25
26 return res
27
28@@ -1075,35 +1078,101 @@
29 d = self.cmd.to_dict()
30 self.assertEqual(d, dict(a=3, b='foo', c=u'año', d=None))
31
32- def test_unwrap_no_results(self):
33- """Test unwrap with no results."""
34- r = self.cmd.unwrap([])
35- self.assertEqual(r, [])
36-
37- def test_unwrap_one_result_ok(self):
38- """Test unwrap with one result ok."""
39- r = self.cmd.unwrap([(True, 'foo')])
40- self.assertEqual(r, ['foo'])
41-
42- def test_unwrap_result_None(self):
43- """Test unwrap with None a valid result."""
44- r = self.cmd.unwrap([None])
45- self.assertEqual(r, [])
46-
47- def test_unwrap_result_failed(self):
48- """Test unwrap with a not ok result."""
49- r = self.cmd.unwrap([(False, 'failure')])
50- self.assertEqual(r, 'failure')
51-
52- def test_unwrap_mixed_results_ok(self):
53- """Test unwrap with different results no failure."""
54- r = self.cmd.unwrap([(True, 'foo'), None, (True, 'bar')])
55- self.assertEqual(r, ['foo', 'bar'])
56-
57- def test_unwrap_mixed_results_failure(self):
58- """Test unwrap with different results one failure."""
59- r = self.cmd.unwrap([(True, 'foo'), (False, 'fail'), (True, 'bar')])
60- self.assertEqual(r, 'fail')
61+ @defer.inlineCallbacks
62+ def test_demark_not_marker(self):
63+ """Test demark with not a marker."""
64+ result = yield self.cmd.demark('not a marker')
65+ self.assertEqual(result, ['not a marker'])
66+
67+ @defer.inlineCallbacks
68+ def test_demark_with_marker_future(self):
69+ """Test demark with a marker not ready.
70+
71+ Here, on purpose, set up everything and trigger later.
72+ """
73+ marker = MDMarker('foo')
74+ d = self.cmd.demark(marker)
75+
76+ self.action_queue.uuid_map.set(marker, 'node_id')
77+ result = yield d
78+ self.assertEqual(result, ['node_id'])
79+ self.assertTrue(self.handler.check_debug(
80+ "waiting for the real value of 'foo'"))
81+
82+ @defer.inlineCallbacks
83+ def test_demark_with_marker_ready(self):
84+ """Test demark with a marker that had data."""
85+ marker = MDMarker('foo')
86+ self.action_queue.uuid_map.set(marker, 'node_id')
87+ result = yield self.cmd.demark(marker)
88+ self.assertEqual(result, ['node_id'])
89+ self.assertTrue(self.handler.check_debug(
90+ "waiting for the real value of 'foo'"))
91+
92+ @defer.inlineCallbacks
93+ def test_demark_mixed_markers(self):
94+ """Test demark with both a marker and not."""
95+ # call demark with both
96+ marker = MDMarker('foo')
97+ self.action_queue.uuid_map.set(marker, 'node_id')
98+ result = yield self.cmd.demark('notamarker', marker)
99+
100+ # check
101+ self.assertEqual(result, ['notamarker', 'node_id'])
102+ self.assertTrue(self.handler.check_debug(
103+ "waiting for the real value of 'foo'"))
104+ self.assertFalse(self.handler.check_debug(
105+ "waiting for the real value of 'notamarker'"))
106+
107+ @defer.inlineCallbacks
108+ def test_demark_marker_ready_got_ok(self):
109+ """Test demark getting a marker triggered ok now."""
110+ marker = MDMarker('foo')
111+ self.action_queue.uuid_map.set(marker, 'node_id')
112+ result = yield self.cmd.demark(marker)
113+ self.assertEqual(result, ['node_id'])
114+ self.assertTrue(self.handler.check_debug("got 'foo'"))
115+
116+ @defer.inlineCallbacks
117+ def test_demark_marker_future_got_ok(self):
118+ """Test demark getting a marker triggered ok later."""
119+ # don't have the info now
120+ marker = MDMarker('foo')
121+ d = self.cmd.demark(marker)
122+ self.assertFalse(self.handler.check_debug("got 'foo'"))
123+
124+ # set and check
125+ self.action_queue.uuid_map.set(marker, 'node_id')
126+ result = yield d
127+ self.assertEqual(result, ['node_id'])
128+ self.assertTrue(self.handler.check_debug("got 'foo'"))
129+
130+ @defer.inlineCallbacks
131+ def test_demark_marker_ready_got_failure(self):
132+ """Test demark getting a marker triggered with failure now."""
133+ marker = MDMarker('foo')
134+ self.action_queue.uuid_map.err(marker, Failure(Exception('bad')))
135+ try:
136+ yield self.cmd.demark(marker)
137+ except Exception, e:
138+ self.assertEqual(str(e), 'bad')
139+ self.assertTrue(self.handler.check_error("failed 'foo'"))
140+
141+ @defer.inlineCallbacks
142+ def test_demark_marker_future_got_failure(self):
143+ """Test demark getting a marker triggered with failure later."""
144+ # don't have the info now
145+ marker = MDMarker('foo')
146+ d = self.cmd.demark(marker)
147+ self.assertFalse(self.handler.check_error("failed 'foo'"))
148+
149+ # set the marker and check
150+ self.action_queue.uuid_map.err(marker, Failure(Exception('bad')))
151+ try:
152+ yield d
153+ except Exception, e:
154+ self.assertEqual(str(e), 'bad')
155+ self.assertTrue(self.handler.check_error("failed 'foo'"))
156
157
158 class CreateUDFTestCase(ConnectedBaseTestCase):
159
160=== modified file 'ubuntuone/syncdaemon/action_queue.py'
161--- ubuntuone/syncdaemon/action_queue.py 2010-08-17 14:23:31 +0000
162+++ ubuntuone/syncdaemon/action_queue.py 2010-08-20 22:22:40 +0000
163@@ -254,7 +254,7 @@
164 try:
165 if upload.cancelled:
166 raise UploadCompressionCancelled("Cancelled")
167- upload.log.debug('compressing', filename)
168+ upload.log.debug('compressing: %r', filename)
169 # we need to compress the file completely to figure out its
170 # compressed size. So streaming is out :(
171 if upload.tempfile_factory is None:
172@@ -519,8 +519,7 @@
173 self.map = {}
174
175 def get(self, key):
176- """
177- Get the value for the given key.
178+ """Get the value for the given key.
179
180 This always returns a deferred; when we already know the value
181 we return a `succeed`, and if we don't know the value because
182@@ -537,9 +536,9 @@
183 return d
184
185 def set(self, key, value):
186- """
187- We've got the value for a key! Write it down in the map, and
188- fire the waiting deferreds.
189+ """We've got the value for a key!
190+
191+ Write it down in the map, and fire the waiting deferreds.
192 """
193 if key not in self.map:
194 self.map[key] = value
195@@ -550,18 +549,18 @@
196 raise KeyError("key is taken -- dunno what to do")
197
198 def err(self, key, failure):
199- """
200- Something went terribly wrong in the process of getting a
201- value. Break the news to the waiting deferreds.
202+ """Something went terribly wrong in the process of getting a value.
203+
204+ Break the news to the waiting deferreds.
205 """
206 self.failed[key] = failure.getErrorMessage()
207 for d in self.waiting.pop(key, ()):
208 d.errback(failure)
209
210 def resolve_maybe(self, key):
211- """
212- Return either the mapping of key (if key has been resolved),
213- or key itself (if not).
214+ """Return either the mapping of key, or key itself.
215+
216+ The former if key has been resolved, the later if not.
217 """
218 return self.map.get(key, key)
219
220@@ -1238,43 +1237,24 @@
221 def check_conditions(self):
222 """Check conditions on which the command may be waiting."""
223
224+ @defer.inlineCallbacks
225 def demark(self, *maybe_markers):
226 """Arrange to have maybe_markers realized."""
227- l = []
228+ results = []
229 for marker in maybe_markers:
230 if IMarker.providedBy(marker):
231- self.log.debug('waiting until we know the real value of %r',
232- marker)
233- d = self.action_queue.uuid_map.get(marker)
234- d.addCallbacks(passit(lambda _:
235- self.log.debug('got %r', marker)),
236- passit(lambda f:
237- self.log.error('failed %r', marker)))
238+ self.log.debug("waiting for the real value of '%s'", marker)
239+ try:
240+ result = yield self.action_queue.uuid_map.get(marker)
241+ except:
242+ self.log.error("failed '%s'", marker)
243+ raise
244+ else:
245+ self.log.debug("got '%s'", marker)
246+ results.append(result)
247 else:
248- d = defer.succeed(marker)
249- l.append(d)
250- dl = defer.DeferredList(l, fireOnOneErrback=True, consumeErrors=True)
251- dl.addCallbacks(self.unwrap, lambda f: f.value.subFailure)
252-
253- return dl
254-
255- @staticmethod
256- def unwrap(results):
257- """Unpack the values from the result of a DeferredList.
258-
259- If there's a failure, return it instead.
260- """
261- values = []
262- for result in results:
263- # result can be none if one of the callbacks failed
264- # before the others were ready
265- if result is not None:
266- is_ok, value = result
267- if not is_ok:
268- # a failure!
269- return value
270- values.append(value)
271- return values
272+ results.append(marker)
273+ defer.returnValue(results)
274
275 def end_callback(self, arg):
276 """It worked!"""
277@@ -1288,9 +1268,9 @@
278 """It failed!"""
279 error_message = failure.getErrorMessage()
280 if failure.check(*self.suppressed_error_messages):
281- self.log.warn('failure', error_message)
282+ self.log.warn('failure: %s', error_message)
283 else:
284- self.log.error('failure', error_message)
285+ self.log.error('failure: %s', error_message)
286 self.log.debug('traceback follows:\n\n' + failure.getTraceback())
287 was_running = self.running
288 self.cleanup()
289@@ -1984,7 +1964,7 @@
290 cmd.volume_id == self.volume_id:
291 # other GetDeltaFromScratch for same volume! skip self
292 m = "GetDeltaFromScratch already queued, not queueing self"
293- self.log.debug(m, cmd)
294+ self.log.debug(m)
295 return
296
297 # no similar command
298
299=== modified file 'ubuntuone/syncdaemon/logger.py'
300--- ubuntuone/syncdaemon/logger.py 2010-07-27 17:15:58 +0000
301+++ ubuntuone/syncdaemon/logger.py 2010-08-20 22:22:40 +0000
302@@ -23,7 +23,6 @@
303 import os
304 import zlib
305
306-from itertools import imap
307 from ubuntuone.logger import (
308 LOGFOLDER,
309 _DEBUG_LOG_LEVEL,
310@@ -65,33 +64,36 @@
311 self.zipped_desc = zlib.compress(desc, 9)
312 self.logger = _logger
313
314- @property
315- def desc(self):
316- return zlib.decompress(self.zipped_desc)
317-
318 def _log(self, logger_func, *args):
319- """
320- Generalized form of the different logging functions.
321- """
322- logger_func(self.desc + " ".join(imap(str, args)))
323+ """Generalized form of the different logging methods."""
324+ desc = zlib.decompress(self.zipped_desc)
325+ text = desc + args[0]
326+ logger_func(text, *args[1:])
327+
328 def debug(self, *args):
329 """Log at level DEBUG"""
330 self._log(self.logger.debug, *args)
331+
332 def info(self, *args):
333 """Log at level INFO"""
334 self._log(self.logger.info, *args)
335+
336 def warn(self, *args):
337 """Log at level WARN"""
338 self._log(self.logger.warn, *args)
339+
340 def error(self, *args):
341 """Log at level ERROR"""
342 self._log(self.logger.error, *args)
343+
344 def exception(self, *args):
345 """Log an exception"""
346 self._log(self.logger.exception, *args)
347+
348 def note(self, *args):
349 """Log at NOTE level (high-priority info) """
350 self._log(self.logger.high, *args)
351+
352 def trace(self, *args):
353 """Log at level TRACE"""
354 self._log(self.logger.trace, *args)

Subscribers

People subscribed via source and target branches