~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/testing/pgsql.py

  • Committer: Jeroen Vermeulen
  • Date: 2011-09-26 06:30:07 UTC
  • mto: This revision was merged to the branch mainline in revision 14049.
  • Revision ID: jeroen.vermeulen@canonical.com-20110926063007-1fb5eelnidpnra9a
Fix lots of lint in recently-changed files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
            try:
45
45
                self.real_connection.close()
46
46
            except psycopg2.InterfaceError:
47
 
                pass # Already closed, killed etc. Ignore.
 
47
                # Already closed, killed etc. Ignore.
 
48
                pass
48
49
 
49
50
    def rollback(self, InterfaceError=psycopg2.InterfaceError):
50
51
        # In our test suites, rollback ends up being called twice in some
87
88
class CursorWrapper:
88
89
    """A wrapper around cursor objects.
89
90
 
90
 
    Acts like a normal cursor object, except if CursorWrapper.record_sql is set,
91
 
    then queries that pass through CursorWrapper.execute will be appended to
92
 
    CursorWrapper.last_executed_sql.  This is useful for tests that want to
 
91
    Acts like a normal cursor object, except if CursorWrapper.record_sql is
 
92
    set, then queries that pass through CursorWrapper.execute will be appended
 
93
    to CursorWrapper.last_executed_sql.  This is useful for tests that want to
93
94
    ensure that certain SQL is generated.
94
95
    """
95
96
    real_cursor = None
130
131
 
131
132
 
132
133
_org_connect = None
 
134
 
 
135
 
133
136
def fake_connect(*args, **kw):
134
137
    return ConnectionWrapper(_org_connect(*args, **kw))
135
138
 
 
139
 
136
140
def installFakeConnect():
137
141
    global _org_connect
138
142
    assert _org_connect is None
139
143
    _org_connect = psycopg2.connect
140
144
    psycopg2.connect = fake_connect
141
145
 
 
146
 
142
147
def uninstallFakeConnect():
143
148
    global _org_connect
144
149
    assert _org_connect is not None
148
153
 
149
154
class PgTestSetup:
150
155
 
151
 
    connections = [] # Shared
 
156
    # Shared:
 
157
    connections = []
152
158
    # Use a dynamically generated dbname:
153
159
    dynamic = object()
154
160
 
267
273
            return
268
274
        self.dropDb()
269
275
 
270
 
        # Take out an external lock on the template to avoid causing contention
271
 
        # and impeding other processes (pg performs poorly when performing
272
 
        # concurrent create db from a single template).
 
276
        # Take out an external lock on the template to avoid causing
 
277
        # contention and impeding other processes (pg performs poorly
 
278
        # when performing concurrent create db from a single template).
273
279
        pid = os.getpid()
274
280
        start = time.time()
275
281
        # try for up to 10 seconds:
278
284
            sys.stderr.write('%0.2f starting %s\n' % (start, pid,))
279
285
        l = None
280
286
        lockname = '/tmp/lp.createdb.%s' % (self.template,)
281
 
        # Wait for the external lock. Most LP tests use the DatabaseLayer which
282
 
        # does a double-indirect: it clones the launchpad_ftest_template into a
283
 
        # per-test runner template, so we don't have much template contention.
284
 
        # However there are a few tests in LP which do use template1 and will
285
 
        # contend a lot. Cloning template1 takes 0.2s on a modern machine, so
286
 
        # even a modest 8-way server will trivially backlog on db cloning.
287
 
        # The 30 second time is enough to deal with the backlog on the known
288
 
        # template1 using tests.
 
287
        # Wait for the external lock.  Most LP tests use the
 
288
        # DatabaseLayer which does a double-indirect: it clones the
 
289
        # launchpad_ftest_template into a per-test runner template, so
 
290
        # we don't have much template contention.
 
291
        # However there are a few tests in LP which do use template1 and
 
292
        # will contend a lot. Cloning template1 takes 0.2s on a modern
 
293
        # machine, so even a modest 8-way server will trivially backlog
 
294
        # on db cloning.
 
295
        # The 30 second time is enough to deal with the backlog on the
 
296
        # known template1 using tests.
289
297
        while time.time() - start < 30.0:
290
298
            try:
291
299
                if debug:
307
315
            attempts = 10
308
316
            for counter in range(0, attempts):
309
317
                if debug:
310
 
                    sys.stderr.write('%0.2f connecting %s %s\n' % (
311
 
                        time.time(), pid, self.template))
 
318
                    sys.stderr.write(
 
319
                        "%0.2f connecting %s %s\n"
 
320
                        % (time.time(), pid, self.template))
312
321
                con = self.superuser_connection(self.template)
313
322
                try:
314
323
                    con.set_isolation_level(0)
325
334
                            # aborting badly.
326
335
                            atexit.register(self.dropDb)
327
336
                            if debug:
328
 
                                sys.stderr.write('create db in %0.2fs\n' % (
329
 
                                    time.time()-_start,))
 
337
                                sys.stderr.write(
 
338
                                    "create db in %0.2fs\n" % (
 
339
                                        time.time() - _start))
330
340
                            break
331
341
                        except psycopg2.DatabaseError, x:
332
342
                            if counter == attempts - 1:
338
348
                        cur.close()
339
349
                finally:
340
350
                    con.close()
341
 
                duration = (2**counter)*random.random()
 
351
                duration = (2 ** counter) * random.random()
342
352
                if debug:
343
353
                    sys.stderr.write(
344
354
                        '%0.2f busy:sleeping (%d retries) %s %s %s\n' % (
345
355
                        time.time(), counter, pid, self.template, duration))
346
 
                # Let the server wrap up whatever was blocking the copy of the template.
 
356
                # Let the server wrap up whatever was blocking the copy
 
357
                # of the template.
347
358
                time.sleep(duration)
348
359
            end = time.time()
349
360
            if debug:
350
 
                sys.stderr.write('%0.2f (%0.2f) completed (%d retries) %s %s\n' % (
351
 
                    end, end-start, counter, pid, self.template))
 
361
                sys.stderr.write(
 
362
                    '%0.2f (%0.2f) completed (%d retries) %s %s\n'
 
363
                    % (end, end - start, counter, pid, self.template))
352
364
        finally:
353
365
            l.unlock()
354
366
            if debug:
362
374
        '''Close all outstanding connections and drop the database'''
363
375
        for con in self.connections[:]:
364
376
            if con.auto_close:
365
 
                con.close() # Removes itself from self.connections
 
377
                # Removes itself from self.connections:
 
378
                con.close()
366
379
        if (ConnectionWrapper.committed and ConnectionWrapper.dirty):
367
380
            PgTestSetup._reset_db = True
368
381
        ConnectionWrapper.committed = False