/*
This file is part of GNUnet.
- (C) 2003, 2004, 2006 Christian Grothoff (and other contributing authors)
+ (C) 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
*/
/**
- * @file applications/fs/ecrs/unindex.c
- * @author Krista Bennett
+ * @file fs/fs_unindex.c
+ * @author Krista Grothoff
* @author Christian Grothoff
- *
- * Unindex file.
- *
- * TODO:
- * - code cleanup (share more with upload.c)
+ * @brief Unindex file.
*/
-
#include "platform.h"
+#include "gnunet_constants.h"
+#include "gnunet_fs_service.h"
#include "gnunet_protocols.h"
-#include "gnunet_ecrs_lib.h"
-#include "gnunet_fs_lib.h"
-#include "gnunet_getoption_lib.h"
-#include "ecrs_core.h"
-#include "ecrs.h"
#include "fs.h"
-#include "tree.h"
+#include "fs_tree.h"
-#define STRICT_CHECKS GNUNET_NO
/**
- * Append the given key and query to the iblock[level].
- * If iblock[level] is already full, compute its chk
- * and push it to level+1. iblocks is guaranteed to
- * be big enough.
+ * Function called by the tree encoder to obtain
+ * a block of plaintext data (for the lowest level
+ * of the tree).
*
- * This function matches exactly upload.c::pushBlock,
- * except in the call to 'GNUNET_FS_delete'. TODO: refactor
- * to avoid code duplication (move to block.c, pass
- * GNUNET_FS_delete as argument!).
+ * @param cls our publishing context
+ * @param offset identifies which block to get
+ * @param max (maximum) number of bytes to get; returning
+ * fewer will also cause errors
+ * @param buf where to copy the plaintext buffer
+ * @param emsg location to store an error message (on error)
+ * @return number of bytes copied to buf, 0 on error
*/
-static int
-pushBlock (struct GNUNET_ClientServerConnection *sock,
- const GNUNET_EC_ContentHashKey * chk, unsigned int level,
- GNUNET_DatastoreValue ** iblocks)
+static size_t
+unindex_reader (void *cls,
+ uint64_t offset,
+ size_t max,
+ void *buf,
+ char **emsg)
{
- unsigned int size;
- unsigned int present;
- GNUNET_DatastoreValue *value;
- GNUNET_EC_DBlock *db;
- GNUNET_EC_ContentHashKey ichk;
-
- size = ntohl (iblocks[level]->size) - sizeof (GNUNET_DatastoreValue);
- present =
- (size - sizeof (GNUNET_EC_DBlock)) / sizeof (GNUNET_EC_ContentHashKey);
- db = (GNUNET_EC_DBlock *) & iblocks[level][1];
- if (present == GNUNET_ECRS_CHK_PER_INODE)
+ struct GNUNET_FS_UnindexContext *uc = cls;
+ size_t pt_size;
+
+ pt_size = GNUNET_MIN(max,
+ uc->file_size - offset);
+ if (offset !=
+ GNUNET_DISK_file_seek (uc->fh, offset, GNUNET_DISK_SEEK_SET))
{
- GNUNET_EC_file_block_get_key (db, size, &ichk.key);
- GNUNET_EC_file_block_get_query (db, size, &ichk.query);
- if (GNUNET_OK != pushBlock (sock, &ichk, level + 1, iblocks))
- {
- GNUNET_GE_BREAK (NULL, 0);
- return GNUNET_SYSERR;
- }
- GNUNET_EC_file_block_encode (db, size, &ichk.query, &value);
-#if STRICT_CHECKS
- if (GNUNET_SYSERR == GNUNET_FS_delete (sock, value))
- {
- GNUNET_free (value);
- GNUNET_GE_BREAK (NULL, 0);
- return GNUNET_SYSERR;
- }
-#else
- GNUNET_FS_delete (sock, value);
-#endif
- GNUNET_free (value);
- size = sizeof (GNUNET_EC_DBlock);
+ *emsg = GNUNET_strdup (_("Failed to find given position in file"));
+ return 0;
}
- /* append GNUNET_EC_ContentHashKey */
- memcpy (&((char *) db)[size], chk, sizeof (GNUNET_EC_ContentHashKey));
- iblocks[level]->size = htonl (size +
- sizeof (GNUNET_EC_ContentHashKey) +
- sizeof (GNUNET_DatastoreValue));
- return GNUNET_OK;
+ if (pt_size !=
+ GNUNET_DISK_file_read (uc->fh,
+ buf,
+ pt_size))
+ {
+ *emsg = GNUNET_strdup (_("Failed to read file"));
+ return 0;
+ }
+ return pt_size;
+}
+
+
+/**
+ * Fill in all of the generic fields for
+ * an unindex event and call the callback.
+ *
+ * @param pi structure to fill in
+ * @param uc overall unindex context
+ * @param offset where we are in the file (for progress)
+ */
+void
+GNUNET_FS_unindex_make_status_ (struct GNUNET_FS_ProgressInfo *pi,
+ struct GNUNET_FS_UnindexContext *uc,
+ uint64_t offset)
+{
+ pi->value.unindex.uc = uc;
+ pi->value.unindex.cctx = uc->client_info;
+ pi->value.unindex.filename = uc->filename;
+ pi->value.unindex.size = uc->file_size;
+ pi->value.unindex.eta
+ = GNUNET_TIME_calculate_eta (uc->start_time,
+ offset,
+ uc->file_size);
+ pi->value.unindex.duration = GNUNET_TIME_absolute_get_duration (uc->start_time);
+ pi->value.unindex.completed = offset;
+ uc->client_info
+ = uc->h->upcb (uc->h->upcb_cls,
+ pi);
+
+}
+
+
+/**
+ * Function called with information about our
+ * progress in computing the tree encoding.
+ *
+ * @param cls closure
+ * @param offset where are we in the file
+ * @param pt_block plaintext of the currently processed block
+ * @param pt_size size of pt_block
+ * @param depth depth of the block in the tree
+ */
+static void
+unindex_progress (void *cls,
+ uint64_t offset,
+ const void *pt_block,
+ size_t pt_size,
+ unsigned int depth)
+{
+ struct GNUNET_FS_UnindexContext *uc = cls;
+ struct GNUNET_FS_ProgressInfo pi;
+
+ pi.status = GNUNET_FS_STATUS_UNINDEX_PROGRESS;
+ pi.value.unindex.specifics.progress.data = pt_block;
+ pi.value.unindex.specifics.progress.offset = offset;
+ pi.value.unindex.specifics.progress.data_len = pt_size;
+ pi.value.unindex.specifics.progress.depth = depth;
+ GNUNET_FS_unindex_make_status_ (&pi, uc, offset);
+}
+
+
+/**
+ * We've encountered an error during
+ * unindexing. Signal the client.
+ *
+ * @param uc context for the failed unindexing operation
+ */
+static void
+signal_unindex_error (struct GNUNET_FS_UnindexContext *uc)
+{
+ struct GNUNET_FS_ProgressInfo pi;
+
+ pi.status = GNUNET_FS_STATUS_UNINDEX_ERROR;
+ pi.value.unindex.eta = GNUNET_TIME_UNIT_FOREVER_REL;
+ pi.value.unindex.specifics.error.message = uc->emsg;
+ GNUNET_FS_unindex_make_status_ (&pi, uc, 0);
}
+/**
+ * Continuation called to notify client about result of the
+ * datastore removal operation.
+ *
+ * @param cls closure
+ * @param success GNUNET_SYSERR on failure
+ * @param msg NULL on success, otherwise an error message
+ */
+static void
+process_cont (void *cls,
+ int success,
+ const char *msg)
+{
+ struct GNUNET_FS_UnindexContext *uc = cls;
+ if (success == GNUNET_SYSERR)
+ {
+ uc->emsg = GNUNET_strdup (msg);
+ signal_unindex_error (uc);
+ return;
+ }
+ GNUNET_FS_tree_encoder_next (uc->tc);
+}
+
/**
- * Undo sym-linking operation:
- * a) check if we have a symlink
- * b) delete symbolic link
+ * Function called asking for the current (encoded)
+ * block to be processed. After processing the
+ * client should either call "GNUNET_FS_tree_encode_next"
+ * or (on error) "GNUNET_FS_tree_encode_finish".
+ *
+ * @param cls closure
+ * @param query the query for the block (key for lookup in the datastore)
+ * @param offset offset of the block
+ * @param type type of the block (IBLOCK or DBLOCK)
+ * @param block the (encrypted) block
+ * @param block_size size of block (in bytes)
*/
-static int
-undoSymlinking (struct GNUNET_GE_Context *ectx,
- const char *fn,
- const GNUNET_HashCode * fileId,
- struct GNUNET_ClientServerConnection *sock)
+static void
+unindex_process (void *cls,
+ const GNUNET_HashCode *query,
+ uint64_t offset,
+ enum GNUNET_BLOCK_Type type,
+ const void *block,
+ uint16_t block_size)
{
- GNUNET_EncName enc;
- char *serverDir;
- char *serverFN;
- struct stat buf;
-
-#ifndef S_ISLNK
- if (1)
- return GNUNET_OK; /* symlinks do not exist? */
-#endif
- if (0 != LSTAT (fn, &buf))
+ struct GNUNET_FS_UnindexContext *uc = cls;
+ uint32_t size;
+ const void *data;
+ struct OnDemandBlock odb;
+
+ if (type != GNUNET_BLOCK_TYPE_DBLOCK)
{
- GNUNET_GE_LOG_STRERROR_FILE (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_BULK |
- GNUNET_GE_USER | GNUNET_GE_ADMIN, "stat",
- fn);
- return GNUNET_SYSERR;
+ size = block_size;
+ data = block;
}
-#ifdef S_ISLNK
- if (!S_ISLNK (buf.st_mode))
- return GNUNET_OK;
-#endif
- serverDir =
- GNUNET_get_daemon_configuration_value (sock, "FS", "INDEX-DIRECTORY");
- if (serverDir == NULL)
- return GNUNET_OK;
- serverFN = GNUNET_malloc (strlen (serverDir) + 2 + sizeof (GNUNET_EncName));
- strcpy (serverFN, serverDir);
- GNUNET_free (serverDir);
- if (serverFN[strlen (serverFN) - 1] != DIR_SEPARATOR)
- strcat (serverFN, DIR_SEPARATOR_STR);
- GNUNET_hash_to_enc (fileId, &enc);
- strcat (serverFN, (char *) &enc);
-
- if (0 != UNLINK (serverFN))
+ else /* on-demand encoded DBLOCK */
{
- GNUNET_GE_LOG_STRERROR_FILE (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_BULK |
- GNUNET_GE_USER | GNUNET_GE_ADMIN, "unlink",
- serverFN);
- GNUNET_free (serverFN);
- return GNUNET_SYSERR;
+ size = sizeof(struct OnDemandBlock);
+ odb.offset = GNUNET_htonll (offset);
+ odb.file_id = uc->file_id;
+ data = &odb;
}
- GNUNET_free (serverFN);
- return GNUNET_OK;
+ GNUNET_DATASTORE_remove (uc->dsh,
+ query,
+ size,
+ data,
+ -2, 1,
+ GNUNET_CONSTANTS_SERVICE_TIMEOUT,
+ &process_cont,
+ uc);
}
+/**
+ * Function called when the tree encoder has
+ * processed all blocks. Clean up.
+ *
+ * @param cls our unindexing context
+ * @param tc not used
+ */
+static void
+unindex_finish (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_FS_UnindexContext *uc = cls;
+ char *emsg;
+ struct GNUNET_FS_Uri *uri;
+ struct GNUNET_FS_ProgressInfo pi;
+
+ GNUNET_FS_tree_encoder_finish (uc->tc,
+ &uri,
+ &emsg);
+ uc->tc = NULL;
+ if (uri != NULL)
+ GNUNET_FS_uri_destroy (uri);
+ GNUNET_DISK_file_close (uc->fh);
+ uc->fh = NULL;
+ GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO);
+ uc->dsh = NULL;
+ if (emsg != NULL)
+ {
+ uc->state = UNINDEX_STATE_ERROR;
+ uc->emsg = emsg;
+ signal_unindex_error (uc);
+ }
+ else
+ {
+ uc->state = UNINDEX_STATE_COMPLETE;
+ pi.status = GNUNET_FS_STATUS_UNINDEX_COMPLETED;
+ pi.value.unindex.eta = GNUNET_TIME_UNIT_ZERO;
+ GNUNET_FS_unindex_make_status_ (&pi, uc, uc->file_size);
+ }
+ GNUNET_FS_unindex_sync_ (uc);
+}
+
/**
- * Unindex a file.
+ * Function called with the response from the
+ * FS service to our unindexing request.
*
- * @return GNUNET_SYSERR if the unindexing failed (i.e. not indexed)
+ * @param cls closure, unindex context
+ * @param msg NULL on timeout, otherwise the response
*/
-int
-GNUNET_ECRS_file_unindex (struct GNUNET_GE_Context *ectx,
- struct GNUNET_GC_Configuration *cfg,
- const char *filename,
- GNUNET_ECRS_UploadProgressCallback upcb,
- void *upcbClosure, GNUNET_ECRS_TestTerminate tt,
- void *ttClosure)
+static void
+process_fs_response (void *cls,
+ const struct GNUNET_MessageHeader *msg)
{
- unsigned long long filesize;
- unsigned long long pos;
- unsigned int treedepth;
- int fd;
- int i;
- unsigned int size;
- GNUNET_DatastoreValue **iblocks;
- GNUNET_DatastoreValue *dblock;
- GNUNET_EC_DBlock *db;
- GNUNET_DatastoreValue *value;
- struct GNUNET_ClientServerConnection *sock;
- GNUNET_HashCode fileId;
- GNUNET_EC_ContentHashKey chk;
- GNUNET_CronTime eta;
- GNUNET_CronTime start;
- GNUNET_CronTime now;
- int wasIndexed;
-
- start = GNUNET_get_time ();
- if (GNUNET_YES != GNUNET_disk_file_test (ectx, filename))
+ struct GNUNET_FS_UnindexContext *uc = cls;
+
+ if (uc->client != NULL)
{
- GNUNET_GE_BREAK (ectx, 0);
- return GNUNET_SYSERR;
+ GNUNET_CLIENT_disconnect (uc->client, GNUNET_NO);
+ uc->client = NULL;
}
- if (GNUNET_OK !=
- GNUNET_disk_file_size (ectx, filename, &filesize, GNUNET_YES))
- return GNUNET_SYSERR;
- sock = GNUNET_client_connection_create (ectx, cfg);
- if (sock == NULL)
- return GNUNET_SYSERR;
- eta = 0;
- if (upcb != NULL)
- upcb (filesize, 0, eta, upcbClosure);
- if (GNUNET_SYSERR == GNUNET_hash_file (ectx, filename, &fileId))
+ if (uc->state != UNINDEX_STATE_FS_NOTIFY)
{
- GNUNET_client_connection_destroy (sock);
- GNUNET_GE_BREAK (ectx, 0);
- return GNUNET_SYSERR;
+ uc->state = UNINDEX_STATE_ERROR;
+ uc->emsg = GNUNET_strdup (_("Unexpected time for a response from `fs' service."));
+ GNUNET_FS_unindex_sync_ (uc);
+ signal_unindex_error (uc);
+ return;
}
- now = GNUNET_get_time ();
- eta = now + 2 * (now - start);
- /* very rough estimate: GNUNET_hash reads once through the file,
- we'll do that once more and write it. But of course
- the second read may be cached, and we have the encryption,
- so a factor of two is really, really just a rough estimate */
- start = now;
- /* reset the counter since the formula later does not
- take the time for GNUNET_hash_file into account */
- treedepth = GNUNET_ECRS_compute_depth (filesize);
-
- /* Test if file is indexed! */
- wasIndexed = GNUNET_FS_test_indexed (sock, &fileId);
-
- fd = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE);
- if (fd == -1)
+ if (NULL == msg)
{
- GNUNET_client_connection_destroy (sock);
- return GNUNET_SYSERR;
+ uc->state = UNINDEX_STATE_ERROR;
+ uc->emsg = GNUNET_strdup (_("Timeout waiting for `fs' service."));
+ GNUNET_FS_unindex_sync_ (uc);
+ signal_unindex_error (uc);
+ return;
}
- dblock =
- GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
- sizeof (GNUNET_EC_DBlock));
- dblock->size =
- htonl (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
- sizeof (GNUNET_EC_DBlock));
- dblock->anonymity_level = htonl (0);
- dblock->priority = htonl (0);
- dblock->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
- dblock->expiration_time = GNUNET_htonll (0);
- db = (GNUNET_EC_DBlock *) & dblock[1];
- db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
- iblocks =
- GNUNET_malloc (sizeof (GNUNET_DatastoreValue *) * (treedepth + 1));
- for (i = 0; i <= treedepth; i++)
+ if (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK)
{
- iblocks[i] =
- GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +
- GNUNET_ECRS_IBLOCK_SIZE + sizeof (GNUNET_EC_DBlock));
- iblocks[i]->size =
- htonl (sizeof (GNUNET_DatastoreValue) + sizeof (GNUNET_EC_DBlock));
- iblocks[i]->anonymity_level = htonl (0);
- iblocks[i]->priority = htonl (0);
- iblocks[i]->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
- iblocks[i]->expiration_time = GNUNET_htonll (0);
- ((GNUNET_EC_DBlock *) & iblocks[i][1])->type =
- htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
+ uc->state = UNINDEX_STATE_ERROR;
+ uc->emsg = GNUNET_strdup (_("Invalid response from `fs' service."));
+ GNUNET_FS_unindex_sync_ (uc);
+ signal_unindex_error (uc);
+ return;
}
+ uc->state = UNINDEX_STATE_DS_REMOVE;
+ GNUNET_FS_unindex_sync_ (uc);
+ GNUNET_FS_unindex_do_remove_ (uc);
+}
- pos = 0;
- while (pos < filesize)
+
+/**
+ * Connect to the datastore and remove the blocks.
+ *
+ * @param uc context for the unindex operation.
+ */
+void
+GNUNET_FS_unindex_do_remove_ (struct GNUNET_FS_UnindexContext *uc)
+{
+ uc->dsh = GNUNET_DATASTORE_connect (uc->h->cfg,
+ uc->h->sched);
+ if (NULL == uc->dsh)
{
- if (upcb != NULL)
- upcb (filesize, pos, eta, upcbClosure);
- if (tt != NULL)
- if (GNUNET_OK != tt (ttClosure))
- goto FAILURE;
- size = GNUNET_ECRS_DBLOCK_SIZE;
- if (size > filesize - pos)
- {
- size = filesize - pos;
- memset (&db[1], 0, GNUNET_ECRS_DBLOCK_SIZE);
- }
- dblock->size =
- htonl (sizeof (GNUNET_DatastoreValue) + size +
- sizeof (GNUNET_EC_DBlock));
- if (size != READ (fd, &db[1], size))
- {
- GNUNET_GE_LOG_STRERROR_FILE (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_USER |
- GNUNET_GE_ADMIN | GNUNET_GE_BULK,
- "READ", filename);
- goto FAILURE;
- }
- if (tt != NULL)
- if (GNUNET_OK != tt (ttClosure))
- goto FAILURE;
- GNUNET_EC_file_block_get_key (db, size + sizeof (GNUNET_EC_DBlock),
- &chk.key);
- GNUNET_EC_file_block_get_query (db, size + sizeof (GNUNET_EC_DBlock),
- &chk.query);
- if (GNUNET_OK != pushBlock (sock, &chk, 0, /* dblocks are on level 0 */
- iblocks))
- {
- GNUNET_GE_BREAK (ectx, 0);
- goto FAILURE;
- }
- if (!wasIndexed)
- {
- if (GNUNET_OK ==
- GNUNET_EC_file_block_encode (db, size, &chk.query, &value))
- {
- *value = *dblock; /* copy options! */
-#if STRICT_CHECKS
- if (GNUNET_OK != GNUNET_FS_delete (sock, value))
- {
- GNUNET_free (value);
- GNUNET_GE_BREAK (ectx, 0);
- goto FAILURE;
- }
-#else
- GNUNET_FS_delete (sock, value);
-#endif
- GNUNET_free (value);
- }
- else
- {
- goto FAILURE;
- }
- }
- pos += size;
- now = GNUNET_get_time ();
- eta = (GNUNET_CronTime) (start +
- (((double) (now - start) / (double) pos))
- * (double) filesize);
+ uc->state = UNINDEX_STATE_ERROR;
+ uc->emsg = GNUNET_strdup (_("Failed to connect to `datastore' service."));
+ GNUNET_FS_unindex_sync_ (uc);
+ signal_unindex_error (uc);
+ return;
}
- if (tt != NULL)
- if (GNUNET_OK != tt (ttClosure))
- goto FAILURE;
- for (i = 0; i < treedepth; i++)
+ uc->fh = GNUNET_DISK_file_open (uc->filename,
+ GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE);
+ if (NULL == uc->fh)
{
- size = ntohl (iblocks[i]->size) - sizeof (GNUNET_DatastoreValue);
- db = (GNUNET_EC_DBlock *) & iblocks[i][1];
- GNUNET_EC_file_block_get_key (db, size, &chk.key);
- GNUNET_EC_file_block_get_query (db, size, &chk.query);
- if (GNUNET_OK != pushBlock (sock, &chk, i + 1, iblocks))
- {
- GNUNET_GE_BREAK (ectx, 0);
- goto FAILURE;
- }
- GNUNET_EC_file_block_encode (db, size, &chk.query, &value);
-#if STRICT_CHECKS
- if (GNUNET_OK != GNUNET_FS_delete (sock, value))
- {
- GNUNET_free (value);
- GNUNET_GE_BREAK (ectx, 0);
- goto FAILURE;
- }
-#else
- GNUNET_FS_delete (sock, value);
-#endif
- GNUNET_free (value);
- GNUNET_free (iblocks[i]);
- iblocks[i] = NULL;
+ GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO);
+ uc->dsh = NULL;
+ uc->state = UNINDEX_STATE_ERROR;
+ uc->emsg = GNUNET_strdup (_("Failed to open file for unindexing."));
+ GNUNET_FS_unindex_sync_ (uc);
+ signal_unindex_error (uc);
+ return;
}
+ uc->tc = GNUNET_FS_tree_encoder_create (uc->h,
+ uc->file_size,
+ uc,
+ &unindex_reader,
+ &unindex_process,
+ &unindex_progress,
+ &unindex_finish);
+ GNUNET_FS_tree_encoder_next (uc->tc);
+}
+
+
+/**
+ * Function called once the hash of the file
+ * that is being unindexed has been computed.
+ *
+ * @param cls closure, unindex context
+ * @param file_id computed hash, NULL on error
+ */
+void
+GNUNET_FS_unindex_process_hash_ (void *cls,
+ const GNUNET_HashCode *file_id)
+{
+ struct GNUNET_FS_UnindexContext *uc = cls;
+ struct UnindexMessage req;
+
+ uc->fhc = NULL;
+ if (uc->state != UNINDEX_STATE_HASHING)
+ {
+ GNUNET_FS_unindex_stop (uc);
+ return;
+ }
+ if (file_id == NULL)
+ {
+ uc->state = UNINDEX_STATE_ERROR;
+ uc->emsg = GNUNET_strdup (_("Failed to compute hash of file."));
+ GNUNET_FS_unindex_sync_ (uc);
+ signal_unindex_error (uc);
+ return;
+ }
+ uc->file_id = *file_id;
+ uc->state = UNINDEX_STATE_FS_NOTIFY;
+ GNUNET_FS_unindex_sync_ (uc);
+ uc->client = GNUNET_CLIENT_connect (uc->h->sched,
+ "fs",
+ uc->h->cfg);
+ req.header.size = htons (sizeof (struct UnindexMessage));
+ req.header.type = htons (GNUNET_MESSAGE_TYPE_FS_UNINDEX);
+ req.reserved = 0;
+ req.file_id = *file_id;
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CLIENT_transmit_and_get_response (uc->client,
+ &req.header,
+ GNUNET_CONSTANTS_SERVICE_TIMEOUT,
+ GNUNET_YES,
+ &process_fs_response,
+ uc));
+}
+
- if (wasIndexed)
+/**
+ * Create SUSPEND event for the given unindex operation
+ * and then clean up our state (without stop signal).
+ *
+ * @param cls the 'struct GNUNET_FS_UnindexContext' to signal for
+ */
+void
+GNUNET_FS_unindex_signal_suspend_ (void *cls)
+{
+ struct GNUNET_FS_UnindexContext *uc = cls;
+ struct GNUNET_FS_ProgressInfo pi;
+
+ if (uc->fhc != NULL)
+ {
+ GNUNET_CRYPTO_hash_file_cancel (uc->fhc);
+ uc->fhc = NULL;
+ }
+ if (uc->client != NULL)
+ {
+ GNUNET_CLIENT_disconnect (uc->client, GNUNET_NO);
+ uc->client = NULL;
+ }
+ if (NULL != uc->dsh)
+ {
+ GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO);
+ uc->dsh = NULL;
+ }
+ if (NULL != uc->tc)
+ {
+ GNUNET_FS_tree_encoder_finish (uc->tc,
+ NULL,
+ NULL);
+ uc->tc = NULL;
+ }
+ if (uc->fh != NULL)
+ {
+ GNUNET_DISK_file_close (uc->fh);
+ uc->fh = NULL;
+ }
+ GNUNET_FS_end_top (uc->h, uc->top);
+ pi.status = GNUNET_FS_STATUS_UNINDEX_SUSPEND;
+ GNUNET_FS_unindex_make_status_ (&pi, uc,
+ (uc->state == UNINDEX_STATE_COMPLETE)
+ ? uc->file_size : 0);
+ GNUNET_break (NULL == uc->client_info);
+ GNUNET_free (uc->filename);
+ GNUNET_free_non_null (uc->serialization);
+ GNUNET_free (uc);
+}
+
+
+/**
+ * Unindex a file.
+ *
+ * @param h handle to the file sharing subsystem
+ * @param filename file to unindex
+ * @param cctx initial value for the client context
+ * @return NULL on error, otherwise handle
+ */
+struct GNUNET_FS_UnindexContext *
+GNUNET_FS_unindex_start (struct GNUNET_FS_Handle *h,
+ const char *filename,
+ void *cctx)
+{
+ struct GNUNET_FS_UnindexContext *ret;
+ struct GNUNET_FS_ProgressInfo pi;
+ uint64_t size;
+
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_size (filename,
+ &size,
+ GNUNET_YES))
+ return NULL;
+ ret = GNUNET_malloc (sizeof (struct GNUNET_FS_UnindexContext));
+ ret->h = h;
+ ret->filename = GNUNET_strdup (filename);
+ ret->start_time = GNUNET_TIME_absolute_get ();
+ ret->file_size = size;
+ ret->client_info = cctx;
+ GNUNET_FS_unindex_sync_ (ret);
+ pi.status = GNUNET_FS_STATUS_UNINDEX_START;
+ pi.value.unindex.eta = GNUNET_TIME_UNIT_FOREVER_REL;
+ GNUNET_FS_unindex_make_status_ (&pi, ret, 0);
+ ret->fhc = GNUNET_CRYPTO_hash_file (h->sched,
+ GNUNET_SCHEDULER_PRIORITY_IDLE,
+ filename,
+ HASHING_BLOCKSIZE,
+ &GNUNET_FS_unindex_process_hash_,
+ ret);
+ ret->top = GNUNET_FS_make_top (h,
+ &GNUNET_FS_unindex_signal_suspend_,
+ ret);
+ return ret;
+}
+
+
+/**
+ * Clean up after completion of an unindex operation.
+ *
+ * @param uc handle
+ */
+void
+GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc)
+{
+ struct GNUNET_FS_ProgressInfo pi;
+
+ if (uc->fhc != NULL)
+ {
+ GNUNET_CRYPTO_hash_file_cancel (uc->fhc);
+ uc->fhc = NULL;
+ }
+ if (uc->client != NULL)
+ {
+ GNUNET_CLIENT_disconnect (uc->client, GNUNET_NO);
+ uc->client = NULL;
+ }
+ if (NULL != uc->dsh)
+ {
+ GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO);
+ uc->dsh = NULL;
+ }
+ if (NULL != uc->tc)
+ {
+ GNUNET_FS_tree_encoder_finish (uc->tc,
+ NULL,
+ NULL);
+ uc->tc = NULL;
+ }
+ if (uc->fh != NULL)
+ {
+ GNUNET_DISK_file_close (uc->fh);
+ uc->fh = NULL;
+ }
+ GNUNET_FS_end_top (uc->h, uc->top);
+ if (uc->serialization != NULL)
{
- if (GNUNET_OK == undoSymlinking (ectx, filename, &fileId, sock))
- {
- if (GNUNET_OK !=
- GNUNET_FS_unindex (sock, GNUNET_ECRS_DBLOCK_SIZE, &fileId))
- {
- GNUNET_GE_BREAK (ectx, 0);
- goto FAILURE;
- }
- }
- else
- {
- GNUNET_GE_BREAK (ectx, 0);
- goto FAILURE;
- }
+ GNUNET_FS_remove_sync_file_ (uc->h, GNUNET_FS_SYNC_PATH_MASTER_UNINDEX, uc->serialization);
+ GNUNET_free (uc->serialization);
+ uc->serialization = NULL;
}
- GNUNET_free (iblocks[treedepth]);
- /* free resources */
- GNUNET_free (iblocks);
- GNUNET_free (dblock);
- CLOSE (fd);
- GNUNET_client_connection_destroy (sock);
- return GNUNET_OK;
-FAILURE:
- for (i = 0; i <= treedepth; i++)
- GNUNET_free_non_null (iblocks[i]);
- GNUNET_free (iblocks);
- GNUNET_free (dblock);
- CLOSE (fd);
- GNUNET_client_connection_destroy (sock);
- return GNUNET_SYSERR;
+ pi.status = GNUNET_FS_STATUS_UNINDEX_STOPPED;
+ pi.value.unindex.eta = GNUNET_TIME_UNIT_ZERO;
+ GNUNET_FS_unindex_make_status_ (&pi, uc,
+ (uc->state == UNINDEX_STATE_COMPLETE)
+ ? uc->file_size : 0);
+ GNUNET_break (NULL == uc->client_info);
+ GNUNET_free (uc->filename);
+ GNUNET_free (uc);
}
-/* end of unindex.c */
+/* end of fs_unindex.c */