~ubuntu-branches/ubuntu/trusty/desktopcouch/trusty

« back to all changes in this revision

Viewing changes to debian/patches/lp_522538.patch

  • Committer: Bazaar Package Importer
  • Author(s): Chad MILLER
  • Date: 2010-06-22 16:21:19 UTC
  • Revision ID: james.westby@ubuntu.com-20100622162119-3ebuc61x323kahha
Tags: 0.6.6-0ubuntu1
* New upstream release, 0.6.6. (There is no 0.6.5, except in the wild.)
* Resolve circular dependencies.  Group together dependent code in 
  'desktopcouch' package, and make transition packages of subpackages.
  Upstream will try decoupling properly in future.  (Debian: #571929)
* debian/patches/lp_522538.patch
  - No longer needed.  Removed.
* debian/patches/replication-exclusion.patch
  - No longer needed.  Removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
=== modified file 'desktopcouch/records/server_base.py'
2
 
--- old/desktopcouch/records/server_base.py     2010-04-08 15:27:33 +0000
3
 
+++ new/desktopcouch/records/server_base.py     2010-04-19 16:07:11 +0000
4
 
@@ -42,6 +42,7 @@
5
 
 from couchdb.client import ResourceNotFound, ResourceConflict, uri as couchdburi
6
 
 from couchdb.design import ViewDefinition
7
 
 from record import Record
8
 
+import logging
9
 
 
10
 
 #DEFAULT_DESIGN_DOCUMENT = "design"
11
 
 DEFAULT_DESIGN_DOCUMENT = None  # each view in its own eponymous design doc.
12
 
@@ -142,29 +143,53 @@
13
 
 
14
 
     def __init__(self, database, uri, record_factory=None, create=False,
15
 
                  server_class=Server, **server_class_extras):
16
 
+        self._database_name = database
17
 
+        self._create = create
18
 
+        self._server_class = server_class
19
 
+        self._server_class_extras = server_class_extras
20
 
+        self.record_factory = record_factory or Record
21
 
         self.server_uri = uri
22
 
-        self._server = server_class(self.server_uri, **server_class_extras)
23
 
-        if database not in self._server:
24
 
-            if create:
25
 
-                self._server.create(database)
26
 
-            else:
27
 
-                raise NoSuchDatabase(database)
28
 
-        self.db = self._server[database]
29
 
-        self.record_factory = record_factory or Record
30
 
+        self._reconnect()
31
 
         self._changes_since = self.db.info()["update_seq"]
32
 
         self._changes_last_used = 0  # Immediate run works.
33
 
 
34
 
+    @staticmethod
35
 
+    def _is_bug_lp539674(ex):
36
 
+        return isinstance(ex, AttributeError) and \
37
 
+                ex.args == ("'NoneType' object has no attribute 'makefile'",)
38
 
+
39
 
+    def with_reconnects(self, func, *args, **kwargs):
40
 
+        for retry in (2, 1, None):
41
 
+            try:
42
 
+                return func(*args, **kwargs)
43
 
+            except Exception, e:
44
 
+                if self._is_bug_lp539674(e) and retry:
45
 
+                    logging.warn("DB connection timed out.  Reconnecting.")
46
 
+                    self._reconnect()
47
 
+                    continue
48
 
+                else:
49
 
+                    raise
50
 
+
51
 
+    def _reconnect(self):
52
 
+        self._server = self._server_class(self.server_uri,
53
 
+                **self._server_class_extras)
54
 
+        if self._database_name not in self._server:
55
 
+            if self._create:
56
 
+                self._server.create(self._database_name)
57
 
+            else:
58
 
+                raise NoSuchDatabase(self._database_name)
59
 
+        self.db = self._server[self._database_name]
60
 
 
61
 
     def _temporary_query(self, map_fun, reduce_fun=None, language='javascript',
62
 
             wrapper=None, **options):
63
 
         """Pass-through to CouchDB library.  Deprecated."""
64
 
-        return self.db.query(map_fun, reduce_fun, language,
65
 
+        return self.with_reconnects(self.db.query, map_fun, reduce_fun, language,
66
 
               wrapper, **options)
67
 
 
68
 
     def get_record(self, record_id):
69
 
         """Get a record from back end storage."""
70
 
         try:
71
 
-            couch_record = self.db[record_id]
72
 
+            couch_record = self.with_reconnects(self.db.__getitem__, record_id)
73
 
         except ResourceNotFound:
74
 
             return None
75
 
         data = {}
76
 
@@ -193,11 +218,12 @@
77
 
             # Do not rely on couchdb to create an ID for us.
78
 
             from uuid import uuid4
79
 
             record.record_id = uuid4().hex
80
 
-        self.db[record.record_id] = record._data
81
 
+        self.with_reconnects(self.db.__setitem__,
82
 
+                record.record_id, record._data)
83
 
 
84
 
         for attachment_name in record.list_attachments():
85
 
             data, content_type = record.attachment_data(attachment_name)
86
 
-            self.db.put_attachment(
87
 
+            self.with_reconnects(self.db.put_attachment,
88
 
                 record._data, data, attachment_name, content_type)
89
 
 
90
 
         return record.record_id
91
 
@@ -215,7 +241,8 @@
92
 
         # although with a single record we need to test for the
93
 
         # revisison, with a batch we do not, but we have to make sure
94
 
         # that we did not get an error
95
 
-        batch_put_result = self.db.update([record._data for record in batch])
96
 
+        batch_put_result = self.with_reconnects(
97
 
+                self.db.update, [record._data for record in batch])
98
 
         for current_tuple in batch_put_result:
99
 
             success, docid, rev_or_exc = current_tuple
100
 
             if success:
101
 
@@ -224,7 +251,7 @@
102
 
                 record._data["_rev"] = rev_or_exc
103
 
                 for attachment_name in record.list_attachments():
104
 
                     data, content_type = record.attachment_data(attachment_name)
105
 
-                    self.db.put_attachment(
106
 
+                    self.with_reconnects(self.db.put_attachment,
107
 
                         {"_id":record.record_id, "_rev":record["_rev"]},
108
 
                         data, attachment_name, content_type)
109
 
         # all success record have the blobs added we return result of
110
 
@@ -249,7 +276,8 @@
111
 
         # as far as we know. (If they're not, we'll get a
112
 
         # ResourceConflict later on, from which we can recover.)
113
 
         if cached_record is None:
114
 
-            cached_record = self.db[record_id]
115
 
+            cached_record = self.with_reconnects(self.db.__getitem__,
116
 
+                    record_id)
117
 
         if isinstance(cached_record, Record):
118
 
             cached_record = cached_record._data
119
 
         record = copy.deepcopy(cached_record)
120
 
@@ -294,13 +322,15 @@
121
 
             # it.
122
 
             if modified:
123
 
                 try:
124
 
-                    self.db[record_id] = record
125
 
+                    self.with_reconnects(self.db.__setitem__, record_id,
126
 
+                            record)
127
 
                 except ResourceConflict:
128
 
                     # We got a conflict, meaning the record has
129
 
                     # changed in the database since we last loaded it
130
 
                     # into memory. Let's get a fresh copy and try
131
 
                     # again.
132
 
-                    record = self.db[record_id]
133
 
+                    record = self.with_reconnects(self.db.__getitem__,
134
 
+                            record_id)
135
 
                     continue
136
 
             # If we get here, nothing remains to be done, and we can
137
 
             # take a well deserved break.
138
 
@@ -308,17 +338,17 @@
139
 
 
140
 
     def delete_record(self, record_id):
141
 
         """Delete record with given id"""
142
 
-        record = self.db[record_id]
143
 
+        record = self.with_reconnects(self.db.__getitem__, record_id)
144
 
         record.setdefault('application_annotations', {}).setdefault(
145
 
             'Ubuntu One', {}).setdefault('private_application_annotations', {})[
146
 
             'deleted'] = True
147
 
-        self.db[record_id] = record
148
 
+        self.with_reconnects(self.db.__setitem__, record_id, record)
149
 
 
150
 
     def record_exists(self, record_id):
151
 
         """Check if record with given id exists."""
152
 
         if record_id not in self.db:
153
 
             return False
154
 
-        record = self.db[record_id]
155
 
+        record = self.with_reconnects(self.db.__getitem__, record_id)
156
 
         return not row_is_deleted(record)
157
 
 
158
 
     def delete_view(self, view_name, design_doc=DEFAULT_DESIGN_DOCUMENT):
159
 
@@ -332,7 +362,8 @@
160
 
         # No atomic updates.  Only read & mutate & write.  Le sigh.
161
 
         # First, get current contents.
162
 
         try:
163
 
-            view_container = self.db[doc_id]["views"]
164
 
+            view_container = self.with_reconnects(
165
 
+                    self.db.__getitem__, doc_id)["views"]
166
 
         except (KeyError, ResourceNotFound):
167
 
             raise KeyError
168
 
 
169
 
@@ -358,7 +389,7 @@
170
 
 
171
 
             # Remove design document.  This assumes there are only views in
172
 
             # design documents.  :(
173
 
-            del self.db[doc_id]
174
 
+            self.with_reconnects(self.db.__delitem__, doc_id)
175
 
 
176
 
         assert not self.view_exists(view_name, design_doc)
177
 
 
178
 
@@ -371,7 +402,8 @@
179
 
             design_doc = view_name
180
 
 
181
 
         view_id_fmt = "_design/%(design_doc)s/_view/%(view_name)s"
182
 
-        return self.db.view(view_id_fmt % locals(), **params)
183
 
+        return self.with_reconnects(self.db.view, view_id_fmt % locals(),
184
 
+                **params)
185
 
 
186
 
     def add_view(self, view_name, map_js, reduce_js,
187
 
             design_doc=DEFAULT_DESIGN_DOCUMENT):
188
 
@@ -393,7 +425,8 @@
189
 
         doc_id = "_design/%(design_doc)s" % locals()
190
 
 
191
 
         try:
192
 
-            view_container = self.db[doc_id]["views"]
193
 
+            view_container = \
194
 
+                    self.with_reconnects(self.db.__getitem__, doc_id)["views"]
195
 
             return view_name in view_container
196
 
         except (KeyError, ResourceNotFound):
197
 
             return False
198
 
@@ -404,7 +437,7 @@
199
 
         in it."""
200
 
         doc_id = "_design/%(design_doc)s" % locals()
201
 
         try:
202
 
-            return list(self.db[doc_id]["views"])
203
 
+            return list(self.with_reconnects(self.db.__getitem__, doc_id)["views"])
204
 
         except (KeyError, ResourceNotFound):
205
 
             return []
206
 
 
207