2 This file is part of GNUnet.
3 (C) 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors)
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 2, or (at your
8 option) any later version.
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.
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file fs/fs_unindex.c
23 * @author Krista Grothoff
24 * @author Christian Grothoff
25 * @brief Unindex file.
28 #include "gnunet_constants.h"
29 #include "gnunet_fs_service.h"
30 #include "gnunet_protocols.h"
36 * Function called by the tree encoder to obtain
37 * a block of plaintext data (for the lowest level
40 * @param cls our publishing context
41 * @param offset identifies which block to get
42 * @param max (maximum) number of bytes to get; returning
43 * fewer will also cause errors
44 * @param buf where to copy the plaintext buffer
45 * @param emsg location to store an error message (on error)
46 * @return number of bytes copied to buf, 0 on error
49 unindex_reader (void *cls,
55 struct GNUNET_FS_UnindexContext *uc = cls;
58 pt_size = GNUNET_MIN(max,
59 uc->file_size - offset);
61 GNUNET_DISK_file_seek (uc->fh, offset, GNUNET_DISK_SEEK_SET))
63 *emsg = GNUNET_strdup (_("Failed to find given position in file"));
67 GNUNET_DISK_file_read (uc->fh,
71 *emsg = GNUNET_strdup (_("Failed to read file"));
79 * Fill in all of the generic fields for
82 * @param pi structure to fill in
83 * @param uc overall unindex context
84 * @param offset where we are in the file (for progress)
87 make_unindex_status (struct GNUNET_FS_ProgressInfo *pi,
88 struct GNUNET_FS_UnindexContext *uc,
91 pi->value.unindex.uc = uc;
92 pi->value.unindex.cctx = uc->client_info;
93 pi->value.unindex.filename = uc->filename;
94 pi->value.unindex.size = uc->file_size;
96 = GNUNET_TIME_calculate_eta (uc->start_time,
99 pi->value.publish.duration = GNUNET_TIME_absolute_get_duration (uc->start_time);
100 pi->value.publish.completed = offset;
105 * Function called with information about our
106 * progress in computing the tree encoding.
109 * @param offset where are we in the file
110 * @param pt_block plaintext of the currently processed block
111 * @param pt_size size of pt_block
112 * @param depth depth of the block in the tree
115 unindex_progress (void *cls,
117 const void *pt_block,
121 struct GNUNET_FS_UnindexContext *uc = cls;
122 struct GNUNET_FS_ProgressInfo pi;
124 pi.status = GNUNET_FS_STATUS_UNINDEX_PROGRESS;
125 make_unindex_status (&pi, uc, offset);
126 pi.value.unindex.specifics.progress.data = pt_block;
127 pi.value.unindex.specifics.progress.offset = offset;
128 pi.value.unindex.specifics.progress.data_len = pt_size;
129 pi.value.unindex.specifics.progress.depth = depth;
131 = uc->h->upcb (uc->h->upcb_cls,
137 * We've encountered an error during
138 * unindexing. Signal the client.
140 * @param uc context for the failed unindexing operation
141 * @param emsg the error message
144 signal_unindex_error (struct GNUNET_FS_UnindexContext *uc,
147 struct GNUNET_FS_ProgressInfo pi;
149 pi.status = GNUNET_FS_STATUS_UNINDEX_ERROR;
150 make_unindex_status (&pi, uc, 0);
151 pi.value.unindex.eta = GNUNET_TIME_UNIT_FOREVER_REL;
152 pi.value.unindex.specifics.error.message = emsg;
154 = uc->h->upcb (uc->h->upcb_cls,
160 * Continuation called to notify client about result of the
161 * datastore removal operation.
164 * @param success GNUNET_SYSERR on failure
165 * @param msg NULL on success, otherwise an error message
168 process_cont (void *cls,
172 struct GNUNET_FS_UnindexContext *uc = cls;
173 if (success == GNUNET_SYSERR)
175 signal_unindex_error (uc,
180 GNUNET_FS_tree_encoder_next (uc->tc);
185 * Function called asking for the current (encoded)
186 * block to be processed. After processing the
187 * client should either call "GNUNET_FS_tree_encode_next"
188 * or (on error) "GNUNET_FS_tree_encode_finish".
191 * @param query the query for the block (key for lookup in the datastore)
192 * @param offset offset of the block
193 * @param type type of the block (IBLOCK or DBLOCK)
194 * @param block the (encrypted) block
195 * @param block_size size of block (in bytes)
198 unindex_process (void *cls,
199 const GNUNET_HashCode *query,
205 struct GNUNET_FS_UnindexContext *uc = cls;
208 struct OnDemandBlock odb;
210 if (type != GNUNET_DATASTORE_BLOCKTYPE_DBLOCK)
215 else /* on-demand encoded DBLOCK */
217 size = sizeof(struct OnDemandBlock);
219 odb.file_id = uc->file_id;
222 GNUNET_DATASTORE_remove (uc->dsh,
228 GNUNET_CONSTANTS_SERVICE_TIMEOUT);
233 * Function called when the tree encoder has
234 * processed all blocks. Clean up.
236 * @param cls our unindexing context
240 unindex_finish (void *cls,
241 const struct GNUNET_SCHEDULER_TaskContext *tc)
243 struct GNUNET_FS_UnindexContext *uc = cls;
245 struct GNUNET_FS_Uri *uri;
246 struct GNUNET_FS_ProgressInfo pi;
248 GNUNET_FS_tree_encoder_finish (uc->tc,
252 GNUNET_FS_uri_destroy (uri);
253 GNUNET_DISK_file_close (uc->fh);
255 GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO);
259 signal_unindex_error (uc, emsg);
264 pi.status = GNUNET_FS_STATUS_UNINDEX_COMPLETED;
265 make_unindex_status (&pi, uc, uc->file_size);
266 pi.value.unindex.eta = GNUNET_TIME_UNIT_ZERO;
268 = uc->h->upcb (uc->h->upcb_cls,
275 * Function called with the response from the
276 * FS service to our unindexing request.
278 * @param cls closure, unindex context
279 * @param msg NULL on timeout, otherwise the response
282 process_fs_response (void *cls,
283 const struct GNUNET_MessageHeader *msg)
285 struct GNUNET_FS_UnindexContext *uc = cls;
287 GNUNET_CLIENT_disconnect (uc->client);
289 if (uc->state != UNINDEX_STATE_FS_NOTIFY)
291 GNUNET_FS_unindex_stop (uc);
296 uc->state = UNINDEX_STATE_ERROR;
297 signal_unindex_error (uc,
298 _("Timeout waiting for `fs' service."));
301 if (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK)
303 uc->state = UNINDEX_STATE_ERROR;
304 signal_unindex_error (uc,
305 _("Invalid response from `fs' service."));
308 uc->state = UNINDEX_STATE_DS_REMOVE;
309 uc->dsh = GNUNET_DATASTORE_connect (uc->h->cfg,
313 uc->state = UNINDEX_STATE_ERROR;
314 signal_unindex_error (uc,
315 _("Failed to connect to `datastore' service."));
318 uc->fh = GNUNET_DISK_file_open (uc->filename,
319 GNUNET_DISK_OPEN_READ,
320 GNUNET_DISK_PERM_NONE);
323 GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO);
325 uc->state = UNINDEX_STATE_ERROR;
326 signal_unindex_error (uc,
327 _("Failed to open file for unindexing."));
330 uc->tc = GNUNET_FS_tree_encoder_create (uc->h,
337 GNUNET_FS_tree_encoder_next (uc->tc);
342 * Function called once the hash of the file
343 * that is being unindexed has been computed.
345 * @param cls closure, unindex context
346 * @param file_id computed hash, NULL on error
349 process_hash (void *cls,
350 const GNUNET_HashCode *file_id)
352 struct GNUNET_FS_UnindexContext *uc = cls;
353 struct UnindexMessage req;
355 if (uc->state != UNINDEX_STATE_HASHING)
357 GNUNET_FS_unindex_stop (uc);
362 uc->state = UNINDEX_STATE_ERROR;
363 signal_unindex_error (uc,
364 _("Failed to compute hash of file."));
367 uc->file_id = *file_id;
368 uc->state = UNINDEX_STATE_FS_NOTIFY;
369 uc->client = GNUNET_CLIENT_connect (uc->h->sched,
372 req.header.size = htons (sizeof (struct UnindexMessage));
373 req.header.type = htons (GNUNET_MESSAGE_TYPE_FS_UNINDEX);
375 req.file_id = *file_id;
376 GNUNET_CLIENT_transmit_and_get_response (uc->client,
378 GNUNET_CONSTANTS_SERVICE_TIMEOUT,
380 &process_fs_response,
388 * @param h handle to the file sharing subsystem
389 * @param filename file to unindex
390 * @param cctx initial value for the client context
391 * @return NULL on error, otherwise handle
393 struct GNUNET_FS_UnindexContext *
394 GNUNET_FS_unindex_start (struct GNUNET_FS_Handle *h,
395 const char *filename,
398 struct GNUNET_FS_UnindexContext *ret;
399 struct GNUNET_FS_ProgressInfo pi;
403 GNUNET_DISK_file_size (filename,
407 ret = GNUNET_malloc (sizeof (struct GNUNET_FS_UnindexContext));
409 ret->filename = GNUNET_strdup (filename);
410 ret->start_time = GNUNET_TIME_absolute_get ();
411 ret->file_size = size;
412 ret->client_info = cctx;
414 // FIXME: make persistent!
415 pi.status = GNUNET_FS_STATUS_UNINDEX_START;
416 make_unindex_status (&pi, ret, 0);
417 pi.value.unindex.eta = GNUNET_TIME_UNIT_FOREVER_REL;
419 = h->upcb (h->upcb_cls,
421 GNUNET_CRYPTO_hash_file (h->sched,
422 GNUNET_SCHEDULER_PRIORITY_IDLE,
433 * Clean up after completion of an unindex operation.
438 GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc)
440 struct GNUNET_FS_ProgressInfo pi;
442 if ( (uc->state != UNINDEX_STATE_COMPLETE) &&
443 (uc->state != UNINDEX_STATE_ERROR) )
445 uc->state = UNINDEX_STATE_ABORTED;
448 // FIXME: make unpersistent!
449 make_unindex_status (&pi, uc,
450 (uc->state == UNINDEX_STATE_COMPLETE)
451 ? uc->file_size : 0);
452 pi.status = GNUNET_FS_STATUS_UNINDEX_STOPPED;
453 pi.value.unindex.eta = GNUNET_TIME_UNIT_ZERO;
455 = uc->h->upcb (uc->h->upcb_cls,
457 GNUNET_break (NULL == uc->client_info);
458 GNUNET_free (uc->filename);
462 /* end of fs_unindex.c */