use heap instead of DLL
[oweals/gnunet.git] / src / fs / fs_list_indexed.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2003, 2004, 2006, 2009 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file fs/fs_list_indexed.c
23  * @author Christian Grothoff
24  * @brief provide a list of all indexed files
25  */
26
27 #include "platform.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_fs_service.h"
30 #include "gnunet_protocols.h"
31 #include "fs_api.h"
32
33
34 /**
35  * Context for #GNUNET_FS_get_indexed_files().
36  */
37 struct GNUNET_FS_GetIndexedContext
38 {
39
40   /**
41    * Connection to the FS service.
42    */
43   struct GNUNET_MQ_Handle *mq;
44
45   /**
46    * Function to call for each indexed file.
47    */
48   GNUNET_FS_IndexedFileProcessor iterator;
49
50   /**
51    * Closure for @e iterator.
52    */
53   void *iterator_cls;
54
55   /**
56    * Continuation to trigger at the end.
57    */
58   GNUNET_SCHEDULER_TaskCallback cont;
59
60   /**
61    * Closure for @e cont.
62    */
63   void *cont_cls;
64 };
65
66
67 /**
68  * Function called on each response from the FS
69  * service with information about indexed files.
70  *
71  * @param cls closure (of type `struct GNUNET_FS_GetIndexedContext *`)
72  * @param msg message with indexing information
73  */
74 static void
75 handle_index_info_end (void *cls,
76                        const struct GNUNET_MessageHeader *msg)
77 {
78   struct GNUNET_FS_GetIndexedContext *gic = cls;
79
80   (void) gic->iterator (gic->iterator_cls,
81                         NULL,
82                         NULL);
83   GNUNET_FS_get_indexed_files_cancel (gic);
84 }
85
86
87 /**
88  * Check validity of response from the FS
89  * service with information about indexed files.
90  *
91  * @param cls closure (of type `struct GNUNET_FS_GetIndexedContext *`)
92  * @param iim message with indexing information
93  */
94 static int
95 check_index_info (void *cls,
96                   const struct IndexInfoMessage *iim)
97 {
98   uint16_t msize = ntohs (iim->header.size) - sizeof (*iim);
99   const char *filename;
100
101   filename = (const char *) &iim[1];
102   if (filename[msize - 1] != '\0')
103   {
104     GNUNET_break (0);
105     return GNUNET_SYSERR;
106   }
107   return GNUNET_OK;
108 }
109
110
111 /**
112  * Function called on each response from the FS
113  * service with information about indexed files.
114  *
115  * @param cls closure (of type `struct GNUNET_FS_GetIndexedContext *`)
116  * @param iim message with indexing information
117  */
118 static void
119 handle_index_info (void *cls,
120                    const struct IndexInfoMessage *iim)
121 {
122   struct GNUNET_FS_GetIndexedContext *gic = cls;
123   const char *filename;
124
125   filename = (const char *) &iim[1];
126   if (GNUNET_OK !=
127       gic->iterator (gic->iterator_cls,
128                      filename,
129                      &iim->file_id))
130   {
131     GNUNET_FS_get_indexed_files_cancel (gic);
132     return;
133   }
134 }
135
136
137 /**
138  * Generic error handler, called with the appropriate error code and
139  * the same closure specified at the creation of the message queue.
140  * Not every message queue implementation supports an error handler.
141  *
142  * @param cls closure with the `struct GNUNET_FS_GetIndexedContent *`
143  * @param error error code
144  */
145 static void
146 mq_error_handler (void *cls,
147                   enum GNUNET_MQ_Error error)
148 {
149   struct GNUNET_FS_GetIndexedContext *gic = cls;
150
151   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
152               _("Failed to receive response from `%s' service.\n"),
153               "fs");
154   (void) gic->iterator (gic->iterator_cls, NULL, NULL);
155   GNUNET_FS_get_indexed_files_cancel (gic);
156 }
157
158
159 /**
160  * Iterate over all indexed files.
161  *
162  * @param h handle to the file sharing subsystem
163  * @param iterator function to call on each indexed file
164  * @param iterator_cls closure for iterator
165  * @return NULL on error ('iter' is not called)
166  */
167 struct GNUNET_FS_GetIndexedContext *
168 GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h,
169                              GNUNET_FS_IndexedFileProcessor iterator,
170                              void *iterator_cls)
171 {
172   struct GNUNET_FS_GetIndexedContext *gic
173     = GNUNET_new (struct GNUNET_FS_GetIndexedContext);
174   struct GNUNET_MQ_MessageHandler handlers[] = {
175     GNUNET_MQ_hd_fixed_size (index_info_end,
176                              GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END,
177                              struct GNUNET_MessageHeader,
178                              gic),
179     GNUNET_MQ_hd_var_size (index_info,
180                            GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY,
181                            struct IndexInfoMessage,
182                            gic),
183     GNUNET_MQ_handler_end ()
184   };
185   struct GNUNET_MQ_Envelope *env;
186   struct GNUNET_MessageHeader *msg;
187
188   gic->mq = GNUNET_CLIENT_connect (h->cfg,
189                                    "fs",
190                                    handlers,
191                                    &mq_error_handler,
192                                    h);
193   if (NULL == gic->mq)
194   {
195     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
196                 _("Failed to not connect to `%s' service.\n"),
197                 "fs");
198     GNUNET_free (gic);
199     return NULL;
200   }
201   gic->iterator = iterator;
202   gic->iterator_cls = iterator_cls;
203   env = GNUNET_MQ_msg (msg,
204                        GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET);
205   GNUNET_MQ_send (gic->mq,
206                   env);
207   return gic;
208 }
209
210
211 /**
212  * Cancel iteration over all indexed files.
213  *
214  * @param gic operation to cancel
215  */
216 void
217 GNUNET_FS_get_indexed_files_cancel (struct GNUNET_FS_GetIndexedContext *gic)
218 {
219   GNUNET_MQ_destroy (gic->mq);
220   GNUNET_free (gic);
221 }
222
223
224 /* end of fs_list_indexed.c */