diff options
Diffstat (limited to 'common/src/leap/soledad/common/couch.py')
-rw-r--r-- | common/src/leap/soledad/common/couch.py | 64 |
1 files changed, 34 insertions, 30 deletions
diff --git a/common/src/leap/soledad/common/couch.py b/common/src/leap/soledad/common/couch.py index 0aa84170..b51b32f3 100644 --- a/common/src/leap/soledad/common/couch.py +++ b/common/src/leap/soledad/common/couch.py @@ -40,7 +40,9 @@ from couchdb.http import ( ResourceConflict, ResourceNotFound, ServerError, - Session as CouchHTTPSession, + Session, + urljoin as couch_urljoin, + Resource, ) from u1db import query_parser, vectorclock from u1db.errors import ( @@ -333,17 +335,6 @@ class MultipartWriter(object): self.headers[name] = value -class Session(CouchHTTPSession): - """ - An HTTP session that can be closed. - """ - - def close_connections(self): - for key, conns in list(self.conns.items()): - for conn in conns: - conn.close() - - @contextmanager def couch_server(url): """ @@ -359,7 +350,6 @@ def couch_server(url): session = Session(timeout=COUCH_TIMEOUT) server = Server(url=url, session=session) yield server - session.close_connections() class CouchDatabase(CommonBackend): @@ -371,6 +361,7 @@ class CouchDatabase(CommonBackend): MAX_GET_DOCS_THREADS = 20 update_handler_lock = defaultdict(threading.Lock) + sync_info_lock = defaultdict(threading.Lock) class _GetDocThread(threading.Thread): """ @@ -440,7 +431,8 @@ class CouchDatabase(CommonBackend): if not create: raise DatabaseDoesNotExist() server.create(dbname) - return cls(url, dbname, replica_uid=replica_uid, ensure_ddocs=ensure_ddocs) + return cls( + url, dbname, replica_uid=replica_uid, ensure_ddocs=ensure_ddocs) def __init__(self, url, dbname, replica_uid=None, ensure_ddocs=True): """ @@ -465,6 +457,10 @@ class CouchDatabase(CommonBackend): self._database = Database( urljoin(self._url, self._dbname), self._session) + try: + self._database.info() + except ResourceNotFound: + raise DatabaseDoesNotExist() if replica_uid is not None: self._set_replica_uid(replica_uid) if ensure_ddocs: @@ -505,7 +501,6 @@ class CouchDatabase(CommonBackend): """ with couch_server(self._url) as server: del(server[self._dbname]) - self.close_connections() def close(self): """ @@ -514,20 +509,12 @@ class CouchDatabase(CommonBackend): :return: True if db was succesfully closed. :rtype: bool """ - self.close_connections() self._url = None self._full_commit = None self._session = None self._database = None return True - def close_connections(self): - """ - Close all open connections to the couch server. - """ - if self._session is not None: - self._session.close_connections() - def __del__(self): """ Close the database upon garbage collection. @@ -576,6 +563,8 @@ class CouchDatabase(CommonBackend): _replica_uid = property(_get_replica_uid, _set_replica_uid) + replica_uid = property(_get_replica_uid) + def _get_generation(self): """ Return the current generation. @@ -869,7 +858,7 @@ class CouchDatabase(CommonBackend): # Date.prototype.getTime() which was used before inside a couchdb # update handler. (int(time.time() * 1000), - self._allocate_transaction_id())) + self._allocate_transaction_id())) # build the couch document couch_doc = { '_id': doc.doc_id, @@ -889,11 +878,9 @@ class CouchDatabase(CommonBackend): envelope.close() # try to save and fail if there's a revision conflict try: - self._database.resource.put_json( + resource = self._new_resource() + resource.put_json( doc.doc_id, body=buf.getvalue(), headers=envelope.headers) - # What follows is a workaround for an ugly bug. See: - # https://leap.se/code/issues/5448 - self.close_connections() except ResourceConflict: raise RevisionConflict() @@ -1465,6 +1452,20 @@ class CouchDatabase(CommonBackend): continue yield t._doc + def _new_resource(self, *path): + """ + Return a new resource for accessing a couch database. + + :return: A resource for accessing a couch database. + :rtype: couchdb.http.Resource + """ + # Workaround for: https://leap.se/code/issues/5448 + url = couch_urljoin(self._database.resource.url, *path) + resource = Resource(url, Session(timeout=COUCH_TIMEOUT)) + resource.credentials = self._database.resource.credentials + resource.headers = self._database.resource.headers.copy() + return resource + class CouchSyncTarget(CommonSyncTarget): """ @@ -1537,8 +1538,8 @@ class CouchServerState(ServerState): :param dbname: The name of the database to ensure. :type dbname: str - :return: The CouchDatabase object and the replica uid. - :rtype: (CouchDatabase, str) + :raise Unauthorized: Always, because Soledad server is not allowed to + create databases. """ raise Unauthorized() @@ -1548,6 +1549,9 @@ class CouchServerState(ServerState): :param dbname: The name of the database to delete. :type dbname: str + + :raise Unauthorized: Always, because Soledad server is not allowed to + delete databases. """ raise Unauthorized() |