Beispiel #1
0
/*!
** @brief request that a content chunk be loaded into the local machine's
** content cache.
**
** XrequestChunk() is called by a client application to load a content chunk 
** into the XIA content cache. It does not return the requested data, it only
** causes the chunk to be loaded into the local content cache. XgetChunkStatus() 
** may be called to get the status of the chunk to determine when it becomes 
** available. Once the chunk is ready to be read, XreadChunk() should be called 
** get the actual content chunk data.
**
** XrequestChunk() is a simple wrapper around the XrequestChunks() API call.
**
** @param sockfd the control socket (must be of type XSOCK_CHUNK)
** @param dag Content ID of this chunk
** @param dagLen length of dag (currently not used)
**
** @returns 0 on success
** @returns -1 if the requested chunk could not be located or a socket error
** occurred. If the error is a socket error, errno set will be set with an 
** appropriate code.
*/
int XrequestChunk(int sockfd, char* dag, size_t /* dagLen */)
{
	ChunkStatus cs;

	cs.cid = dag;
	cs.cidLen = strlen(dag);

	return XrequestChunks(sockfd, &cs, 1);
}
Beispiel #2
0
int getListedChunks(int csock, FILE *fd, char *chunks, char *p_ad, char *p_hid)
{
	ChunkStatus cs[NUM_CHUNKS];
	char data[XIA_MAXCHUNK];
	int len;
	int status;
	int n = -1;
	
	
	n = buildChunkDAGs(cs, chunks, p_ad, p_hid);
	
	// NOTE: the chunk transport is not currently reliable and chunks may need to be re-requested
	// ask for the current chunk list again every REREQUEST seconds
	// chunks already in the local cache will not be refetched from the network 
	unsigned ctr = 0;
	while (1) {
		if (ctr % REREQUEST == 0) {
			// bring the list of chunks local
			say("%srequesting list of %d chunks\n", (ctr == 0 ? "" : "re-"), n);
			if (XrequestChunks(csock, cs, n) < 0) {
				say("unable to request chunks\n");
				return -1;
			}
			say("checking chunk status\n");
			ctr++;
		}

		status = XgetChunkStatuses(csock, cs, n);

		if (status == READY_TO_READ)
			break;

		else if (status < 0) {
			say("error getting chunk status\n");
			return -1;

		} else if (status & WAITING_FOR_CHUNK) {
			// one or more chunks aren't ready.
			say("waiting... one or more chunks aren't ready yet\n");
		
		} else if (status & INVALID_HASH) {
			die(-1, "one or more chunks has an invalid hash");
		
		} else if (status & REQUEST_FAILED) {
			die(-1, "no chunks found\n");

		} else {
			say("unexpected result\n");
		}
		sleep(1);
	}

	say("all chunks ready\n");

	for (int i = 0; i < n; i++) {
		char *cid = strrchr(cs[i].cid, ':');
		cid++;
		say("reading chunk %s\n", cid);
		if ((len = XreadChunk(csock, data, sizeof(data), 0, cs[i].cid, cs[i].cidLen)) < 0) {
			say("error getting chunk\n");
			return -1;
		}

		// write the chunk to disk
//		say("writing %d bytes of chunk %s to disk\n", len, cid);
		fwrite(data, 1, len, fd);

		free(cs[i].cid);
		cs[i].cid = NULL;
		cs[i].cidLen = 0;
	}

	return n;
}
Beispiel #3
0
/*!
** @brief request that a list of content chunks be loaded into the local 
** machine's content cache.
**
** XrequestChunks() is called by a client application to load a content chunk 
** into the XIA content cache. It does not return the requested data, it only
** causes the chunk to be loaded into the local content cache. XgetChunkStatuses() 
** may be called to get the status of the chunk to determine when it becomes 
** available. Once the chunk is ready to be read, XreadChunk() should be called 
** get the actual content chunk data.
**
** XrequestChunk() can be used when only a single chunk is requested.
**
** @param sockfd the control socket (must be of type XSOCK_CHUNK)
** @param chunks A list of content DAGs to retrieve
** @param numChunks number of CIDs in the chunk list
**
** @returns 0 on success
** @returns -1 if one or more of the requested chunks could not be located 
** or a socket error occurred. If the error is a socket error, errno set 
** will be set with an appropriate code.
*/
int XrequestChunks(int sockfd, const ChunkStatus *chunks, int numChunks)
{
	int rc;
	const char *buf="Chunk request";//Maybe send more useful information here.

	if (validateSocket(sockfd, XSOCK_CHUNK, EAFNOSUPPORT) < 0) {
		LOGF("Socket %d must be a chunk socket", sockfd);
		return -1;
	}

	if (numChunks == 0)
		return 0;

	if (!chunks) {
		LOG("null pointer error!");
		errno = EFAULT;
		return -1;
	}
	
	// If the DAG list is too long for a UDP packet to click, replace with multiple calls
	if (numChunks > 300) //TODO: Make this more precise
	{
		rc = 0;
		int i;
		for (i = 0; i < numChunks; i += 300)
		{
			int num = (numChunks-i > 300) ? 300 : numChunks-i;
			int rv = XrequestChunks(sockfd, &chunks[i], num);

			if (rv == -1) {
				perror("XrequestChunk(): requestChunk failed");
				return(-1);
			} else {
				rc += rv;
			}
		}

		return rc;
	}
	
	xia::XSocketMsg xsm;
	xsm.set_type(xia::XREQUESTCHUNK);

	xia::X_Requestchunk_Msg *x_requestchunk_msg = xsm.mutable_x_requestchunk();
  
	for (int i = 0; i < numChunks; i++) {
		if (chunks[i].cid != NULL)
			x_requestchunk_msg->add_dag(chunks[i].cid);
		else {
			LOGF("NULL pointer at chunks[%d]\n", i);
		}
	}

	if (x_requestchunk_msg->dag_size() == 0) {
		// FIXME: what error should this relate to?
		errno = EFAULT;
		LOG("No dags specified\n");
		return -1;
	}

	x_requestchunk_msg->set_payload((const char*)buf, strlen(buf)+1);

	std::string p_buf;
	xsm.SerializeToString(&p_buf);

	if ((rc = click_data(sockfd, &xsm)) < 0) {
		LOGF("Error talking to Click: %s", strerror(errno));
		return -1;
	}

#if 0	
	// process the reply from click
	if ((rc = click_reply2(sockfd, &type)) < 0) {
		LOGF("Error getting status from Click: %s", strerror(errno));
		return -1;
	}
#endif

	return 0;
}
int getListedChunks(int csock, FILE *fd, char *chunks, char *p_ad, char *p_hid)
{
	ChunkStatus cs[NUM_CHUNKS];
	char data[XIA_MAXCHUNK];
	int len;
	int status;
	int n = -1;
	
	
	n = buildChunkDAGs(cs, chunks, p_ad, p_hid);
	
	// bring the list of chunks local
	say("requesting list of %d chunks\n", n);
	if (XrequestChunks(csock, cs, n) < 0) {
		say("unable to request chunks\n");
		return -1;
	}
	
	say("checking chunk status\n");
	while (1) {
		status = XgetChunkStatuses(csock, cs, n);

		if (status == READY_TO_READ)
			break;

		else if (status < 0) {
			say("error getting chunk status\n");
			return -1;

		} else if (status & WAITING_FOR_CHUNK) {
			// one or more chunks aren't ready.
			say("waiting... one or more chunks aren't ready yet\n");
		
		} else if (status & INVALID_HASH) {
			die(-1, "one or more chunks has an invalid hash");
		
		} else if (status & REQUEST_FAILED) {
			die(-1, "no chunks found\n");

		} else {
			say("unexpected result\n");
		}
		sleep(1);
	}

	say("all chunks ready\n");

	for (int i = 0; i < n; i++) {
		char *cid = strrchr(cs[i].cid, ':');
		cid++;
		say("reading chunk %s\n", cid);
		if ((len = XreadChunk(csock, data, sizeof(data), 0, cs[i].cid, cs[i].cidLen)) < 0) {
			say("error getting chunk\n");
			return -1;
		}

		// write the chunk to disk
//		say("writing %d bytes of chunk %s to disk\n", len, cid);
		fwrite(data, 1, len, fd);

		free(cs[i].cid);
		cs[i].cid = NULL;
		cs[i].cidLen = 0;
	}

	return n;
}