database error
[notmuch-archives.git] / db / 3a9ad84ec00c33e7e6241f94a1aaedda51adb2
1 Return-Path: <adrien@bustany.org>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 677E7431FDE\r
6         for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 11:41:09 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 0\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\r
12         autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id Fgysct7-kN8i for <notmuch@notmuchmail.org>;\r
16         Wed, 18 Jul 2012 11:41:07 -0700 (PDT)\r
17 Received: from mail.bustany.org (bustany.org [176.31.244.208])\r
18         by olra.theworths.org (Postfix) with ESMTP id 81E4A431FC4\r
19         for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 11:41:05 -0700 (PDT)\r
20 Received: from localhost.localdomain (91-158-2-79.elisa-laajakaista.fi\r
21         [91.158.2.79])\r
22         by mail.bustany.org (Postfix) with ESMTPSA id 6A6D91400C2\r
23         for <notmuch@notmuchmail.org>; Wed, 18 Jul 2012 20:37:08 +0200 (CEST)\r
24 From: Adrien Bustany <adrien@bustany.org>\r
25 To: notmuch@notmuchmail.org\r
26 Subject: [PATCH 3/7] go: Allow notmuch objects to be garbage collected\r
27 Date: Wed, 18 Jul 2012 21:34:31 +0300\r
28 Message-Id: <1342636475-16057-4-git-send-email-adrien@bustany.org>\r
29 X-Mailer: git-send-email 1.7.7.6\r
30 In-Reply-To: <1342636475-16057-1-git-send-email-adrien@bustany.org>\r
31 References: <1342636475-16057-1-git-send-email-adrien@bustany.org>\r
32 X-BeenThere: notmuch@notmuchmail.org\r
33 X-Mailman-Version: 2.1.13\r
34 Precedence: list\r
35 List-Id: "Use and development of the notmuch mail system."\r
36         <notmuch.notmuchmail.org>\r
37 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
38         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
39 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
40 List-Post: <mailto:notmuch@notmuchmail.org>\r
41 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
42 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
43         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
44 X-List-Received-Date: Wed, 18 Jul 2012 18:41:10 -0000\r
45 \r
46 This makes notmuch appropriately free the underlying notmuch C objects\r
47 when garbage collecting their Go wrappers. To make sure we don't break\r
48 the underlying links between objects (for example, a notmuch_messages_t\r
49 being GC'ed before a notmuch_message_t belonging to it), we add for each\r
50 wraper struct a pointer to the owner object (Go objects with a reference\r
51 pointing to them don't get garbage collected).\r
52 ---\r
53  bindings/go/src/notmuch/notmuch.go |  153 +++++++++++++++++++++++++++++++-----\r
54  1 files changed, 134 insertions(+), 19 deletions(-)\r
55 \r
56 diff --git a/bindings/go/src/notmuch/notmuch.go b/bindings/go/src/notmuch/notmuch.go\r
57 index 1d77fd2..3f436a0 100644\r
58 --- a/bindings/go/src/notmuch/notmuch.go\r
59 +++ b/bindings/go/src/notmuch/notmuch.go\r
60 @@ -11,6 +11,7 @@ package notmuch\r
61  #include "notmuch.h"\r
62  */\r
63  import "C"\r
64 +import "runtime"\r
65  import "unsafe"\r
66  \r
67  // Status codes used for the return values of most functions\r
68 @@ -47,40 +48,152 @@ func (self Status) String() string {\r
69  /* Various opaque data types. For each notmuch_<foo>_t see the various\r
70   * notmuch_<foo> functions below. */\r
71  \r
72 +type Object interface {}\r
73 +\r
74  type Database struct {\r
75         db *C.notmuch_database_t\r
76  }\r
77  \r
78 +func createDatabase(db *C.notmuch_database_t) *Database {\r
79 +       self := &Database{db: db}\r
80 +\r
81 +       runtime.SetFinalizer(self, func(x *Database) {\r
82 +               if (x.db != nil) {\r
83 +                       C.notmuch_database_destroy(x.db)\r
84 +               }\r
85 +       })\r
86 +\r
87 +       return self\r
88 +}\r
89 +\r
90  type Query struct {\r
91         query *C.notmuch_query_t\r
92 +       owner Object\r
93 +}\r
94 +\r
95 +func createQuery(query *C.notmuch_query_t, owner Object) *Query {\r
96 +       self := &Query{query: query, owner: owner}\r
97 +\r
98 +       runtime.SetFinalizer(self, func(x *Query) {\r
99 +               if (x.query != nil) {\r
100 +                       C.notmuch_query_destroy(x.query)\r
101 +               }\r
102 +       })\r
103 +\r
104 +       return self\r
105  }\r
106  \r
107  type Threads struct {\r
108         threads *C.notmuch_threads_t\r
109 +       owner Object\r
110 +}\r
111 +\r
112 +func createThreads(threads *C.notmuch_threads_t, owner Object) *Threads {\r
113 +       self := &Threads{threads: threads, owner: owner}\r
114 +\r
115 +       runtime.SetFinalizer(self, func(x *Threads) {\r
116 +               if (x.threads != nil) {\r
117 +                       C.notmuch_threads_destroy(x.threads)\r
118 +               }\r
119 +       })\r
120 +\r
121 +       return self\r
122  }\r
123  \r
124  type Thread struct {\r
125         thread *C.notmuch_thread_t\r
126 +       owner Object\r
127 +}\r
128 +\r
129 +func createThread(thread *C.notmuch_thread_t, owner Object) *Thread {\r
130 +       self := &Thread{thread: thread, owner: owner}\r
131 +\r
132 +       runtime.SetFinalizer(self, func(x *Thread) {\r
133 +               if (x.thread != nil) {\r
134 +                       C.notmuch_thread_destroy(x.thread)\r
135 +               }\r
136 +       })\r
137 +\r
138 +       return self\r
139  }\r
140  \r
141  type Messages struct {\r
142         messages *C.notmuch_messages_t\r
143 +       owner Object\r
144 +}\r
145 +\r
146 +func createMessages(messages *C.notmuch_messages_t, owner Object) *Messages {\r
147 +       self := &Messages{messages: messages, owner: owner}\r
148 +\r
149 +       return self\r
150  }\r
151  \r
152  type Message struct {\r
153         message *C.notmuch_message_t\r
154 +       owner Object\r
155 +}\r
156 +\r
157 +func createMessage(message *C.notmuch_message_t, owner Object) *Message {\r
158 +       self := &Message{message: message, owner: owner}\r
159 +\r
160 +       runtime.SetFinalizer(self, func(x *Message) {\r
161 +               if (x.message != nil) {\r
162 +                       C.notmuch_message_destroy(x.message)\r
163 +               }\r
164 +       })\r
165 +\r
166 +       return self\r
167  }\r
168  \r
169  type Tags struct {\r
170         tags *C.notmuch_tags_t\r
171 +       owner Object\r
172 +}\r
173 +\r
174 +func createTags(tags *C.notmuch_tags_t, owner Object) *Tags {\r
175 +       self := &Tags{tags: tags, owner: owner}\r
176 +\r
177 +       runtime.SetFinalizer(self, func(x *Tags) {\r
178 +               if (x.tags != nil) {\r
179 +                       C.notmuch_tags_destroy(x.tags)\r
180 +               }\r
181 +       })\r
182 +\r
183 +       return self\r
184  }\r
185  \r
186  type Directory struct {\r
187         dir *C.notmuch_directory_t\r
188 +       owner Object\r
189 +}\r
190 +\r
191 +func createDirectory(directory *C.notmuch_directory_t, owner Object) *Directory {\r
192 +       self := &Directory{dir: directory, owner: owner}\r
193 +\r
194 +       runtime.SetFinalizer(self, func(x *Directory) {\r
195 +               if (x.dir != nil) {\r
196 +                       C.notmuch_directory_destroy(x.dir)\r
197 +               }\r
198 +       })\r
199 +\r
200 +       return self\r
201  }\r
202  \r
203  type Filenames struct {\r
204         fnames *C.notmuch_filenames_t\r
205 +       owner Object\r
206 +}\r
207 +\r
208 +func createFilenames(filenames *C.notmuch_filenames_t, owner Object) *Filenames {\r
209 +       self := &Filenames{fnames: filenames, owner: owner}\r
210 +\r
211 +       runtime.SetFinalizer(self, func(x *Filenames) {\r
212 +               if (x.fnames != nil) {\r
213 +                       C.notmuch_filenames_destroy(x.fnames)\r
214 +               }\r
215 +       })\r
216 +\r
217 +       return self\r
218  }\r
219  \r
220  type DatabaseMode C.notmuch_database_mode_t\r
221 @@ -100,12 +213,13 @@ func NewDatabase(path string) (*Database, Status) {\r
222                 return nil, STATUS_OUT_OF_MEMORY\r
223         }\r
224  \r
225 -       self := &Database{db: nil}\r
226 -       st := Status(C.notmuch_database_create(c_path, &self.db))\r
227 +       var db *C.notmuch_database_t;\r
228 +       st := Status(C.notmuch_database_create(c_path, &db))\r
229         if st != STATUS_SUCCESS {\r
230                 return nil, st\r
231         }\r
232 -       return self, st\r
233 +\r
234 +       return createDatabase(db), st\r
235  }\r
236  \r
237  /* Open an existing notmuch database located at 'path'.\r
238 @@ -134,12 +248,13 @@ func OpenDatabase(path string, mode DatabaseMode) (*Database, Status) {\r
239                 return nil, STATUS_OUT_OF_MEMORY\r
240         }\r
241  \r
242 -       self := &Database{db: nil}\r
243 -       st := Status(C.notmuch_database_open(c_path, C.notmuch_database_mode_t(mode), &self.db))\r
244 +       var db *C.notmuch_database_t;\r
245 +       st := Status(C.notmuch_database_open(c_path, C.notmuch_database_mode_t(mode), &db))\r
246         if st != STATUS_SUCCESS {\r
247                 return nil, st\r
248         }\r
249 -       return self, st\r
250 +\r
251 +       return createDatabase(db), st\r
252  }\r
253  \r
254  /* Close the given notmuch database, freeing all associated\r
255 @@ -204,7 +319,7 @@ func (self *Database) GetDirectory(path string) (*Directory, Status) {\r
256         if st != STATUS_SUCCESS || c_dir == nil {\r
257                 return nil, st\r
258         }\r
259 -       return &Directory{dir: c_dir}, st\r
260 +       return createDirectory(c_dir, nil), st\r
261  }\r
262  \r
263  /* Add a new message to the given notmuch database.\r
264 @@ -258,7 +373,7 @@ func (self *Database) AddMessage(fname string) (*Message, Status) {\r
265         var c_msg *C.notmuch_message_t = new(C.notmuch_message_t)\r
266         st := Status(C.notmuch_database_add_message(self.db, c_fname, &c_msg))\r
267  \r
268 -       return &Message{message: c_msg}, st\r
269 +       return createMessage(c_msg, nil), st\r
270  }\r
271  \r
272  /* Remove a message from the given notmuch database.\r
273 @@ -319,12 +434,12 @@ func (self *Database) FindMessage(message_id string) (*Message, Status) {\r
274                 return nil, STATUS_OUT_OF_MEMORY\r
275         }\r
276  \r
277 -       msg := &Message{message: nil}\r
278 -       st := Status(C.notmuch_database_find_message(self.db, c_msg_id, &msg.message))\r
279 +       var msg *C.notmuch_message_t\r
280 +       st := Status(C.notmuch_database_find_message(self.db, c_msg_id, &msg))\r
281         if st != STATUS_SUCCESS {\r
282                 return nil, st\r
283         }\r
284 -       return msg, st\r
285 +       return createMessage(msg, nil), st\r
286  }\r
287  \r
288  /* Return a list of all tags found in the database.\r
289 @@ -339,7 +454,7 @@ func (self *Database) GetAllTags() *Tags {\r
290         if tags == nil {\r
291                 return nil\r
292         }\r
293 -       return &Tags{tags: tags}\r
294 +       return createTags(tags, nil)\r
295  }\r
296  \r
297  /* Create a new query for 'database'.\r
298 @@ -379,7 +494,7 @@ func (self *Database) CreateQuery(query string) *Query {\r
299         if q == nil {\r
300                 return nil\r
301         }\r
302 -       return &Query{query: q}\r
303 +       return createQuery(q, nil)\r
304  }\r
305  \r
306  /* Sort values for notmuch_query_set_sort */\r
307 @@ -459,7 +574,7 @@ func (self *Query) SearchThreads() *Threads {\r
308         if threads == nil {\r
309                 return nil\r
310         }\r
311 -       return &Threads{threads: threads}\r
312 +       return createThreads(threads, self)\r
313  }\r
314  \r
315  /* Execute a query for messages, returning a notmuch_messages_t object\r
316 @@ -505,7 +620,7 @@ func (self *Query) SearchMessages() *Messages {\r
317         if msgs == nil {\r
318                 return nil\r
319         }\r
320 -       return &Messages{messages: msgs}\r
321 +       return createMessages(msgs, self)\r
322  }\r
323  \r
324  /* Destroy a notmuch_query_t along with any associated resources.\r
325 @@ -607,7 +722,7 @@ func (self *Messages) Get() *Message {\r
326         if msg == nil {\r
327                 return nil\r
328         }\r
329 -       return &Message{message: msg}\r
330 +       return createMessage(msg, self)\r
331  }\r
332  \r
333  /* Move the 'messages' iterator to the next message.\r
334 @@ -659,7 +774,7 @@ func (self *Messages) CollectTags() *Tags {\r
335         if tags == nil {\r
336                 return nil\r
337         }\r
338 -       return &Tags{tags: tags}\r
339 +       return createTags(tags, self)\r
340  }\r
341  \r
342  /* Get the message ID of 'message'.\r
343 @@ -739,7 +854,7 @@ func (self *Message) GetReplies() *Messages {\r
344         if msgs == nil {\r
345                 return nil\r
346         }\r
347 -       return &Messages{messages: msgs}\r
348 +       return createMessages(msgs, self)\r
349  }\r
350  \r
351  /* Get a filename for the email corresponding to 'message'.\r
352 @@ -871,7 +986,7 @@ func (self *Message) GetTags() *Tags {\r
353         if tags == nil {\r
354                 return nil\r
355         }\r
356 -       return &Tags{tags: tags}\r
357 +       return createTags(tags, self)\r
358  }\r
359  \r
360  /* The longest possible tag value. */\r
361 -- \r
362 1.7.7.6\r
363 \r