}
-/**
- * Given a block at the given offset and depth, calculate the offset
- * for the CHK at the given index.
- *
- * @param offset the offset of the first
- * DBLOCK in the subtree of the
- * identified IBLOCK
- * @param depth the depth of the IBLOCK in the tree, 0 for DBLOCK
- * @param k which CHK in the IBLOCK are we
- * talking about
- * @return offset if k=0, otherwise an appropriately
- * larger value (i.e., if depth = 1,
- * the returned value should be offset+k*DBLOCK_SIZE)
- */
-static uint64_t
-compute_dblock_offset (uint64_t offset,
- unsigned int depth,
- unsigned int k)
-{
- unsigned int i;
- uint64_t lsize; /* what is the size of the sum of all DBlocks
- that a CHK at depth i corresponds to? */
-
- if (depth == 0)
- return offset;
- lsize = DBLOCK_SIZE;
- for (i=1;i<depth;i++)
- lsize *= CHK_PER_INODE;
- return offset + k * lsize;
-}
-
-
/**
* Fill in all of the generic fields for a download event and call the
* callback.
* Try it for upward reconstruction of the data. On success,
* the top-level block will move to state BRS_DOWNLOAD_UP.
*
- * @param dr one of our request entries
+ * @param dc context for the download
+ * @param dr download request to match against
* @param data plaintext data, starting from the beginning of the file
* @param data_len number of bytes in data
*/
pi.value.download.specifics.progress.data_len = dlen;
pi.value.download.specifics.progress.depth = 0;
GNUNET_FS_download_make_status_ (&pi, dc);
- if (0 != truncate (dc->filename,
- GNUNET_ntohll (dc->uri->data.chk.file_length)))
+ if ( (NULL != dc->filename) &&
+ (0 != truncate (dc->filename,
+ GNUNET_ntohll (dc->uri->data.chk.file_length))) )
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
"truncate",
dc->filename);
child_block_size = GNUNET_FS_tree_compute_tree_size (drc->depth);
GNUNET_assert (0 == (drc->offset - dr->offset) % child_block_size);
chk_off = (drc->offset - dr->offset) / child_block_size;
- GNUNET_assert (drc->state == BRS_INIT);
- drc->state = BRS_CHK_SET;
- drc->chk = chks[chk_off];
- try_top_down_reconstruction (dc, drc);
+ if (drc->state == BRS_INIT)
+ {
+ drc->state = BRS_CHK_SET;
+ drc->chk = chks[chk_off];
+ try_top_down_reconstruction (dc, drc);
+ }
if (drc->state != BRS_DOWNLOAD_UP)
up_done = GNUNET_NO; /* children not all done */
}
* Schedule the download of the specified block in the tree.
*
* @param dc overall download this block belongs to
- * @param chk content-hash-key of the block
- * @param offset offset of the block in the file
- * (for IBlocks, the offset is the lowest
- * offset of any DBlock in the subtree under
- * the IBlock)
- * @param depth depth of the block, 0 is the root of the tree
+ * @param dr request to schedule
*/
static void
schedule_block_download (struct GNUNET_FS_DownloadContext *dc,
dr->depth,
GNUNET_h2s (&dr->chk.query));
#endif
- GNUNET_CONTAINER_DLL_insert (dc->pending_head,
- dc->pending_tail,
- dr);
- dr->is_pending = GNUNET_YES;
+ if (GNUNET_NO !=
+ GNUNET_CONTAINER_multihashmap_contains_value (dc->active,
+ &dr->chk.query,
+ dr))
+ return; /* already active */
GNUNET_CONTAINER_multihashmap_put (dc->active,
&dr->chk.query,
dr,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
if (dc->client == NULL)
return; /* download not active */
+ GNUNET_CONTAINER_DLL_insert (dc->pending_head,
+ dc->pending_tail,
+ dr);
+ dr->is_pending = GNUNET_YES;
if (NULL == dc->th)
dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client,
sizeof (struct SearchMessage),
{
struct GNUNET_FS_DownloadContext *dc = cls;
struct GNUNET_FS_DownloadContext *cpos;
- // struct GNUNET_DISK_FileHandle *fh;
char *temp_name;
- // const char *real_name;
char *fn;
char *us;
char *ext;
char *dn;
char *pos;
char *full_name;
+ char *sfn;
if (NULL == uri)
return; /* entry for the directory itself */
(NULL !=
strstr (dn + strlen(dn) - strlen(GNUNET_FS_DIRECTORY_EXT),
GNUNET_FS_DIRECTORY_EXT)) );
+ sfn = GNUNET_strdup (filename);
+ while ( (strlen (sfn) > 0) &&
+ (filename[strlen(sfn)-1] == '/') )
+ sfn[strlen(sfn)-1] = '\0';
if ( (strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) &&
(NULL !=
strstr (dn + strlen(dn) - strlen(GNUNET_FS_DIRECTORY_EXT),
"%s%s%s%s",
dn,
DIR_SEPARATOR_STR,
- filename,
+ sfn,
GNUNET_FS_DIRECTORY_EXT);
}
else
"%s%s%s",
dn,
DIR_SEPARATOR_STR,
- filename);
+ sfn);
}
+ GNUNET_free (sfn);
GNUNET_free (dn);
}
if ( (full_name != NULL) &&
}
temp_name = NULL;
-#if 0
- if (data != NULL)
- {
- if (GNUNET_FS_uri_chk_get_file_size (uri) == length)
- {
- if (full_name == NULL)
- {
- temp_name = GNUNET_DISK_mktemp ("gnunet-download-trd");
- real_name = temp_name;
- }
- else
- {
- real_name = full_name;
- }
- /* write to disk, then trigger normal download which will instantly progress to completion */
- fh = GNUNET_DISK_file_open (real_name,
- GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE,
- GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
- if (fh == NULL)
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
- "open",
- real_name);
- GNUNET_free (full_name);
- GNUNET_free_non_null (fn);
- return;
- }
- if (length !=
- GNUNET_DISK_file_write (fh,
- data,
- length))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
- "write",
- full_name);
- }
-#if DEBUG_DOWNLOAD
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Wrote %llu bytes of plaintext from meta data to `%s' for validation\n",
- (unsigned long long) length,
- real_name);
-#endif
- GNUNET_DISK_file_close (fh);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Length mismatch between supplied plaintext and expected file size (%llu != %llu)\n"),
- (unsigned long long) GNUNET_FS_uri_chk_get_file_size (uri),
- (unsigned long long) length);
- }
- }
-#endif
#if DEBUG_DOWNLOAD
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Triggering recursive download of size %llu with %u bytes MD\n",
chk = (struct ContentHashKey*) pt;
for (i=(prc->size / sizeof(struct ContentHashKey))-1;i>=0;i--)
{
- off = compute_dblock_offset (dr->offset,
- dr->depth,
- i);
drc = dr->children[i];
switch (drc->state)
{
dc->th = NULL;
}
GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO);
+ dc->in_receive = GNUNET_NO;
dc->client = NULL;
GNUNET_FS_free_download_request_ (dc->top_request);
dc->top_request = NULL;
dc);
GNUNET_assert (dc->th != NULL);
}
+ if (GNUNET_NO == dc->in_receive)
+ {
+ dc->in_receive = GNUNET_YES;
+ GNUNET_CLIENT_receive (dc->client,
+ &receive_results,
+ dc,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ }
return msize;
}
dc);
GNUNET_assert (dc->th != NULL);
}
- GNUNET_CLIENT_receive (client,
- &receive_results,
- dc,
- GNUNET_TIME_UNIT_FOREVER_REL);
}
struct GNUNET_FS_DownloadContext *dc = cls;
struct DownloadRequest *dr = entry;
+ dr->next = NULL;
+ dr->prev = NULL;
GNUNET_CONTAINER_DLL_insert (dc->pending_head,
dc->pending_tail,
dr);
&retry_entry,
dc);
GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO);
+ dc->in_receive = GNUNET_NO;
dc->client = NULL;
}
#if DEBUG_DOWNLOAD
GNUNET_assert (dc->client == NULL);
GNUNET_assert (dc->th == NULL);
dc->client = client;
- GNUNET_CLIENT_receive (client,
- &receive_results,
- dc,
- GNUNET_TIME_UNIT_FOREVER_REL);
pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE;
GNUNET_FS_download_make_status_ (&pi, dc);
+ dc->pending_head = NULL;
+ dc->pending_tail = NULL;
GNUNET_CONTAINER_multihashmap_iterate (dc->active,
&retry_entry,
dc);
if (NULL != dc->client)
{
GNUNET_CLIENT_disconnect (dc->client, GNUNET_NO);
+ dc->in_receive = GNUNET_NO;
dc->client = NULL;
}
+ dc->pending_head = NULL;
+ dc->pending_tail = NULL;
pi.status = GNUNET_FS_STATUS_DOWNLOAD_INACTIVE;
GNUNET_FS_download_make_status_ (&pi, dc);
}
* @param file_start_offset desired starting offset for the download
* in the original file; requesting tree should not contain
* DBLOCKs prior to the file_start_offset
- * @param file_length desired number of bytes the user wanted to access
+ * @param desired_length desired number of bytes the user wanted to access
* (from file_start_offset). Resulting tree should not contain
* DBLOCKs after file_start_offset + file_length.
* @return download request tree for the given range of DBLOCKs at
/**
* Task requesting the next block from the tree encoder.
*
+ * @param cls the 'struct GNUJNET_FS_DownloadContext' we're processing
* @param tc task context
*/
static void
/* no bytes required! */
if (dc->filename != NULL)
{
- fh = GNUNET_DISK_file_open (dc->filename != NULL
- ? dc->filename
- : dc->temp_filename,
+ fh = GNUNET_DISK_file_open (dc->filename,
GNUNET_DISK_OPEN_READWRITE |
GNUNET_DISK_OPEN_CREATE |
( (0 == GNUNET_FS_uri_chk_get_file_size (dc->uri))