/*! ** @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); }
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; }
/*! ** @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; }