Esempio n. 1
0
/**
 * Launch simple commands (commands without file I/O) and return response
 *
 * @param url       Target URL
 * @param method    HTTP method (GET/PUT/POST)
 * @param followloc Whether or not need to set CURLOPT_FOLLOWLOCATION
 * @param response  Response from remote service
 * @return 0 for success and non-zero value to indicate error
 */
static int launchCmd(const char *url, enum HttpHeader method,
                     enum Redirect followloc, struct Response **response)
{
    CURL *curl = NULL;
    CURLcode curlCode;
    int ret = 0;
    struct Response *resp = NULL;
    
    resp = calloc(1, sizeof(struct Response));
    if (!resp) {
        return ENOMEM;
    }
    ret = initResponseBuffer(&(resp->body));
    if (ret) {
        goto done;
    }
    ret = initResponseBuffer(&(resp->header));
    if (ret) {
        goto done;
    }
    initCurlGlobal();
    curl = curl_easy_init();
    if (!curl) {
        ret = ENOMEM;       // curl_easy_init does not return error code,
                            // and most of its errors are caused by malloc()
        fprintf(stderr, "ERROR in curl_easy_init.\n");
        goto done;
    }
    /* Set callback function for reading data from remote service */
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, resp->body);
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, writefunc);
    curl_easy_setopt(curl, CURLOPT_WRITEHEADER, resp->header);
    curl_easy_setopt(curl, CURLOPT_URL, url);
    switch(method) {
        case GET:
            break;
        case PUT:
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
            break;
        case POST:
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
            break;
        case DELETE:
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
            break;
        default:
            ret = EINVAL;
            fprintf(stderr, "ERROR: Invalid HTTP method\n");
            goto done;
    }
    if (followloc == YES) {
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
    }
    /* Now run the curl handler */
    curlCode = curl_easy_perform(curl);
    if (curlCode != CURLE_OK) {
        ret = EIO;
        fprintf(stderr, "ERROR: preform the URL %s failed, <%d>: %s\n",
                url, curlCode, curl_easy_strerror(curlCode));
    }
done:
    if (curl != NULL) {
        curl_easy_cleanup(curl);
    }
    if (ret) {
        free(resp);
        resp = NULL;
    }
    *response = resp;
    return ret;
}
Esempio n. 2
0
/**
 * The function does the write operation by connecting to a DataNode. 
 * The function keeps the connection with the DataNode until 
 * the closeFlag is set. Whenever the current data has been sent out, 
 * the function blocks waiting for further input from user or close.
 *
 * @param url           URL of the remote DataNode
 * @param method        PUT for create and POST for append
 * @param uploadBuffer  Buffer storing user's data to write
 * @param response      Response from remote service
 * @return 0 for success and non-zero value to indicate error
 */
static int launchWrite(const char *url, enum HttpHeader method,
                       struct webhdfsBuffer *uploadBuffer,
                       struct Response **response)
{
    CURLcode curlCode;
    struct Response* resp = NULL;
    struct curl_slist *chunk = NULL;
    CURL *curl = NULL;
    int ret = 0;
    
    if (!uploadBuffer) {
        fprintf(stderr, "ERROR: upload buffer is NULL!\n");
        return EINVAL;
    }
    
    initCurlGlobal();
    resp = calloc(1, sizeof(struct Response));
    if (!resp) {
        return ENOMEM;
    }
    ret = initResponseBuffer(&(resp->body));
    if (ret) {
        goto done;
    }
    ret = initResponseBuffer(&(resp->header));
    if (ret) {
        goto done;
    }
    
    // Connect to the datanode in order to create the lease in the namenode
    curl = curl_easy_init();
    if (!curl) {
        fprintf(stderr, "ERROR: failed to initialize the curl handle.\n");
        return ENOMEM;
    }
    curl_easy_setopt(curl, CURLOPT_URL, url);
    
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, resp->body);
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, writefunc);
    curl_easy_setopt(curl, CURLOPT_WRITEHEADER, resp->header);
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, readfunc);
    curl_easy_setopt(curl, CURLOPT_READDATA, uploadBuffer);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    
    chunk = curl_slist_append(chunk, "Transfer-Encoding: chunked");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
    chunk = curl_slist_append(chunk, "Expect:");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
    
    switch(method) {
        case PUT:
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
            break;
        case POST:
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
            break;
        default:
            ret = EINVAL;
            fprintf(stderr, "ERROR: Invalid HTTP method\n");
            goto done;
    }
    curlCode = curl_easy_perform(curl);
    if (curlCode != CURLE_OK) {
        ret = EIO;
        fprintf(stderr, "ERROR: preform the URL %s failed, <%d>: %s\n",
                url, curlCode, curl_easy_strerror(curlCode));
    }
    
done:
    if (chunk != NULL) {
        curl_slist_free_all(chunk);
    }
    if (curl != NULL) {
        curl_easy_cleanup(curl);
    }
    if (ret) {
        free(resp);
        resp = NULL;
    }
    *response = resp;
    return ret;
}
static int hdfsReadImpl(hdfsFS fs, hdfsFile file, void* buffer, tSize off,
                        tSize length, tSize *numRead)
{
    int ret = 0;
    char *url = NULL;
    struct Response *resp = NULL;

    if (fs == NULL || file == NULL || file->type != INPUT || buffer == NULL ||
            length < 0) {
        ret = EINVAL;
        goto done;
    }
    if (length == 0) {
        // Special case: the user supplied a buffer of zero length, so there is
        // nothing to do.
        *numRead = 0;
        goto done;
    }
    resp = calloc(1, sizeof(*resp)); // resp is actually a pointer type
    if (!resp) {
        ret = ENOMEM;
        goto done;
    }
    ret = initResponseBuffer(&(resp->header));
    if (ret) {
        goto done;
    }
    ret = initResponseBuffer(&(resp->body));
    if (ret) {
        goto done;
    }
    memset(buffer, 0, length);
    resp->body->content = buffer;
    resp->body->remaining = length;
    
    ret = createUrlForOPEN(fs->nn, fs->port, file->file->absPath,
                           fs->userName, off, length, &url);
    if (ret) {
        goto done;
    }
    ret = launchOPEN(url, resp);
    if (ret) {
        goto done;
    }
    ret = parseOPEN(resp->header->content, resp->body->content);
    if (ret == -1) {
        // Special case: if parseOPEN returns -1, we asked for a byte range
        // with outside what the file contains.  In this case, hdfsRead and
        // hdfsPread return 0, meaning end-of-file.
        *numRead = 0;
    } else if (ret == 0) {
        *numRead = (tSize) resp->body->offset;
    }
done:
    if (resp) {
        freeResponseBuffer(resp->header);
        free(resp->body);
    }
    free(resp);
    free(url);
    return ret;
}