📄 ondemand.c
字号:
{
GNUNET_free (dsvalue);
}
}
#endif
return datastore->putUpdate (&key, &odb.header);
}
/**
* Call datastore's delete method using the
* query and datastore value from the closure.
* (and free the closure).
*/
static void
async_delete_job (void *cls)
{
GNUNET_HashCode *query = cls;
GNUNET_DatastoreValue *dbv = (GNUNET_DatastoreValue *) & query[1];
datastore->del (query, dbv);
GNUNET_free (query);
}
/**
* Delete the query that still references the unavailable file. This
* must be done asynchronously since we are in the "get" iterator and
* a del operation during "get" would deadlock!
*/
static void
delete_content_asynchronously (const GNUNET_DatastoreValue * dbv,
const GNUNET_HashCode * query)
{
GNUNET_HashCode *ctx;
ctx = GNUNET_malloc (sizeof (GNUNET_HashCode) + ntohl (dbv->size));
*ctx = *query;
memcpy (&ctx[1], dbv, ntohl (dbv->size));
GNUNET_cron_add_job (coreAPI->cron, &async_delete_job, 0, 0, ctx);
}
/**
* A query on the datastore resulted in the on-demand
* block dbv. On-demand encode the block and return
* the resulting DSV in enc. If the on-demand
* encoding fails because the file is no longer there,
* this function also removes the OD-Entry
*
* @return GNUNET_OK on success, GNUNET_SYSERR if there was an error
*/
int
GNUNET_FS_ONDEMAND_get_indexed_content (const GNUNET_DatastoreValue * dbv,
const GNUNET_HashCode * query,
GNUNET_DatastoreValue ** enc)
{
char *fn;
char *iobuf;
int blen;
int fileHandle;
int ret;
const OnDemandBlock *odb;
GNUNET_EC_DBlock *db;
struct stat linkStat;
if ((ntohl (dbv->size) != sizeof (OnDemandBlock)) ||
(ntohl (dbv->type) != GNUNET_ECRS_BLOCKTYPE_ONDEMAND))
{
GNUNET_GE_BREAK (coreAPI->ectx, 0);
return GNUNET_SYSERR;
}
odb = (const OnDemandBlock *) dbv;
fn = get_indexed_filename (&odb->fileId);
if ((GNUNET_YES != GNUNET_disk_file_test (coreAPI->ectx,
fn)) ||
(-1 == (fileHandle = GNUNET_disk_file_open (coreAPI->ectx,
fn, O_LARGEFILE | O_RDONLY,
0))))
{
GNUNET_GE_LOG_STRERROR_FILE (coreAPI->ectx,
GNUNET_GE_WARNING | GNUNET_GE_ADMIN |
GNUNET_GE_USER | GNUNET_GE_BULK, "open",
fn);
/* Is the symlink (still) there? */
if (LSTAT (fn, &linkStat) == -1)
delete_content_asynchronously (dbv, query);
else
publish_unavailable_mark (&odb->fileId);
GNUNET_free (fn);
return GNUNET_SYSERR;
}
if (GNUNET_ntohll (odb->fileOffset) != LSEEK (fileHandle,
GNUNET_ntohll
(odb->fileOffset), SEEK_SET))
{
GNUNET_GE_LOG_STRERROR_FILE (coreAPI->ectx,
GNUNET_GE_WARNING | GNUNET_GE_ADMIN |
GNUNET_GE_USER | GNUNET_GE_BULK, "lseek",
fn);
GNUNET_free (fn);
CLOSE (fileHandle);
delete_content_asynchronously (dbv, query);
return GNUNET_SYSERR;
}
db = GNUNET_malloc (sizeof (GNUNET_EC_DBlock) + ntohl (odb->blockSize));
db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
iobuf = (char *) &db[1];
blen = READ (fileHandle, iobuf, ntohl (odb->blockSize));
if (blen != ntohl (odb->blockSize))
{
GNUNET_GE_LOG_STRERROR_FILE (coreAPI->ectx,
GNUNET_GE_WARNING | GNUNET_GE_ADMIN |
GNUNET_GE_USER | GNUNET_GE_BULK, "read",
fn);
GNUNET_free (fn);
GNUNET_free (db);
CLOSE (fileHandle);
delete_content_asynchronously (dbv, query);
return GNUNET_SYSERR;
}
CLOSE (fileHandle);
ret = GNUNET_EC_file_block_encode (db,
ntohl (odb->blockSize) +
sizeof (GNUNET_EC_DBlock), query, enc);
GNUNET_free (db);
GNUNET_free (fn);
if (ret == GNUNET_SYSERR)
{
GNUNET_GE_LOG (coreAPI->ectx,
GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
_
("Indexed content changed (does not match its hash).\n"));
delete_content_asynchronously (dbv, query);
return GNUNET_SYSERR;
}
(*enc)->anonymity_level = dbv->anonymity_level;
(*enc)->expiration_time = dbv->expiration_time;
(*enc)->priority = dbv->priority;
return GNUNET_OK;
}
/**
* Test if the file with the given ID is
* indexed.
* @return GNUNET_YES if so, GNUNET_NO if not.
*/
int
GNUNET_FS_ONDEMAND_test_indexed_file (GNUNET_Datastore_ServiceAPI * datastore,
const GNUNET_HashCode * fileId)
{
struct stat filestat;
char *fn;
fn = get_indexed_filename (fileId);
if (0 != STAT (fn, &filestat))
{
GNUNET_free (fn);
return GNUNET_NO;
}
GNUNET_free (fn);
return GNUNET_YES;
}
/**
* Unindex the file with the given ID. Removes the file from the
* filesystem and all of the corresponding obd blocks from the
* datastore. Note that the IBlocks are NOT removed by this function.
*
* @param blocksize the size of each of the
* indexed blocks (required to break
* up the file properly when computing
* the keys of the odb blocks).
*/
int
GNUNET_FS_ONDEMAND_delete_indexed_content (struct GNUNET_GE_Context *ectx,
GNUNET_Datastore_ServiceAPI *
datastore, unsigned int blocksize,
const GNUNET_HashCode * fileId)
{
char *fn;
int fd;
int ret;
OnDemandBlock odb;
GNUNET_HashCode key;
unsigned long long pos;
unsigned long long size;
unsigned long long delta;
GNUNET_EC_DBlock *block;
GNUNET_EncName enc;
fn = get_indexed_filename (fileId);
fd = GNUNET_disk_file_open (ectx, fn, O_RDONLY | O_LARGEFILE, 0);
if (fd == -1)
{
GNUNET_free (fn);
return GNUNET_SYSERR;
}
pos = 0;
if (GNUNET_OK != GNUNET_disk_file_size (ectx, fn, &size, GNUNET_YES))
{
GNUNET_free (fn);
return GNUNET_SYSERR;
}
block = GNUNET_malloc (sizeof (GNUNET_EC_DBlock) + blocksize);
block->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
while (pos < size)
{
delta = size - pos;
if (delta > blocksize)
delta = blocksize;
if (delta != READ (fd, &block[1], delta))
{
GNUNET_GE_LOG_STRERROR_FILE (ectx,
GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
GNUNET_GE_USER | GNUNET_GE_BULK,
"read", fn);
CLOSE (fd);
GNUNET_free (fn);
GNUNET_free (block);
return GNUNET_SYSERR;
}
odb.header.size = htonl (sizeof (OnDemandBlock));
odb.header.type = htonl (GNUNET_ECRS_BLOCKTYPE_ONDEMAND);
odb.header.priority = 0;
odb.header.anonymity_level = 0;
odb.header.expiration_time = 0;
odb.type = htonl (GNUNET_ECRS_BLOCKTYPE_ONDEMAND);
odb.fileOffset = GNUNET_htonll (pos);
odb.blockSize = htonl (delta);
odb.fileId = *fileId;
/* compute the primary key */
GNUNET_EC_file_block_get_query (block,
delta + sizeof (GNUNET_EC_DBlock),
&key);
if ((0 <
datastore->get (&key, GNUNET_ECRS_BLOCKTYPE_ONDEMAND,
&GNUNET_FS_HELPER_complete_value_from_database_callback,
&odb.header)) && (odb.header.expiration_time != 0))
ret = datastore->del (&key, &odb.header);
else /* not found */
ret = GNUNET_SYSERR;
if (ret == GNUNET_SYSERR)
{
IF_GELOG (ectx,
GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
GNUNET_hash_to_enc (&key, &enc));
GNUNET_GE_LOG (ectx,
GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
_
("Unindexed ODB block `%s' from offset %llu already missing from datastore.\n"),
&enc, pos);
}
pos += delta;
}
GNUNET_free (block);
CLOSE (fd);
UNLINK (fn);
GNUNET_free (fn);
remove_unavailable_mark (fileId);
return GNUNET_OK;
}
int
GNUNET_FS_ONDEMAND_init (GNUNET_CoreAPIForPlugins * capi)
{
char *tmp;
coreAPI = capi;
GNUNET_GC_get_configuration_value_filename (capi->cfg,
"GNUNETD",
"GNUNETD_HOME",
GNUNET_DEFAULT_DAEMON_VAR_DIRECTORY,
&tmp);
tmp = GNUNET_realloc (tmp, strlen (tmp) + strlen ("/data/shared/") + 1);
strcat (tmp, "/data/shared/");
GNUNET_GC_get_configuration_value_filename (capi->cfg,
"FS",
"INDEX-DIRECTORY",
tmp, &index_directory);
GNUNET_free (tmp);
GNUNET_disk_directory_create (coreAPI->ectx, index_directory); /* just in case */
state = capi->service_request ("state");
if (state == NULL)
{
GNUNET_GE_BREAK (coreAPI->ectx, 0);
GNUNET_free (index_directory);
return GNUNET_SYSERR;
}
datastore = capi->service_request ("datastore");
if (datastore == NULL)
{
GNUNET_GE_BREAK (coreAPI->ectx, 0);
coreAPI->service_release (state);
state = NULL;
GNUNET_free (index_directory);
return GNUNET_SYSERR;
}
return 0;
}
int
GNUNET_FS_ONDEMAND_done ()
{
coreAPI->service_release (state);
state = NULL;
coreAPI->service_release (datastore);
datastore = NULL;
GNUNET_free (index_directory);
index_directory = NULL;
return 0;
}
/* end of ondemand.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -