0a4d2e3c481e0ca6f4e2db65c492da4c409335cb
[oweals/gnunet.git] / src / fs / test_fs_unindex_persistence.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20  * @file fs/test_fs_unindex_persistence.c
21  * @brief simple testcase for simple publish + unindex operation
22  * @author Christian Grothoff
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include "gnunet_testing_lib.h"
27 #include "gnunet_fs_service.h"
28
29 /**
30  * File-size we use for testing.
31  */
32 #define FILESIZE (1024 * 1024 * 2)
33
34 /**
35  * How long until we give up on transmitting the message?
36  */
37 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
38
39 /**
40  * How long should our test-content live?
41  */
42 #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
43
44
45 static struct GNUNET_TIME_Absolute start;
46
47 static struct GNUNET_FS_Handle *fs;
48
49 static struct GNUNET_FS_UnindexContext *unindex;
50
51 static struct GNUNET_FS_PublishContext *publish;
52
53 static char *fn;
54
55 static const struct GNUNET_CONFIGURATION_Handle *cfg;
56
57
58 static void
59 abort_publish_task (void *cls)
60 {
61   GNUNET_FS_publish_stop (publish);
62   publish = NULL;
63 }
64
65
66 static void
67 abort_unindex_task (void *cls)
68 {
69   if (unindex != NULL)
70   {
71     GNUNET_FS_unindex_stop (unindex);
72     unindex = NULL;
73   }
74   if (fn != NULL)
75   {
76     GNUNET_DISK_directory_remove (fn);
77     GNUNET_free (fn);
78     fn = NULL;
79   }
80 }
81
82
83 static void *
84 progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event);
85
86
87 static void
88 restart_fs_task (void *cls)
89 {
90   GNUNET_FS_stop (fs);
91   fs = GNUNET_FS_start (cfg, "test-fs-unindex-persistence", &progress_cb, NULL,
92                         GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END);
93 }
94
95
96 /**
97  * Consider scheduling the restart-task.
98  * Only runs the restart task once per event
99  * category.
100  *
101  * @param ev type of the event to consider
102  */
103 static void
104 consider_restart (int ev)
105 {
106   static int prev[32];
107   static int off;
108   int i;
109
110   for (i = 0; i < off; i++)
111     if (prev[i] == ev)
112       return;
113   prev[off++] = ev;
114   GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_URGENT,
115                                       &restart_fs_task, NULL);
116 }
117
118
119 static void *
120 progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event)
121 {
122   switch (event->status)
123   {
124   case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
125     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
126                 "Publish is progressing (%llu/%llu at level %u off %llu)...\n",
127                 (unsigned long long) event->value.publish.completed,
128                 (unsigned long long) event->value.publish.size,
129                 event->value.publish.specifics.progress.depth,
130                 (unsigned long long) event->value.publish.specifics.
131                 progress.offset);
132     break;
133   case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY:
134     break;
135   case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
136     printf ("Publishing complete, %llu kbps.\n",
137             (unsigned long long) (FILESIZE * 1000000LL /
138                                   (1 +
139                                    GNUNET_TIME_absolute_get_duration
140                                    (start).rel_value_us) / 1024));
141     start = GNUNET_TIME_absolute_get ();
142     unindex = GNUNET_FS_unindex_start (fs, fn, "unindex");
143     GNUNET_assert (unindex != NULL);
144     break;
145   case GNUNET_FS_STATUS_UNINDEX_COMPLETED:
146     printf ("Unindex complete,  %llu kbps.\n",
147             (unsigned long long) (FILESIZE * 1000000LL /
148                                   (1 +
149                                    GNUNET_TIME_absolute_get_duration
150                                    (start).rel_value_us) / 1024));
151     GNUNET_SCHEDULER_add_now (&abort_unindex_task, NULL);
152     break;
153   case GNUNET_FS_STATUS_UNINDEX_PROGRESS:
154     consider_restart (event->status);
155     GNUNET_assert (unindex == event->value.unindex.uc);
156     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
157                 "Unindex is progressing (%llu/%llu at level %u off %llu)...\n",
158                 (unsigned long long) event->value.unindex.completed,
159                 (unsigned long long) event->value.unindex.size,
160                 event->value.unindex.specifics.progress.depth,
161                 (unsigned long long) event->value.unindex.specifics.
162                 progress.offset);
163     break;
164   case GNUNET_FS_STATUS_PUBLISH_SUSPEND:
165     if (event->value.publish.pc == publish)
166       publish = NULL;
167     break;
168   case GNUNET_FS_STATUS_PUBLISH_RESUME:
169     if (NULL == publish)
170     {
171       publish = event->value.publish.pc;
172       return "publish-context";
173     }
174     break;
175   case GNUNET_FS_STATUS_UNINDEX_SUSPEND:
176     GNUNET_assert (event->value.unindex.uc == unindex);
177     unindex = NULL;
178     break;
179   case GNUNET_FS_STATUS_UNINDEX_RESUME:
180     GNUNET_assert (NULL == unindex);
181     unindex = event->value.unindex.uc;
182     return "unindex";
183   case GNUNET_FS_STATUS_PUBLISH_ERROR:
184     FPRINTF (stderr, "Error publishing file: %s\n",
185              event->value.publish.specifics.error.message);
186     GNUNET_break (0);
187     GNUNET_SCHEDULER_add_now (&abort_publish_task, NULL);
188     break;
189   case GNUNET_FS_STATUS_UNINDEX_ERROR:
190     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191                 "Error unindexing file: %s\n",
192                 event->value.unindex.specifics.error.message);
193     GNUNET_SCHEDULER_add_now (&abort_unindex_task, NULL);
194     break;
195   case GNUNET_FS_STATUS_PUBLISH_START:
196     GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx));
197     GNUNET_assert (NULL == event->value.publish.pctx);
198     GNUNET_assert (FILESIZE == event->value.publish.size);
199     GNUNET_assert (0 == event->value.publish.completed);
200     GNUNET_assert (1 == event->value.publish.anonymity);
201     break;
202   case GNUNET_FS_STATUS_PUBLISH_STOPPED:
203     GNUNET_assert (publish == event->value.publish.pc);
204     GNUNET_assert (FILESIZE == event->value.publish.size);
205     GNUNET_assert (1 == event->value.publish.anonymity);
206     GNUNET_FS_stop (fs);
207     fs = NULL;
208     break;
209   case GNUNET_FS_STATUS_UNINDEX_START:
210     consider_restart (event->status);
211     GNUNET_assert (unindex == NULL);
212     GNUNET_assert (0 == strcmp ("unindex", event->value.unindex.cctx));
213     GNUNET_assert (0 == strcmp (fn, event->value.unindex.filename));
214     GNUNET_assert (FILESIZE == event->value.unindex.size);
215     GNUNET_assert (0 == event->value.unindex.completed);
216     break;
217   case GNUNET_FS_STATUS_UNINDEX_STOPPED:
218     GNUNET_assert (unindex == event->value.unindex.uc);
219     GNUNET_SCHEDULER_add_now (&abort_publish_task, NULL);
220     break;
221   default:
222     printf ("Unexpected event: %d\n", event->status);
223     break;
224   }
225   return NULL;
226 }
227
228
229 static void
230 run (void *cls,
231      const struct GNUNET_CONFIGURATION_Handle *c,
232      struct GNUNET_TESTING_Peer *peer)
233 {
234   const char *keywords[] = {
235     "down_foo",
236     "down_bar",
237   };
238   char *buf;
239   struct GNUNET_CONTAINER_MetaData *meta;
240   struct GNUNET_FS_Uri *kuri;
241   struct GNUNET_FS_FileInformation *fi;
242   size_t i;
243   struct GNUNET_FS_BlockOptions bo;
244
245   cfg = c;
246   fn = GNUNET_DISK_mktemp ("gnunet-unindex-test-dst");
247   fs = GNUNET_FS_start (cfg, "test-fs-unindex-persistence", &progress_cb, NULL,
248                         GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END);
249   GNUNET_assert (NULL != fs);
250   buf = GNUNET_malloc (FILESIZE);
251   for (i = 0; i < FILESIZE; i++)
252     buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256);
253   GNUNET_assert (FILESIZE ==
254                  GNUNET_DISK_fn_write (fn, buf, FILESIZE,
255                                        GNUNET_DISK_PERM_USER_READ |
256                                        GNUNET_DISK_PERM_USER_WRITE));
257   GNUNET_free (buf);
258   meta = GNUNET_CONTAINER_meta_data_create ();
259   kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords);
260   bo.content_priority = 42;
261   bo.anonymity_level = 1;
262   bo.replication_level = 0;
263   bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME);
264   fi = GNUNET_FS_file_information_create_from_file (fs, "publish-context", fn,
265                                                     kuri, meta, GNUNET_YES,
266                                                     &bo);
267   GNUNET_FS_uri_destroy (kuri);
268   GNUNET_CONTAINER_meta_data_destroy (meta);
269   GNUNET_assert (NULL != fi);
270   start = GNUNET_TIME_absolute_get ();
271   publish =
272       GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL,
273                                GNUNET_FS_PUBLISH_OPTION_NONE);
274   GNUNET_assert (publish != NULL);
275 }
276
277
278 int
279 main (int argc, char *argv[])
280 {
281   if (0 != GNUNET_TESTING_peer_run ("test-fs-unindex-persistence",
282                                     "test_fs_unindex_data.conf",
283                                     &run, NULL))
284     return 1;
285   return 0;
286 }
287
288 /* end of test_fs_unindex_persistence.c */