Example #1
0
gridfs_offset gridfile_read(gridfile* gfile, gridfs_offset size, char* buf)

{
    mongo_cursor* chunks;
    bson chunk;

    int first_chunk;
    int last_chunk;
    int total_chunks;
    gridfs_offset chunksize;
    gridfs_offset contentlength;
    gridfs_offset bytes_left;
    int i;
    bson_iterator it;
    gridfs_offset chunk_len;
    const char * chunk_data;

    contentlength = gridfile_get_contentlength(gfile);
    chunksize = gridfile_get_chunksize(gfile);
    size = (contentlength - gfile->pos < size)
           ? contentlength - gfile->pos
           : size;
    bytes_left = size;

    first_chunk = (gfile->pos)/chunksize;
    last_chunk = (gfile->pos+size-1)/chunksize;
    total_chunks = last_chunk - first_chunk + 1;
    chunks = gridfile_get_chunks(gfile, first_chunk, total_chunks);

    for (i = 0; i < total_chunks; i++) {
        mongo_cursor_next(chunks);
        chunk = chunks->current;
        bson_find(&it, &chunk, "data");
        chunk_len = bson_iterator_bin_len( &it );
        chunk_data = bson_iterator_bin_data( &it );
        if (i == 0) {
            chunk_data += (gfile->pos)%chunksize;
            chunk_len -= (gfile->pos)%chunksize;
        }
        if (bytes_left > chunk_len) {
            memcpy(buf, chunk_data, chunk_len);
            bytes_left -= chunk_len;
            buf += chunk_len;
        } else {
            memcpy(buf, chunk_data, bytes_left);
        }
    }

    mongo_cursor_destroy(chunks);
    gfile->pos = gfile->pos + size;

    return size;
}
Example #2
0
gridfs_offset gridfile_write_file( gridfile *gfile, FILE *stream ) {
    int i;
    size_t len;
    bson chunk;
    bson_iterator it;
    const char *data;
    const int num = gridfile_get_numchunks( gfile );

    for ( i=0; i<num; i++ ) {
        chunk = gridfile_get_chunk( gfile, i );
        bson_find( &it, &chunk, "data" );
        len = bson_iterator_bin_len( &it );
        data = bson_iterator_bin_data( &it );
        fwrite( data , sizeof( char ), len, stream );
        bson_destroy( &chunk );
    }

    return gridfile_get_contentlength( gfile );
}
Example #3
0
gridfs_offset gridfile_write_buffer(gridfile* gfile, char * buf)

{
  int i;
  gridfs_offset len;
  bson chunk;
  bson_iterator it;
  const char* data;
  const int num = gridfile_get_numchunks( gfile );
 
  for ( i = 0; i < num; i++ ){
    chunk = gridfile_get_chunk( gfile, i );
    bson_find( &it, &chunk, "data" );
    len = bson_iterator_bin_len( &it );
    data = bson_iterator_bin_data( &it );
    memcpy( buf, data, len);
    buf += len;
  }
  
  return gridfile_get_contentlength(gfile);
}
static ngx_int_t ngx_http_gridfs_handler(ngx_http_request_t* request) {
    ngx_http_gridfs_loc_conf_t* gridfs_conf;
    ngx_http_core_loc_conf_t* core_conf;
    ngx_buf_t* buffer;
    ngx_chain_t out;
    ngx_str_t location_name;
    ngx_str_t full_uri;
    char* value;
    ngx_http_mongo_connection_t *mongo_conn;
    gridfs gfs;
    gridfile gfile;
    gridfs_offset length;
    ngx_uint_t numchunks;
    char* contenttype;
    char* md5;
    bson_date_t last_modified;

    volatile ngx_uint_t i;
    ngx_int_t rc = NGX_OK;
    bson query;
    bson_oid_t oid;
    mongo_cursor ** cursors;
    gridfs_offset chunk_len;
    const char * chunk_data;
    bson_iterator it;
    bson chunk;
    ngx_pool_cleanup_t* gridfs_cln;
    ngx_http_gridfs_cleanup_t* gridfs_clndata;
    int status;
    volatile ngx_uint_t e = FALSE;
    volatile ngx_uint_t ecounter = 0;
    uint64_t range_start = 0;
    uint64_t range_end   = 0;
    uint64_t current_buf_pos = 0;

    gridfs_conf = ngx_http_get_module_loc_conf(request, ngx_http_gridfs_module);
    core_conf = ngx_http_get_module_loc_conf(request, ngx_http_core_module);

    // ---------- ENSURE MONGO CONNECTION ---------- //

    mongo_conn = ngx_http_get_mongo_connection( gridfs_conf->mongo );
    if (mongo_conn == NULL) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Mongo Connection not found: \"%V\"", &gridfs_conf->mongo);
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    if (mongo_conn->conn.connected == 0) {
        if (ngx_http_mongo_reconnect(request->connection->log, mongo_conn) == NGX_ERROR) {
            ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                          "Could not connect to mongo: \"%V\"", &gridfs_conf->mongo);
            if(mongo_conn->conn.connected) { mongo_disconnect(&mongo_conn->conn); }
            return NGX_HTTP_SERVICE_UNAVAILABLE;
        }
        if (ngx_http_mongo_reauth(request->connection->log, mongo_conn) == NGX_ERROR) {
            ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                          "Failed to reauth to mongo: \"%V\"", &gridfs_conf->mongo);
            if(mongo_conn->conn.connected) { mongo_disconnect(&mongo_conn->conn); }
            return NGX_HTTP_SERVICE_UNAVAILABLE;
        }
    }

    // ---------- RETRIEVE KEY ---------- //

    location_name = core_conf->name;
    full_uri = request->uri;

    if (full_uri.len < location_name.len) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Invalid location name or uri.");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    value = (char*)malloc(sizeof(char) * (full_uri.len - location_name.len + 1));
    if (value == NULL) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Failed to allocate memory for value buffer.");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    memcpy(value, full_uri.data + location_name.len, full_uri.len - location_name.len);
    value[full_uri.len - location_name.len] = '\0';

    if (!url_decode(value)) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Malformed request.");
        free(value);
        return NGX_HTTP_BAD_REQUEST;
    }

    // ---------- RETRIEVE GRIDFILE ---------- //

    bson_init(&query);
    switch (gridfs_conf->type) {
    case  BSON_OID:
        bson_oid_from_string(&oid, value);
        bson_append_oid(&query, (char*)gridfs_conf->field.data, &oid);
        break;
    case BSON_INT:
      bson_append_int(&query, (char*)gridfs_conf->field.data, ngx_atoi((u_char*)value, strlen(value)));
        break;
    case BSON_STRING:
        bson_append_string(&query, (char*)gridfs_conf->field.data, value);
        break;
    }
    bson_finish(&query);

    do {
        e = FALSE;
        if (gridfs_init(&mongo_conn->conn,
                        (const char*)gridfs_conf->db.data,
                        (const char*)gridfs_conf->root_collection.data,
                        &gfs) != MONGO_OK
            || (status = gridfs_find_query(&gfs, &query, &gfile) == MONGO_ERROR)) {
            e = TRUE; ecounter++;
            if (ecounter > MONGO_MAX_RETRIES_PER_REQUEST
                || ngx_http_mongo_reconnect(request->connection->log, mongo_conn) == NGX_ERROR
                || ngx_http_mongo_reauth(request->connection->log, mongo_conn) == NGX_ERROR) {
                ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                              "Mongo connection dropped, could not reconnect");
                if(&mongo_conn->conn.connected) { mongo_disconnect(&mongo_conn->conn); }
                bson_destroy(&query);
                free(value);
                return NGX_HTTP_SERVICE_UNAVAILABLE;
            }
        }
    } while (e);

    bson_destroy(&query);
    free(value);

    /* Get information about the file */
    length = gridfile_get_contentlength(&gfile);
    numchunks = gridfile_get_numchunks(&gfile);

    // NaN workaround
    if (numchunks > INT_MAX)
    {
        gridfile_destroy(&gfile);
        gridfs_destroy(&gfs);
        return NGX_HTTP_NOT_FOUND;
    }

    contenttype = (char*)gridfile_get_contenttype(&gfile);

    md5 = (char*)gridfile_get_md5(&gfile);
    last_modified = gridfile_get_uploaddate(&gfile);

    // ---------- Partial Range
    // set follow-fork-mode child
    // attach (pid)
    // break ngx_http_gridfs_module.c:959

    if (request->headers_in.range) {
        gridfs_parse_range(request, &request->headers_in.range->value, &range_start, &range_end, length);
    }

    // ---------- SEND THE HEADERS ---------- //

    if (range_start == 0 && range_end == 0) {
        request->headers_out.status = NGX_HTTP_OK;
        request->headers_out.content_length_n = length;
    } else {
        request->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
        request->headers_out.content_length_n = length;
        //request->headers_out.content_range = range_end - range_start + 1;

        ngx_table_elt_t   *content_range;

        content_range = ngx_list_push(&request->headers_out.headers);
        if (content_range == NULL) {
            return NGX_ERROR;
        }

        request->headers_out.content_range = content_range;

        content_range->hash = 1;
        ngx_str_set(&content_range->key, "Content-Range");

        content_range->value.data = ngx_pnalloc(request->pool,sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);
        if (content_range->value.data == NULL) {
            return NGX_ERROR;
        }

        /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
        content_range->value.len = ngx_sprintf(content_range->value.data,
                                               "bytes %O-%O/%O",
                                               range_start, range_end,
                                               request->headers_out.content_length_n)
            - content_range->value.data;

        request->headers_out.content_length_n = range_end - range_start + 1;
    }
    if (contenttype != NULL) {
        request->headers_out.content_type.len = strlen(contenttype);
        request->headers_out.content_type.data = (u_char*)contenttype;
    }
    else ngx_http_set_content_type(request);

    // use md5 field as ETag if possible
    if (md5 != NULL) {
        request->headers_out.etag = ngx_list_push(&request->headers_out.headers);
        request->headers_out.etag->hash = 1;
        request->headers_out.etag->key.len = sizeof("ETag") - 1;
        request->headers_out.etag->key.data = (u_char*)"ETag";

        ngx_buf_t *b;
        b = ngx_create_temp_buf(request->pool, strlen(md5) + 2);
        b->last = ngx_sprintf(b->last, "\"%s\"", md5);
        request->headers_out.etag->value.len = strlen(md5) + 2;
        request->headers_out.etag->value.data = b->start;
    }

    // use uploadDate field as last_modified if possible
    if (last_modified) {
        request->headers_out.last_modified_time = (time_t)(last_modified/1000);
    }

    /* Determine if content is gzipped, set headers accordingly */
    if ( gridfile_get_boolean(&gfile,"gzipped") ) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, gridfile_get_field(&gfile,"gzipped") );
        request->headers_out.content_encoding = ngx_list_push(&request->headers_out.headers);
        if (request->headers_out.content_encoding == NULL) {
            gridfile_destroy(&gfile);
            gridfs_destroy(&gfs);
            return NGX_ERROR;
        }
        request->headers_out.content_encoding->hash = 1;
        request->headers_out.content_encoding->key.len = sizeof("Content-Encoding") - 1;
        request->headers_out.content_encoding->key.data = (u_char *) "Content-Encoding";
        request->headers_out.content_encoding->value.len = sizeof("gzip") - 1;
        request->headers_out.content_encoding->value.data = (u_char *) "gzip";
    }

    ngx_http_send_header(request);

    // ---------- SEND THE BODY ---------- //

    /* Empty file */
    if (numchunks == 0) {
        /* Allocate space for the response buffer */
        buffer = ngx_pcalloc(request->pool, sizeof(ngx_buf_t));
        if (buffer == NULL) {
            ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                          "Failed to allocate response buffer");
            gridfile_destroy(&gfile);
            gridfs_destroy(&gfs);
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        buffer->pos = NULL;
        buffer->last = NULL;
        buffer->memory = 1;
        buffer->last_buf = 1;
        out.buf = buffer;
        out.next = NULL;

        gridfile_destroy(&gfile);
        gridfs_destroy(&gfs);

        return ngx_http_output_filter(request, &out);
    }

    cursors = (mongo_cursor **)ngx_pcalloc(request->pool, sizeof(mongo_cursor *) * numchunks);
    if (cursors == NULL) {
      gridfile_destroy(&gfile);
      gridfs_destroy(&gfs);
      return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ngx_memzero( cursors, sizeof(mongo_cursor *) * numchunks);

    /* Hook in the cleanup function */
    gridfs_cln = ngx_pool_cleanup_add(request->pool, sizeof(ngx_http_gridfs_cleanup_t));
    if (gridfs_cln == NULL) {
      gridfile_destroy(&gfile);
      gridfs_destroy(&gfs);
      return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    gridfs_cln->handler = ngx_http_gridfs_cleanup;
    gridfs_clndata = gridfs_cln->data;
    gridfs_clndata->cursors = cursors;
    gridfs_clndata->numchunks = numchunks;

    /* Read and serve chunk by chunk */
    for (i = 0; i < numchunks; i++) {

        /* Allocate space for the response buffer */
        buffer = ngx_pcalloc(request->pool, sizeof(ngx_buf_t));
        if (buffer == NULL) {
            ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                          "Failed to allocate response buffer");
            gridfile_destroy(&gfile);
            gridfs_destroy(&gfs);
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        /* Fetch the chunk from mongo */
        do {
            e = FALSE;
            cursors[i] = gridfile_get_chunks(&gfile, i, 1);
            if (!(cursors[i] && mongo_cursor_next(cursors[i]) == MONGO_OK)) {
                e = TRUE; ecounter++;
                if (ecounter > MONGO_MAX_RETRIES_PER_REQUEST
                    || ngx_http_mongo_reconnect(request->connection->log, mongo_conn) == NGX_ERROR
                    || ngx_http_mongo_reauth(request->connection->log, mongo_conn) == NGX_ERROR) {
                    ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                                  "Mongo connection dropped, could not reconnect");
                    if(mongo_conn->conn.connected) { mongo_disconnect(&mongo_conn->conn); }
                    gridfile_destroy(&gfile);
                    gridfs_destroy(&gfs);
                    return NGX_HTTP_SERVICE_UNAVAILABLE;
                }
            }
        } while (e);

        chunk = cursors[i]->current;
        bson_find(&it, &chunk, "data");
        chunk_len = bson_iterator_bin_len( &it ); // break ngx_http_gridfs_module.c:1099
        chunk_data = bson_iterator_bin_data( &it );

        if (range_start == 0 && range_end == 0) {
            /* <<no range request>> */
            /* Set up the buffer chain */
            buffer->pos = (u_char*)chunk_data;
            buffer->last = (u_char*)chunk_data + chunk_len;
            buffer->memory = 1;
            buffer->last_buf = (i == numchunks-1);
            out.buf = buffer;
            out.next = NULL;

            /* Serve the Chunk */
            rc = ngx_http_output_filter(request, &out);
        } else {
            /* <<range request>> */
            if ( range_start >= (current_buf_pos+chunk_len) ||
                 range_end <= current_buf_pos) {
                /* no output */
                ngx_pfree(request->pool, buffer);
            } else {
                if (range_start <= current_buf_pos) {
                    buffer->pos = (u_char*)chunk_data;
                } else {
                    buffer->pos = (u_char*)chunk_data + (range_start - current_buf_pos);
                }
                if (range_end < (current_buf_pos+chunk_len)) {
                    buffer->last = (u_char*)chunk_data + (range_end - current_buf_pos + 1);
                } else {
                    buffer->last = (u_char*)chunk_data + chunk_len;
                }
                if (buffer->pos == buffer->last) {
                    ngx_log_error(NGX_LOG_ALERT, request->connection->log, 0,
                                  "zero size buf in writer "
                                  "range_start:%d range_end:%d "
                                  "current_buf_pos:%d chunk_len:%d i:%d numchunk:%d",
                                  range_start,range_end,
                                  current_buf_pos, chunk_len,
                                  i,numchunks);
                }
                buffer->memory = 1;
                buffer->last_buf = (i == numchunks-1) || (range_end < (current_buf_pos+chunk_len));
                out.buf = buffer;
                out.next = NULL;

                /* Serve the Chunk */
                rc = ngx_http_output_filter(request, &out);
            }
        }

        current_buf_pos += chunk_len;

        /* TODO: More Codes to Catch? */
        if (rc == NGX_ERROR) {
            gridfile_destroy(&gfile);
            gridfs_destroy(&gfs);
            return NGX_ERROR;
        }
    }

    gridfile_destroy(&gfile);
    gridfs_destroy(&gfs);

    return rc;
}
static ngx_int_t ngx_http_gridfs_handler(ngx_http_request_t* request) {
    ngx_http_gridfs_loc_conf_t* gridfs_conf;
    ngx_http_core_loc_conf_t* core_conf;
    ngx_buf_t* buffer;
    ngx_chain_t out;
    ngx_str_t location_name;
    ngx_str_t full_uri;
    // --------------- xulin add start -------------------
    char* ml_args;
    char* arg;
    unsigned int add_arg;
    unsigned int add_len; 
    // --------------- xulin add end -------------------
    char* value;
    ngx_http_mongo_connection_t *mongo_conn;
    gridfs gfs;
    gridfile gfile;
    gridfs_offset length;
    ngx_uint_t numchunks;
    char* contenttype;
    char* md5;
    bson_date_t last_modified;

    volatile ngx_uint_t i;
    ngx_int_t rc = NGX_OK;
    bson query;
    bson_oid_t oid;
    mongo_cursor ** cursors;
    gridfs_offset chunk_len;
    const char * chunk_data;
    bson_iterator it;
    bson chunk;
    ngx_pool_cleanup_t* gridfs_cln;
    ngx_http_gridfs_cleanup_t* gridfs_clndata;
    int status;
    volatile ngx_uint_t e = FALSE; 
    volatile ngx_uint_t ecounter = 0;

    gridfs_conf = ngx_http_get_module_loc_conf(request, ngx_http_gridfs_module);
    core_conf = ngx_http_get_module_loc_conf(request, ngx_http_core_module);

    // ---------- ENSURE MONGO CONNECTION ---------- //

    mongo_conn = ngx_http_get_mongo_connection( gridfs_conf->mongo );
    if (mongo_conn == NULL) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Mongo Connection not found: \"%V\"", &gridfs_conf->mongo);
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    
    if ( !(&mongo_conn->conn.connected)
         && (ngx_http_mongo_reconnect(request->connection->log, mongo_conn) == NGX_ERROR
             || ngx_http_mongo_reauth(request->connection->log, mongo_conn) == NGX_ERROR)) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Could not connect to mongo: \"%V\"", &gridfs_conf->mongo);
        if(&mongo_conn->conn.connected) { mongo_disconnect(&mongo_conn->conn); }
        return NGX_HTTP_SERVICE_UNAVAILABLE;
    }

    // ---------- RETRIEVE KEY ---------- //

    location_name = core_conf->name;
    full_uri = request->uri;

    if (full_uri.len < location_name.len) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Invalid location name or uri.");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    value = (char*)malloc(sizeof(char) * (full_uri.len - location_name.len + 1 + request->args.len + 1));
    if (value == NULL) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Failed to allocate memory for value buffer.");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    memcpy(value, full_uri.data + location_name.len, full_uri.len - location_name.len);
    
    // ------------------------------------ xulin add start --------------------------------------
    if (request->args.len > 0)
    {  
        ml_args = (char*)malloc(sizeof(char) * (request->args.len + 1));
        memcpy(ml_args, request->args.data, request->args.len);
        ml_args[request->args.len] = '\0';
        
        add_len = full_uri.len - location_name.len;
        memcpy(value + add_len, "?", 1);
        add_len += 1;
        arg = strtok(ml_args, "&");
        while (arg != NULL)
        {
            add_arg = 1;
            if (strstr(arg, "xc_md5") != NULL)
            {
                 add_arg = 0;
            }
            else if (strstr(arg, "_xingcloud_t") != NULL)
            {     
                 add_arg = 0;
            }        
            
            if (add_arg == 1)
            {
                 memcpy(value + add_len, arg, strlen(arg));
                 add_len += strlen(arg);
                 memcpy(value + add_len, "&", 1);
                 add_len += 1;
            }
            
            arg = strtok(NULL, "&");
        }
        
        free(ml_args);
        if (value[add_len - 1] == '?' || value[add_len - 1] == '&')
        {
            value[add_len - 1] = '\0';
        }
        else
        {
            value[add_len] = '\0';
        }
    }
    ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, "ml_url = [%s]", value);
    // ------------------------------------ xulin add end --------------------------------------


    if (!url_decode(value)) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Malformed request.");
        free(value);
        return NGX_HTTP_BAD_REQUEST;
    }

    // ---------- RETRIEVE GRIDFILE ---------- //

    do {
        e = FALSE;
        if (gridfs_init(&mongo_conn->conn,
                        (const char*)gridfs_conf->db.data,
                        (const char*)gridfs_conf->root_collection.data,
                        &gfs) != MONGO_OK) {
            e = TRUE; ecounter++;
            if (ecounter > MONGO_MAX_RETRIES_PER_REQUEST
                || ngx_http_mongo_reconnect(request->connection->log, mongo_conn) == NGX_ERROR
                || ngx_http_mongo_reauth(request->connection->log, mongo_conn) == NGX_ERROR) {
                ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                              "Mongo connection dropped, could not reconnect");
                if(&mongo_conn->conn.connected) { mongo_disconnect(&mongo_conn->conn); }
                free(value);
                return NGX_HTTP_SERVICE_UNAVAILABLE;
            }
        }
    } while (e);

    bson_init(&query);
    switch (gridfs_conf->type) {
    case  BSON_OID:
        bson_oid_from_string(&oid, value);
        bson_append_oid(&query, (char*)gridfs_conf->field.data, &oid);
        break;
    case BSON_INT:
      bson_append_int(&query, (char*)gridfs_conf->field.data, ngx_atoi((u_char*)value, strlen(value)));
        break;
    case BSON_STRING:
        bson_append_string(&query, (char*)gridfs_conf->field.data, value);
        break;
    }
    bson_finish(&query);

    status = gridfs_find_query(&gfs, &query, &gfile);
    
    bson_destroy(&query);
    free(value);

    if(status == MONGO_ERROR) {
        gridfs_destroy(&gfs);
        return NGX_HTTP_NOT_FOUND;
    }

    /* Get information about the file */
    length = gridfile_get_contentlength(&gfile);
    numchunks = gridfile_get_numchunks(&gfile);
    contenttype = (char*)gridfile_get_contenttype(&gfile);

    md5 = (char*)gridfile_get_md5(&gfile);
    last_modified = gridfile_get_uploaddate(&gfile);

    // ---------- SEND THE HEADERS ---------- //

    request->headers_out.status = NGX_HTTP_OK;
    request->headers_out.content_length_n = length;
    if (contenttype != NULL) {
        request->headers_out.content_type.len = strlen(contenttype);
        request->headers_out.content_type.data = (u_char*)contenttype;
    }
    else ngx_http_set_content_type(request);

    // use md5 field as ETag if possible
    if (md5 != NULL) {
        request->headers_out.etag = ngx_list_push(&request->headers_out.headers);
        request->headers_out.etag->hash = 1;
        request->headers_out.etag->key.len = sizeof("ETag") - 1;
        request->headers_out.etag->key.data = (u_char*)"ETag";

        ngx_buf_t *b;  
        b = ngx_create_temp_buf(request->pool, strlen(md5) + 2);  
        b->last = ngx_sprintf(b->last, "\"%s\"", md5);
        request->headers_out.etag->value.len = strlen(md5) + 2;
        request->headers_out.etag->value.data = b->start;
    }
    
    // use uploadDate field as last_modified if possible
    if (last_modified) {
        request->headers_out.last_modified_time = (time_t)(last_modified/1000);
    }

    /* Determine if content is gzipped, set headers accordingly */
    if ( gridfile_get_boolean(&gfile,"gzipped") ) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, gridfile_get_field(&gfile,"gzipped") );
        request->headers_out.content_encoding = ngx_list_push(&request->headers_out.headers);
        if (request->headers_out.content_encoding == NULL) {
            gridfile_destroy(&gfile);
            gridfs_destroy(&gfs);
            return NGX_ERROR;
        }
        request->headers_out.content_encoding->hash = 1;
        request->headers_out.content_encoding->key.len = sizeof("Content-Encoding") - 1;
        request->headers_out.content_encoding->key.data = (u_char *) "Content-Encoding";
        request->headers_out.content_encoding->value.len = sizeof("gzip") - 1;
        request->headers_out.content_encoding->value.data = (u_char *) "gzip";
    }

    ngx_http_send_header(request);

    // ---------- SEND THE BODY ---------- //

    /* Empty file */
    if (numchunks == 0) {
        /* Allocate space for the response buffer */
        buffer = ngx_pcalloc(request->pool, sizeof(ngx_buf_t));
        if (buffer == NULL) {
            ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                          "Failed to allocate response buffer");
            gridfile_destroy(&gfile);
            gridfs_destroy(&gfs);
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        buffer->pos = NULL;
        buffer->last = NULL;
        buffer->memory = 1;
        buffer->last_buf = 1;
        out.buf = buffer;
        out.next = NULL;

        gridfile_destroy(&gfile);
        gridfs_destroy(&gfs);

        return ngx_http_output_filter(request, &out);
    }
    
    cursors = (mongo_cursor **)ngx_pcalloc(request->pool, sizeof(mongo_cursor *) * numchunks);
    if (cursors == NULL) {
      gridfile_destroy(&gfile);
      gridfs_destroy(&gfs);
      return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    
    ngx_memzero( cursors, sizeof(mongo_cursor *) * numchunks);

    /* Hook in the cleanup function */
    gridfs_cln = ngx_pool_cleanup_add(request->pool, sizeof(ngx_http_gridfs_cleanup_t));
    if (gridfs_cln == NULL) {
      gridfile_destroy(&gfile);
      gridfs_destroy(&gfs);
      return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    gridfs_cln->handler = ngx_http_gridfs_cleanup;
    gridfs_clndata = gridfs_cln->data;
    gridfs_clndata->cursors = cursors;
    gridfs_clndata->numchunks = numchunks;

    /* Read and serve chunk by chunk */
    for (i = 0; i < numchunks; i++) {

        /* Allocate space for the response buffer */
        buffer = ngx_pcalloc(request->pool, sizeof(ngx_buf_t));
        if (buffer == NULL) {
            ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                          "Failed to allocate response buffer");
            gridfile_destroy(&gfile);
            gridfs_destroy(&gfs);
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        /* Fetch the chunk from mongo */
        do {
            e = FALSE;
            cursors[i] = gridfile_get_chunks(&gfile, i, 1);
            if (!(cursors[i] && mongo_cursor_next(cursors[i]) == MONGO_OK)) {
                e = TRUE; ecounter++;
                if (ecounter > MONGO_MAX_RETRIES_PER_REQUEST 
                    || ngx_http_mongo_reconnect(request->connection->log, mongo_conn) == NGX_ERROR
                    || ngx_http_mongo_reauth(request->connection->log, mongo_conn) == NGX_ERROR) {
                    ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                                  "Mongo connection dropped, could not reconnect");
                    if(&mongo_conn->conn.connected) { mongo_disconnect(&mongo_conn->conn); }
                    gridfile_destroy(&gfile);
                    gridfs_destroy(&gfs);
                    return NGX_HTTP_SERVICE_UNAVAILABLE;
                }
            }
        } while (e);

        chunk = cursors[i]->current;
        bson_find(&it, &chunk, "data");
        chunk_len = bson_iterator_bin_len( &it );
        chunk_data = bson_iterator_bin_data( &it );

        /* Set up the buffer chain */
        buffer->pos = (u_char*)chunk_data;
        buffer->last = (u_char*)chunk_data + chunk_len;
        buffer->memory = 1;
        buffer->last_buf = (i == numchunks-1);
        out.buf = buffer;
        out.next = NULL;

        /* Serve the Chunk */
        rc = ngx_http_output_filter(request, &out);

        /* TODO: More Codes to Catch? */
        if (rc == NGX_ERROR) {
            gridfile_destroy(&gfile);
            gridfs_destroy(&gfs);
            return NGX_ERROR;
        }
    }

    gridfile_destroy(&gfile);
    gridfs_destroy(&gfs);

    return rc;
}
Example #6
0
int test_bson_generic( void ) {

   bson_iterator it, it2, it3;
   bson_oid_t oid;
   bson_timestamp_t ts;
   bson_timestamp_t ts_result;
   bson b[1];
   bson copy[1];
   bson scope[1];

   ts.i = 1;
   ts.t = 2;

   bson_init( b );
   bson_append_double( b, "d", 3.14 );
   bson_append_string( b, "s", "hello" );
   bson_append_string_n( b, "s_n", "goodbye cruel world", 7 );

   {
       bson_append_start_object( b, "o" );
       bson_append_start_array( b, "a" );
       bson_append_binary( b, "0", 8, "w\0rld", 5 );
       bson_append_finish_object( b );
       bson_append_finish_object( b );
   }

   bson_append_undefined( b, "u" );

   bson_oid_from_string( &oid, "010203040506070809101112" );
   ASSERT( !memcmp( oid.bytes, "\x001\x002\x003\x004\x005\x006\x007\x008\x009\x010\x011\x012", 12 ) );
   bson_append_oid( b, "oid", &oid );

   bson_append_bool( b, "b", 1 );
   bson_append_date( b, "date", 0x0102030405060708 );
   bson_append_null( b, "n" );
   bson_append_regex( b, "r", "^asdf", "imx" );
   /* no dbref test (deprecated) */
   bson_append_code( b, "c", "function(){}" );
   bson_append_code_n( b, "c_n", "function(){}garbage", 12 );
   bson_append_symbol( b, "symbol", "symbol" );
   bson_append_symbol_n( b, "symbol_n", "symbol and garbage", 6 );

   {
       bson_init( scope );
       bson_append_int( scope, "i", 123 );
       bson_finish( scope );

       bson_append_code_w_scope( b, "cws", "function(){return i}", scope );
       bson_destroy( scope );
   }

   bson_append_timestamp( b, "timestamp", &ts );
   bson_append_long( b, "l", 0x1122334455667788 );

   /* Ensure that we can't copy a non-finished object. */
   ASSERT( bson_copy( copy, b ) == BSON_ERROR );

   bson_finish( b );

   ASSERT( b->err == BSON_VALID );

   /* Test append after finish. */
   ASSERT( bson_append_string( b, "foo", "bar" ) == BSON_ERROR );
   ASSERT( b->err & BSON_ALREADY_FINISHED );

   ASSERT( bson_copy( copy, b ) == BSON_OK );

   ASSERT( 1 == copy->finished );
   ASSERT( 0 == copy->err );

   bson_destroy( copy );

   bson_print( b );

   bson_iterator_init( &it, b );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_DOUBLE );
   ASSERT( bson_iterator_type( &it ) == BSON_DOUBLE );
   ASSERT( !strcmp( bson_iterator_key( &it ), "d" ) );
   ASSERT( bson_iterator_double( &it ) == 3.14 );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_STRING );
   ASSERT( bson_iterator_type( &it ) == BSON_STRING );
   ASSERT( !strcmp( bson_iterator_key( &it ), "s" ) );
   ASSERT( !strcmp( bson_iterator_string( &it ), "hello" ) );
   ASSERT( strcmp( bson_iterator_string( &it ), "" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_STRING );
   ASSERT( bson_iterator_type( &it ) == BSON_STRING );
   ASSERT( !strcmp( bson_iterator_key( &it ), "s_n" ) );
   ASSERT( !strcmp( bson_iterator_string( &it ), "goodbye" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_OBJECT );
   ASSERT( bson_iterator_type( &it ) == BSON_OBJECT );
   ASSERT( !strcmp( bson_iterator_key( &it ), "o" ) );
   bson_iterator_subiterator( &it, &it2 );

   ASSERT( bson_iterator_more( &it2 ) );
   ASSERT( bson_iterator_next( &it2 ) == BSON_ARRAY );
   ASSERT( bson_iterator_type( &it2 ) == BSON_ARRAY );
   ASSERT( !strcmp( bson_iterator_key( &it2 ), "a" ) );
   bson_iterator_subiterator( &it2, &it3 );

   ASSERT( bson_iterator_more( &it3 ) );
   ASSERT( bson_iterator_next( &it3 ) == BSON_BINDATA );
   ASSERT( bson_iterator_type( &it3 ) == BSON_BINDATA );
   ASSERT( !strcmp( bson_iterator_key( &it3 ), "0" ) );
   ASSERT( bson_iterator_bin_type( &it3 ) == 8 );
   ASSERT( bson_iterator_bin_len( &it3 ) == 5 );
   ASSERT( !memcmp( bson_iterator_bin_data( &it3 ), "w\0rld", 5 ) );

   ASSERT( bson_iterator_more( &it3 ) );
   ASSERT( bson_iterator_next( &it3 ) == BSON_EOO );
   ASSERT( bson_iterator_type( &it3 ) == BSON_EOO );
   ASSERT( !bson_iterator_more( &it3 ) );

   ASSERT( bson_iterator_more( &it2 ) );
   ASSERT( bson_iterator_next( &it2 ) == BSON_EOO );
   ASSERT( bson_iterator_type( &it2 ) == BSON_EOO );
   ASSERT( !bson_iterator_more( &it2 ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_UNDEFINED );
   ASSERT( bson_iterator_type( &it ) == BSON_UNDEFINED );
   ASSERT( !strcmp( bson_iterator_key( &it ), "u" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_OID );
   ASSERT( bson_iterator_type( &it ) == BSON_OID );
   ASSERT( !strcmp( bson_iterator_key( &it ), "oid" ) );
   ASSERT( !memcmp( bson_iterator_oid( &it )->bytes, "\x001\x002\x003\x004\x005\x006\x007\x008\x009\x010\x011\x012", 12 ) );
   ASSERT( bson_iterator_oid( &it )->ints[0] == oid.ints[0] );
   ASSERT( bson_iterator_oid( &it )->ints[1] == oid.ints[1] );
   ASSERT( bson_iterator_oid( &it )->ints[2] == oid.ints[2] );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_BOOL );
   ASSERT( bson_iterator_type( &it ) == BSON_BOOL );
   ASSERT( !strcmp( bson_iterator_key( &it ), "b" ) );
   ASSERT( bson_iterator_bool( &it ) == 1 );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_DATE );
   ASSERT( bson_iterator_type( &it ) == BSON_DATE );
   ASSERT( !strcmp( bson_iterator_key( &it ), "date" ) );
   ASSERT( bson_iterator_date( &it ) == 0x0102030405060708 );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_NULL );
   ASSERT( bson_iterator_type( &it ) == BSON_NULL );
   ASSERT( !strcmp( bson_iterator_key( &it ), "n" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_REGEX );
   ASSERT( bson_iterator_type( &it ) == BSON_REGEX );
   ASSERT( !strcmp( bson_iterator_key( &it ), "r" ) );
   ASSERT( !strcmp( bson_iterator_regex( &it ), "^asdf" ) );
   ASSERT( !strcmp( bson_iterator_regex_opts( &it ), "imx" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_CODE );
   ASSERT( bson_iterator_type( &it ) == BSON_CODE );
   ASSERT( !strcmp( bson_iterator_code(&it), "function(){}") );
   ASSERT( !strcmp( bson_iterator_key( &it ), "c" ) );
   ASSERT( !strcmp( bson_iterator_string( &it ), "" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_CODE );
   ASSERT( bson_iterator_type( &it ) == BSON_CODE );
   ASSERT( !strcmp( bson_iterator_key( &it ), "c_n" ) );
   ASSERT( !strcmp( bson_iterator_string( &it ), "" ) );
   ASSERT( !strcmp( bson_iterator_code( &it ), "function(){}" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_SYMBOL );
   ASSERT( bson_iterator_type( &it ) == BSON_SYMBOL );
   ASSERT( !strcmp( bson_iterator_key( &it ), "symbol" ) );
   ASSERT( !strcmp( bson_iterator_string( &it ), "symbol" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_SYMBOL );
   ASSERT( bson_iterator_type( &it ) == BSON_SYMBOL );
   ASSERT( !strcmp( bson_iterator_key( &it ), "symbol_n" ) );
   ASSERT( !strcmp( bson_iterator_string( &it ), "symbol" ) );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_CODEWSCOPE );
   ASSERT( bson_iterator_type( &it ) == BSON_CODEWSCOPE );
   ASSERT( !strcmp( bson_iterator_key( &it ), "cws" ) );
   ASSERT( !strcmp( bson_iterator_code( &it ), "function(){return i}" ) );

   {
       bson scope;
       bson_iterator_code_scope( &it, &scope );
       bson_iterator_init( &it2, &scope );

       ASSERT( bson_iterator_more( &it2 ) );
       ASSERT( bson_iterator_next( &it2 ) == BSON_INT );
       ASSERT( bson_iterator_type( &it2 ) == BSON_INT );
       ASSERT( !strcmp( bson_iterator_key( &it2 ), "i" ) );
       ASSERT( bson_iterator_int( &it2 ) == 123 );

       ASSERT( bson_iterator_more( &it2 ) );
       ASSERT( bson_iterator_next( &it2 ) == BSON_EOO );
       ASSERT( bson_iterator_type( &it2 ) == BSON_EOO );
       ASSERT( !bson_iterator_more( &it2 ) );
   }

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_TIMESTAMP );
   ASSERT( bson_iterator_type( &it ) == BSON_TIMESTAMP );
   ASSERT( !strcmp( bson_iterator_key( &it ), "timestamp" ) );
   ts_result = bson_iterator_timestamp( &it );
   ASSERT( ts_result.i == 1 );
   ASSERT( ts_result.t == 2 );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_LONG );
   ASSERT( bson_iterator_type( &it ) == BSON_LONG );
   ASSERT( !strcmp( bson_iterator_key( &it ), "l" ) );
   ASSERT( bson_iterator_long( &it ) == 0x1122334455667788 );

   ASSERT( bson_iterator_more( &it ) );
   ASSERT( bson_iterator_next( &it ) == BSON_EOO );
   ASSERT( bson_iterator_type( &it ) == BSON_EOO );
   ASSERT( !bson_iterator_more( &it ) );

   bson_destroy( b );

   {
       bson bsrc[1];
       bson_init( bsrc );
       bson_append_double( bsrc, "d", 3.14 );
       bson_finish( bsrc );
       ASSERT( bsrc->err == BSON_VALID );
       bson_init( b );
       bson_append_double( b, "", 3.14 ); /* test empty name (in general) */
       bson_iterator_init( &it, bsrc );
       ASSERT( bson_iterator_more( &it ) );
       ASSERT( bson_iterator_next( &it ) == BSON_DOUBLE );
       ASSERT( bson_iterator_type( &it ) == BSON_DOUBLE );
       bson_append_element( b, "d", &it );
       bson_append_element( b, 0, &it ); /* test null */
       bson_append_element( b, "", &it ); /* test empty name */
       bson_finish( b );
       ASSERT( b->err == BSON_VALID );
       /* bson_print( b ); */
       bson_iterator_init( &it, b );
       ASSERT( bson_iterator_more( &it ) );
       ASSERT( bson_iterator_next( &it ) == BSON_DOUBLE );
       ASSERT( !strcmp( bson_iterator_key( &it ), "" ) );
       ASSERT( bson_iterator_double( &it ) == 3.14 );
       ASSERT( bson_iterator_more( &it ) );
       ASSERT( bson_iterator_next( &it ) == BSON_DOUBLE );
       ASSERT( !strcmp( bson_iterator_key( &it ), "d" ) );
       ASSERT( bson_iterator_double( &it ) == 3.14 );
       ASSERT( bson_iterator_more( &it ) );
       ASSERT( bson_iterator_next( &it ) == BSON_DOUBLE );
       ASSERT( !strcmp( bson_iterator_key( &it ), "d" ) );
       ASSERT( bson_iterator_double( &it ) == 3.14 );
       ASSERT( bson_iterator_more( &it ) );
       ASSERT( bson_iterator_next( &it ) == BSON_DOUBLE );
       ASSERT( !strcmp( bson_iterator_key( &it ), "" ) );
       ASSERT( bson_iterator_double( &it ) == 3.14 );
       ASSERT( bson_iterator_more( &it ) );
       ASSERT( bson_iterator_next( &it ) == BSON_EOO );
       ASSERT( !bson_iterator_more( &it ) );
       bson_destroy( bsrc );
       bson_destroy( b );
   }

   return 0;
}
Example #7
0
int main(int argc, char *argv[])
{
    bson_buffer bb;
    bson b;
    bson_iterator it, it2, it3;
    bson_oid_t oid;

    bson_buffer_init(&bb);
    bson_append_double(&bb, "d", 3.14);
    bson_append_string(&bb, "s", "hello");

    {
        bson_buffer *obj = bson_append_start_object(&bb, "o");
        bson_buffer *arr = bson_append_start_array(obj, "a");
        bson_append_binary(arr, "0", 8, "w\0rld", 5);
        bson_append_finish_object(arr);
        bson_append_finish_object(obj);
    }

    bson_append_undefined(&bb, "u");

    bson_oid_from_string(&oid, "010203040506070809101112");
    ASSERT(!memcmp(oid.bytes, "\x001\x002\x003\x004\x005\x006\x007\x008\x009\x010\x011\x012", 12));
    bson_append_oid(&bb, "oid", &oid);

    bson_append_bool(&bb, "b", 1);
    bson_append_date(&bb, "date", 0x0102030405060708ULL);
    bson_append_null(&bb, "n");
    bson_append_regex(&bb, "r", "^asdf", "imx");
    /* no dbref test (deprecated) */
    bson_append_code(&bb, "c", "function(){}");
    bson_append_symbol(&bb, "symbol", "SYMBOL");

    {
        bson_buffer scope_buf;
        bson scope;
        bson_buffer_init(&scope_buf);
        bson_append_int(&scope_buf, "i", 123);
        bson_from_buffer(&scope, &scope_buf);

        bson_append_code_w_scope(&bb, "cws", "function(){return i}", &scope);
        bson_destroy(&scope);
    }

    /* no timestamp test (internal) */
    bson_append_long(&bb, "l", 0x1122334455667788ULL);

    bson_from_buffer(&b, &bb);

    bson_iterator_init(&it, b.data);
    
    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_double);
    ASSERT(bson_iterator_type(&it) == bson_double);
    ASSERT(!strcmp(bson_iterator_key(&it), "d"));
    ASSERT(bson_iterator_double(&it) == 3.14);

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_string);
    ASSERT(bson_iterator_type(&it) == bson_string);
    ASSERT(!strcmp(bson_iterator_key(&it), "s"));
    ASSERT(!strcmp(bson_iterator_string(&it), "hello"));

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_object);
    ASSERT(bson_iterator_type(&it) == bson_object);
    ASSERT(!strcmp(bson_iterator_key(&it), "o"));
    bson_iterator_subiterator(&it, &it2);

    ASSERT(bson_iterator_more(&it2));
    ASSERT(bson_iterator_next(&it2) == bson_array);
    ASSERT(bson_iterator_type(&it2) == bson_array);
    ASSERT(!strcmp(bson_iterator_key(&it2), "a"));
    bson_iterator_subiterator(&it2, &it3);

    ASSERT(bson_iterator_more(&it3));
    ASSERT(bson_iterator_next(&it3) == bson_bindata);
    ASSERT(bson_iterator_type(&it3) == bson_bindata);
    ASSERT(!strcmp(bson_iterator_key(&it3), "0"));
    ASSERT(bson_iterator_bin_type(&it3) == 8);
    ASSERT(bson_iterator_bin_len(&it3) == 5);
    ASSERT(!memcmp(bson_iterator_bin_data(&it3), "w\0rld", 5));
    
    ASSERT(bson_iterator_more(&it3));
    ASSERT(bson_iterator_next(&it3) == bson_eoo);
    ASSERT(bson_iterator_type(&it3) == bson_eoo);
    ASSERT(!bson_iterator_more(&it3));

    ASSERT(bson_iterator_more(&it2));
    ASSERT(bson_iterator_next(&it2) == bson_eoo);
    ASSERT(bson_iterator_type(&it2) == bson_eoo);
    ASSERT(!bson_iterator_more(&it2));

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_undefined);
    ASSERT(bson_iterator_type(&it) == bson_undefined);
    ASSERT(!strcmp(bson_iterator_key(&it), "u"));


    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_oid);
    ASSERT(bson_iterator_type(&it) == bson_oid);
    ASSERT(!strcmp(bson_iterator_key(&it), "oid"));
    ASSERT(!memcmp(bson_iterator_oid(&it)->bytes, "\x001\x002\x003\x004\x005\x006\x007\x008\x009\x010\x011\x012", 12));
    ASSERT(bson_iterator_oid(&it)->ints[0] == oid.ints[0]);
    ASSERT(bson_iterator_oid(&it)->ints[1] == oid.ints[1]);
    ASSERT(bson_iterator_oid(&it)->ints[2] == oid.ints[2]);

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_bool);
    ASSERT(bson_iterator_type(&it) == bson_bool);
    ASSERT(!strcmp(bson_iterator_key(&it), "b"));
    ASSERT(bson_iterator_bool(&it) == 1);

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_date);
    ASSERT(bson_iterator_type(&it) == bson_date);
    ASSERT(!strcmp(bson_iterator_key(&it), "date"));
    ASSERT(bson_iterator_date(&it) == 0x0102030405060708ULL);

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_null);
    ASSERT(bson_iterator_type(&it) == bson_null);
    ASSERT(!strcmp(bson_iterator_key(&it), "n"));

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_regex);
    ASSERT(bson_iterator_type(&it) == bson_regex);
    ASSERT(!strcmp(bson_iterator_key(&it), "r"));
    ASSERT(!strcmp(bson_iterator_regex(&it), "^asdf"));
    ASSERT(!strcmp(bson_iterator_regex_opts(&it), "imx"));

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_code);
    ASSERT(bson_iterator_type(&it) == bson_code);
    ASSERT(!strcmp(bson_iterator_key(&it), "c"));
    ASSERT(!strcmp(bson_iterator_string(&it), "function(){}"));
    ASSERT(!strcmp(bson_iterator_code(&it), "function(){}"));

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_symbol);
    ASSERT(bson_iterator_type(&it) == bson_symbol);
    ASSERT(!strcmp(bson_iterator_key(&it), "symbol"));
    ASSERT(!strcmp(bson_iterator_string(&it), "SYMBOL"));

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_codewscope);
    ASSERT(bson_iterator_type(&it) == bson_codewscope);
    ASSERT(!strcmp(bson_iterator_key(&it), "cws"));
    ASSERT(!strcmp(bson_iterator_code(&it), "function(){return i}"));

    {
        bson scope;
        bson_iterator_code_scope(&it, &scope);
        bson_iterator_init(&it2, scope.data);

        ASSERT(bson_iterator_more(&it2));
        ASSERT(bson_iterator_next(&it2) == bson_int);
        ASSERT(bson_iterator_type(&it2) == bson_int);
        ASSERT(!strcmp(bson_iterator_key(&it2), "i"));
        ASSERT(bson_iterator_int(&it2) == 123);

        ASSERT(bson_iterator_more(&it2));
        ASSERT(bson_iterator_next(&it2) == bson_eoo);
        ASSERT(bson_iterator_type(&it2) == bson_eoo);
        ASSERT(!bson_iterator_more(&it2));
    }

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_long);
    ASSERT(bson_iterator_type(&it) == bson_long);
    ASSERT(!strcmp(bson_iterator_key(&it), "l"));
    ASSERT(bson_iterator_long(&it) == 0x1122334455667788ULL);

    ASSERT(bson_iterator_more(&it));
    ASSERT(bson_iterator_next(&it) == bson_eoo);
    ASSERT(bson_iterator_type(&it) == bson_eoo);
    ASSERT(!bson_iterator_more(&it));
    
    return 0;
}
Example #8
0
void lua_push_bson_value(lua_State *L, bson_iterator *it) {
    bson_type bt = bson_iterator_type(it);
    switch (bt) {
        case BSON_OID:
        {
            char xoid[25];
            bson_oid_to_string(bson_iterator_oid(it), xoid);
            lua_pushstring(L, xoid);
            break;
        }
        case BSON_STRING:
        case BSON_SYMBOL:
            lua_pushstring(L, bson_iterator_string(it));
            break;
        case BSON_NULL:
        case BSON_UNDEFINED:
            lua_push_bsontype_table(L, bt);
            break;
        case BSON_INT:
            lua_pushinteger(L, bson_iterator_int(it));
            break;
        case BSON_LONG:
        case BSON_DOUBLE:
            lua_pushnumber(L, (lua_Number) bson_iterator_double(it));
            break;
        case BSON_BOOL:
            lua_pushboolean(L, bson_iterator_bool(it));
            break;
        case BSON_OBJECT:
        case BSON_ARRAY:
        {
            bson_iterator nit;
            bson_iterator_subiterator(it, &nit);
            if (bt == BSON_OBJECT) {
                lua_push_bson_table(L, &nit);
            } else {
                lua_push_bson_array(L, &nit);
            }
            break;
        }
        case BSON_DATE:
        {
            lua_push_bsontype_table(L, bt);
            lua_pushnumber(L, bson_iterator_date(it));
            lua_rawseti(L, -2, 1);
            break;
        }
        case BSON_BINDATA:
        {
            lua_push_bsontype_table(L, bt);
            lua_pushlstring(L, bson_iterator_bin_data(it), bson_iterator_bin_len(it));
            break;
        }
        case BSON_REGEX:
        {
            const char *re = bson_iterator_regex(it);
            const char *ro = bson_iterator_regex_opts(it);
            lua_push_bsontype_table(L, bt);
            lua_pushstring(L, re);
            lua_rawseti(L, -2, 1);
            lua_pushstring(L, ro);
            lua_rawseti(L, -2, 2);
            break;
        }
        default:
            break;
    }
}
Example #9
0
EXPORT void mongo_bson_iterator_bin_value(struct bson_iterator_* i, void* v) {
    int len = bson_iterator_bin_len((bson_iterator*)i);
    memcpy(v, bson_iterator_bin_data((bson_iterator*)i), len);
}
Example #10
0
EXPORT int mongo_bson_iterator_bin_len(struct bson_iterator_* i) {
    return bson_iterator_bin_len((bson_iterator*)i);
}
static ngx_int_t ngx_http_gridfs_handler(ngx_http_request_t* request) {
    ngx_http_gridfs_loc_conf_t* gridfs_conf;
    ngx_http_core_loc_conf_t* core_conf;
    ngx_buf_t* buffer;
    ngx_chain_t out;
    ngx_str_t location_name;
    ngx_str_t full_uri;
    char* value;
    gridfs gfs;
    gridfile gfile;
    gridfs_offset length;
    ngx_uint_t chunksize;
    ngx_uint_t numchunks;
    char* contenttype;
    ngx_uint_t i;
    ngx_int_t rc = NGX_OK;
    bson query;
    bson_buffer buf;
    bson_oid_t oid;
    mongo_cursor ** cursors;
    gridfs_offset chunk_len;
    const char * chunk_data;
    bson_iterator it;
    bson chunk;
    ngx_pool_cleanup_t* gridfs_cln;
    ngx_http_gridfs_cleanup_t* gridfs_clndata;

    gridfs_conf = ngx_http_get_module_loc_conf(request, ngx_http_gridfs_module);
    core_conf = ngx_http_get_module_loc_conf(request, ngx_http_core_module);

    location_name = core_conf->name;
    full_uri = request->uri;

    gridfs_cln = ngx_pool_cleanup_add(request->pool, sizeof(ngx_http_gridfs_cleanup_t));
    if (gridfs_cln == NULL) {
      return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    gridfs_cln->handler = ngx_http_gridfs_cleanup;
    gridfs_clndata = gridfs_cln->data;

    /* defensive */
    if (full_uri.len < location_name.len) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Invalid location name or uri.");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Extract the value from the uri */
    value = (char*)malloc(sizeof(char) * (full_uri.len - location_name.len + 1));
    if (value == NULL) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Failed to allocate memory for value buffer.");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    memcpy(value, full_uri.data + location_name.len, full_uri.len - location_name.len);
    value[full_uri.len - location_name.len] = '\0';

    /* URL Decoding */
    if (!url_decode(value)) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                      "Malformed request.");
        free(value);
        return NGX_HTTP_BAD_REQUEST;
    }

    /* Find the GridFile */
    gridfs_init(gridfs_conf->mongod_conn,
                (const char*)gridfs_conf->gridfs_db.data,
                (const char*)gridfs_conf->gridfs_root_collection.data,
                &gfs);
    bson_buffer_init(&buf);
    switch (gridfs_conf->gridfs_type) {
    case  bson_oid:
        bson_oid_from_string(&oid, value);
        bson_append_oid(&buf, (char*)gridfs_conf->gridfs_field.data, &oid);
        break;
    case bson_int:
      bson_append_int(&buf, (char*)gridfs_conf->gridfs_field.data, ngx_atoi((u_char*)value, strlen(value)));
        break;
    case bson_string:
        bson_append_string(&buf, (char*)gridfs_conf->gridfs_field.data, value);
        break;
    }
    bson_from_buffer(&query, &buf);
    if(!gridfs_find_query(&gfs, &query, &gfile)){
        bson_destroy(&query);
        free(value);
        return NGX_HTTP_NOT_FOUND;
    }
    bson_destroy(&query);
    free(value);

    /* Get information about the file */
    length = gridfile_get_contentlength(&gfile);
    chunksize = gridfile_get_chunksize(&gfile);
    numchunks = gridfile_get_numchunks(&gfile);
    contenttype = (char*)gridfile_get_contenttype(&gfile);

    /* Set the headers */
    request->headers_out.status = NGX_HTTP_OK;
    request->headers_out.content_length_n = length;
    if (contenttype != NULL) {
        request->headers_out.content_type.len = strlen(contenttype);
        request->headers_out.content_type.data = (u_char*)contenttype;
    }
    else ngx_http_set_content_type(request);

    /* Determine if content is gzipped, set headers accordingly */
    if ( gridfile_get_boolean(&gfile,"gzipped") ) {
        ngx_log_error(NGX_LOG_ERR, request->connection->log, 0, gridfile_get_field(&gfile,"gzipped") );
        request->headers_out.content_encoding = ngx_list_push(&request->headers_out.headers);
        if (request->headers_out.content_encoding == NULL) {
            return NGX_ERROR;
        }
        request->headers_out.content_encoding->hash = 1;
        request->headers_out.content_encoding->key.len = sizeof("Content-Encoding") - 1;
        request->headers_out.content_encoding->key.data = (u_char *) "Content-Encoding";
        request->headers_out.content_encoding->value.len = sizeof("gzip") - 1;
        request->headers_out.content_encoding->value.data = (u_char *) "gzip";
    }

    ngx_http_send_header(request);

    if (numchunks == 0) {
        /* Allocate space for the response buffer */
        buffer = ngx_pcalloc(request->pool, sizeof(ngx_buf_t));
        if (buffer == NULL) {
            ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                          "Failed to allocate response buffer");
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
	
	buffer->pos = NULL;
	buffer->last = NULL;
	buffer->memory = 1;
	buffer->last_buf = 1;
	out.buf = buffer;
	out.next = NULL;
	return ngx_http_output_filter(request, &out);
    }
    
    cursors = (mongo_cursor **)ngx_pcalloc(request->pool, sizeof(mongo_cursor *) * numchunks);

    /* Read and serve chunk by chunk */
    for (i = 0; i < numchunks; i++) {

        /* Allocate space for the response buffer */
        buffer = ngx_pcalloc(request->pool, sizeof(ngx_buf_t));
        if (buffer == NULL) {
            ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
                          "Failed to allocate response buffer");
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

	/* Fetch the chunk from mongo */
	cursors[i] = gridfile_get_chunks(&gfile, i, 1);
	mongo_cursor_next(cursors[i]);
	chunk = cursors[i]->current;
	bson_find(&it, &chunk, "data");
	chunk_len = bson_iterator_bin_len( &it );
	chunk_data = bson_iterator_bin_data( &it );

        /* Set up the buffer chain */
        buffer->pos = (u_char*)chunk_data;
        buffer->last = (u_char*)chunk_data + chunk_len;
        buffer->memory = 1;
        buffer->last_buf = (i == numchunks-1);
        out.buf = buffer;
        out.next = NULL;

        /* Serve the Chunk */
        rc = ngx_http_output_filter(request, &out);

        /* TODO: More Codes to Catch? */
        if (rc == NGX_ERROR) {
            return NGX_ERROR;
        }
    }

    gridfs_clndata->cursors = cursors;
    gridfs_clndata->numchunks = numchunks;

    return rc;
}
Example #12
0
int
mongotcl_bsontoarray_raw (Tcl_Interp *interp, char *arrayName, char *typeArrayName, const char *data , int depth) {
    bson_iterator i;
    const char *key;
    bson_timestamp_t ts;
    char oidhex[25];
	Tcl_Obj *obj;
	char *type;

	if (data == NULL) {
		return TCL_OK;
	}

    bson_iterator_from_buffer(&i, data);

    while (bson_iterator_next (&i)) {
        bson_type t = bson_iterator_type (&i);
        if (t == 0) {
            break;
		}

        key = bson_iterator_key (&i);

        switch (t) {
			case BSON_DOUBLE: {
				obj = Tcl_NewDoubleObj (bson_iterator_double (&i));
				type = "double";
				break;
		}

			case BSON_SYMBOL: {
				obj = Tcl_NewStringObj (bson_iterator_string (&i), -1);
				type = "symbol";
				break;
			}

			case BSON_STRING: {
				obj = Tcl_NewStringObj (bson_iterator_string (&i), -1);
				type = "string";
				break;
			}

			case BSON_OID: {
				bson_oid_to_string( bson_iterator_oid( &i ), oidhex );
				obj = Tcl_NewStringObj (oidhex, -1);
				type = "oid";
				break;
			}

			case BSON_BOOL: {
				obj = Tcl_NewBooleanObj (bson_iterator_bool (&i));
				type = "bool";
				break;
			}

			case BSON_DATE: {
				obj = Tcl_NewLongObj ((long) bson_iterator_date(&i));
				type = "date";
				break;
			}

			case BSON_BINDATA: {
				unsigned char *bindata = (unsigned char *)bson_iterator_bin_data (&i);
				int binlen = bson_iterator_bin_len (&i);

				obj = Tcl_NewByteArrayObj (bindata, binlen);
				type = "bin";
				break;
			}

			case BSON_UNDEFINED: {
				obj = Tcl_NewObj ();
				type = "undefined";
				break;
			}

			case BSON_NULL: {
				obj = Tcl_NewObj ();
				type = "null";
				break;
			}

			case BSON_REGEX: {
				obj = Tcl_NewStringObj (bson_iterator_regex (&i), -1);
				type = "regex";
				break;
			}

			case BSON_CODE: {
				obj = Tcl_NewStringObj (bson_iterator_code (&i), -1);
				type = "code";
				break;
			}

			case BSON_CODEWSCOPE: {
				// bson_printf( "BSON_CODE_W_SCOPE: %s", bson_iterator_code( &i ) );
				/* bson_init( &scope ); */ /* review - stepped on by bson_iterator_code_scope? */
				// bson_iterator_code_scope( &i, &scope );
				// bson_printf( "\n\t SCOPE: " );
				// bson_print( &scope );
				/* bson_destroy( &scope ); */ /* review - causes free error */
				break;
			}

			case BSON_INT: {
				obj = Tcl_NewIntObj (bson_iterator_int (&i));
				type = "int";
				break;
			}

			case BSON_LONG: {
				obj = Tcl_NewLongObj ((uint64_t)bson_iterator_long (&i));
				type = "long";
				break;
			}

			case BSON_TIMESTAMP: {
				char string[64];

				ts = bson_iterator_timestamp (&i);
				snprintf(string, sizeof(string), "%d:%d", ts.i, ts.t);
				obj = Tcl_NewStringObj (bson_iterator_string (&i), -1);
				type = "timestamp";
				break;
			}

			case BSON_ARRAY: {
				obj = Tcl_NewObj();
				obj = mongotcl_bsontolist_raw (interp, obj, bson_iterator_value (&i), depth + 1);
				type = "array";

				break;
			}

			case BSON_OBJECT: {
				Tcl_Obj *subList = Tcl_NewObj ();

				obj = mongotcl_bsontolist_raw (interp, subList, bson_iterator_value (&i), depth + 1);
				type = "object";
				break;
			}

			default: {
				obj = Tcl_NewIntObj (t);
				type = "unknown";
				break;
			}
		}

		if (Tcl_SetVar2Ex (interp, arrayName, key, obj, TCL_LEAVE_ERR_MSG) == NULL) {
			return TCL_ERROR;
		}

		if (typeArrayName != NULL) {
			if (Tcl_SetVar2Ex (interp, typeArrayName, key, Tcl_NewStringObj (type, -1), TCL_LEAVE_ERR_MSG) == NULL) {
				return TCL_ERROR;
			}
		}
    }
	return TCL_OK; 
}
Example #13
0
Tcl_Obj *
mongotcl_bsontolist_raw (Tcl_Interp *interp, Tcl_Obj *listObj, const char *data , int depth) {
    bson_iterator i;
    const char *key;
    bson_timestamp_t ts;
    char oidhex[25];
    bson scope;

	if (data == NULL) {
		return listObj;
	}

    bson_iterator_from_buffer(&i, data);

    while (bson_iterator_next (&i)) {
        bson_type t = bson_iterator_type (&i);
        if (t == 0) {
            break;
		}

        key = bson_iterator_key (&i);

		switch (t) {
			case BSON_DOUBLE: {
				append_list_type_object (interp, listObj, "double", key, Tcl_NewDoubleObj (bson_iterator_double (&i)));
				break;
			}

			case BSON_STRING: {
				append_list_type_object (interp, listObj, "string", key, Tcl_NewStringObj (bson_iterator_string (&i), -1));
				break;
			}

			case BSON_SYMBOL: {
				append_list_type_object (interp, listObj, "symbol", key, Tcl_NewStringObj (bson_iterator_string (&i), -1));
				break;
			}

			case BSON_OID: {
				bson_oid_to_string( bson_iterator_oid( &i ), oidhex );
				append_list_type_object (interp, listObj, "oid", key, Tcl_NewStringObj (oidhex, -1));
				break;
			}

			case BSON_BOOL: {
			append_list_type_object (interp, listObj, "bool", key, Tcl_NewBooleanObj (bson_iterator_bool (&i)));
				break;
			}

			case BSON_DATE: {
				append_list_type_object (interp, listObj, "date", key, Tcl_NewLongObj ((long) bson_iterator_date(&i)));
				break;
			}

			case BSON_BINDATA: {
				unsigned char *bindata = (unsigned char *)bson_iterator_bin_data (&i);
				int binlen = bson_iterator_bin_len (&i);

				append_list_type_object (interp, listObj, "bin", key, Tcl_NewByteArrayObj (bindata, binlen));
				break;
			}

			case BSON_UNDEFINED: {
				append_list_type_object (interp, listObj, "undefined", key, Tcl_NewObj ());
				break;
			}

			case BSON_NULL: {
				append_list_type_object (interp, listObj, "null", key, Tcl_NewObj ());
				break;
			}

			case BSON_REGEX: {
				append_list_type_object (interp, listObj, "regex", key, Tcl_NewStringObj (bson_iterator_regex (&i), -1));
				break;
			}

			case BSON_CODE: {
				append_list_type_object (interp, listObj, "code", key, Tcl_NewStringObj (bson_iterator_code (&i), -1));
				break;
			}

			case BSON_CODEWSCOPE: {
				bson_printf( "BSON_CODE_W_SCOPE: %s", bson_iterator_code( &i ) );
				/* bson_init( &scope ); */ /* review - stepped on by bson_iterator_code_scope? */
				bson_iterator_code_scope( &i, &scope );
				bson_printf( "\n\t SCOPE: " );
				bson_print( &scope );
				/* bson_destroy( &scope ); */ /* review - causes free error */
				break;
			}

			case BSON_INT: {
				append_list_type_object (interp, listObj, "int", key, Tcl_NewIntObj (bson_iterator_int (&i)));
				break;
			}

			case BSON_LONG: {
				append_list_type_object (interp, listObj, "long", key, Tcl_NewLongObj ((uint64_t)bson_iterator_long (&i)));
				break;
			}

			case BSON_TIMESTAMP: {
				char string[64];

				ts = bson_iterator_timestamp (&i);
				snprintf(string, sizeof(string), "%d:%d", ts.i, ts.t);
				append_list_type_object (interp, listObj, "timestamp", key, Tcl_NewStringObj (bson_iterator_string (&i), -1));
				break;
			}

			case BSON_ARRAY: {
				Tcl_Obj *subList = Tcl_NewObj ();

				subList = mongotcl_bsontolist_raw (interp, subList, bson_iterator_value (&i), depth + 1);
				append_list_type_object (interp, listObj, "array", key, subList);
				break;
			}

			case BSON_OBJECT: {
				Tcl_Obj *subList = Tcl_NewObj ();

				subList = mongotcl_bsontolist_raw (interp, subList, bson_iterator_value (&i), depth + 1);
				append_list_type_object (interp, listObj, "object", key, subList);
				break;
			}

			default: {
				append_list_type_object (interp, listObj, "unknown", key, Tcl_NewIntObj (t));
				break;
			}
		}
    }
    return listObj;
}
Example #14
0
INT32 _appendValue( CHAR delChar, bson_iterator *pIt,
                    CHAR **ppBuffer, INT32 *pCSVSize,
                    BOOLEAN includeBinary,
                    BOOLEAN includeRegex )
{
   INT32 rc = SDB_OK ;
   bson_type type = bson_iterator_type( pIt ) ;
   INT32 tempSize = 0 ;
   INT32 base64Size = 0 ;
   INT32 binType = 0 ;
   CHAR temp[128] = { 0 } ;
   const CHAR *pTemp = NULL ;
   CHAR *pBase64 = NULL ;
   bson_timestamp_t ts;
   time_t timer ;
   struct tm psr;

   if ( type == BSON_DOUBLE || type == BSON_BOOL ||
        type == BSON_NULL || type == BSON_INT ||
        type == BSON_LONG )
   {
      rc = _appendNonString( delChar, pIt, ppBuffer, pCSVSize ) ;
      if ( rc )
      {
         goto error ;
      }
   }
   else
   {
      rc = _appendString( delChar, &delChar, 1, ppBuffer, pCSVSize ) ;
      if ( rc )
      {
         goto error ;
      }
      if ( type == BSON_TIMESTAMP )
      {
         ts = bson_iterator_timestamp( pIt ) ;
         timer = (time_t)ts.t;
         local_time( &timer, &psr ) ;
         tempSize = ossSnprintf ( temp, 64,
                                  "%04d-%02d-%02d-%02d.%02d.%02d.%06d",
                                  psr.tm_year + 1900,
                                  psr.tm_mon + 1,
                                  psr.tm_mday,
                                  psr.tm_hour,
                                  psr.tm_min,
                                  psr.tm_sec,
                                  ts.i ) ;
         rc = _appendString( delChar, temp, tempSize, ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else if ( type == BSON_DATE )
      {
         timer = bson_iterator_date( pIt ) / 1000 ;
         local_time( &timer, &psr ) ;
         tempSize = ossSnprintf ( temp, 64, "%04d-%02d-%02d",
                                  psr.tm_year + 1900,
                                  psr.tm_mon + 1,
                                  psr.tm_mday ) ;
         rc = _appendString( delChar, temp, tempSize, ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else if ( type == BSON_UNDEFINED )
      {
         rc = _appendString( delChar, CSV_STR_UNDEFINED,
                             CSV_STR_UNDEFINED_SIZE,
                             ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else if ( type == BSON_MINKEY )
      {
         rc = _appendString( delChar, CSV_STR_MINKEY,
                             CSV_STR_MINKEY_SIZE, ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else if ( type == BSON_MAXKEY )
      {
         rc = _appendString( delChar, CSV_STR_MAXKEY,
                             CSV_STR_MAXKEY_SIZE, ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else if ( type == BSON_CODE )
      {
         pTemp = bson_iterator_code( pIt ) ;
         rc = _appendString( delChar, pTemp, ossStrlen( pTemp ),
                             ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else if ( type == BSON_STRING || type == BSON_SYMBOL )
      {
         pTemp = bson_iterator_string( pIt ) ;
         rc = _appendString( delChar, pTemp, ossStrlen( pTemp ),
                             ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else if ( type == BSON_BINDATA )
      {
         if( TRUE == includeBinary )
         {
            rc = _appendString( delChar, CSV_STR_LEFTBRACKET, 1, ppBuffer, pCSVSize ) ;
            if ( rc )
            {
               goto error ;
            }
            binType = (INT32)bson_iterator_bin_type( pIt ) ;
            tempSize = ossSnprintf ( temp, 64, "%d", binType ) ;
            rc = _appendString( delChar, &temp, tempSize, ppBuffer, pCSVSize ) ;
            if ( rc )
            {
               goto error ;
            }
            rc = _appendString( delChar, CSV_STR_RIGHTBRACKET, 1, ppBuffer, pCSVSize ) ;
            if ( rc )
            {
               goto error ;
            }
         }
         pTemp = bson_iterator_bin_data( pIt ) ;
         tempSize = bson_iterator_bin_len ( pIt ) ;
         base64Size = getEnBase64Size ( tempSize ) ;
         pBase64 = (CHAR *)SDB_OSS_MALLOC( base64Size ) ;
         if( NULL == pBase64 )
         {
            rc = SDB_OOM ;
            goto error ;
         }
         ossMemset( pBase64, 0, base64Size ) ;
         if ( !base64Encode( pTemp, tempSize, pBase64, base64Size ) )
         {
            rc = SDB_OOM ;
            goto error ;
         }
         rc = _appendString( delChar, pBase64, base64Size - 1,
                             ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else if ( type == BSON_REGEX )
      {
         if( TRUE == includeRegex )
         {
            rc = _appendString( delChar, CSV_STR_BACKSLASH, 1,
                                ppBuffer, pCSVSize ) ;
            if ( rc )
            {
               goto error ;
            }
         }
         pTemp = bson_iterator_regex( pIt ) ;
         rc = _appendString( delChar, pTemp, ossStrlen( pTemp ),
                             ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
         if( TRUE == includeRegex )
         {
            rc = _appendString( delChar, CSV_STR_BACKSLASH, 1,
                                ppBuffer, pCSVSize ) ;
            if ( rc )
            {
               goto error ;
            }
            pTemp = bson_iterator_regex_opts( pIt ) ;
            rc = _appendString( delChar, pTemp, ossStrlen( pTemp ),
                                ppBuffer, pCSVSize ) ;
            if ( rc )
            {
               goto error ;
            }
         }
      }
      else if ( type == BSON_OID )
      {
         bson_oid_to_string( bson_iterator_oid( pIt ), temp ) ;
         rc = _appendString( delChar, temp, 24, ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      else
      {
         rc = _appendObj( delChar, pIt, ppBuffer, pCSVSize ) ;
         if ( rc )
         {
            goto error ;
         }
      }
      rc = _appendString( delChar, &delChar, 1, ppBuffer, pCSVSize ) ;
      if ( rc )
      {
         goto error ;
      }
   }
done:
   SAFE_OSS_FREE( pBase64 ) ;
   return rc ;
error:
   goto done ;
}
Example #15
0
static int resolve_block(struct inode * e, uint8_t hash[HASH_LEN], char * buf) {
    bson query;
    int res;
    mongo_cursor curs;
    bson_iterator i;
    bson_type bt;
    const char * key;
    mongo * conn = get_conn();

    bson_init(&query);
    bson_append_binary(&query, "_id", 0, (char*)hash, 20);
    bson_finish(&query);

    mongo_cursor_init(&curs, conn, blocks_name);
    mongo_cursor_set_query(&curs, &query);
    mongo_cursor_set_limit(&curs, 1);

    res = mongo_cursor_next(&curs);
    bson_destroy(&query);
    if(res != MONGO_OK) {
        mongo_cursor_destroy(&curs);
        return -EIO;
    }

    bson_iterator_init(&i, mongo_cursor_bson(&curs));
    size_t outsize, compsize = 0;
    const char * compdata = NULL;
    uint32_t offset = 0, size = 0;

    while((bt = bson_iterator_next(&i)) > 0) {
        key = bson_iterator_key(&i);
        if(strcmp(key, "data") == 0) {
            compsize = bson_iterator_bin_len(&i);
            compdata = bson_iterator_bin_data(&i);
        }
        else if(strcmp(key, "offset") == 0)
            offset = bson_iterator_int(&i);
        else if(strcmp(key, "size") == 0)
            size = bson_iterator_int(&i);
    }

    if(curs.err != MONGO_CURSOR_EXHAUSTED) {
        fprintf(stderr, "Error getting extents %d", curs.err);
        return -EIO;
    }

    if(!compdata) {
        fprintf(stderr, "No data in block?\n");
        return -EIO;
    }

    outsize = MAX_BLOCK_SIZE;
    if((res = snappy_uncompress(compdata, compsize,
        buf + offset, &outsize)) != SNAPPY_OK) {
        fprintf(stderr, "Error uncompressing block %d\n", res);
        return -EIO;
    }
    if(offset > 0)
        memset(buf, 0, offset);
    compsize = outsize + offset;
    if(compsize < size)
        memset(buf + compsize, 0, size - compsize);
    mongo_cursor_destroy(&curs);

    return 0;
}
Example #16
0
void decodeValue(v8::Local<v8::Object> obj, bson_iterator *it)
{
    bson_type type = bson_iterator_type(it);
    const char *key = bson_iterator_key(it);

    switch (type)
    {
    case BSON_NULL:
        obj->Set(v8::String::NewFromUtf8(isolate, key), v8::Null(isolate));
        break;
    case BSON_STRING:
        obj->Set(v8::String::NewFromUtf8(isolate, key),
                 v8::String::NewFromUtf8(isolate, bson_iterator_string(it)));
        break;
    case BSON_BOOL:
        obj->Set(v8::String::NewFromUtf8(isolate, key),
                 bson_iterator_bool(it) ? v8::True(isolate) : v8::False(isolate));
        break;
    case BSON_INT:
        obj->Set(v8::String::NewFromUtf8(isolate, key), v8::Number::New(isolate, bson_iterator_int(it)));
        break;
    case BSON_LONG:
    {
        int64_t num = bson_iterator_long(it);
        if (num >= -2147483648ll && num <= 2147483647ll)
        {
            obj->Set(v8::String::NewFromUtf8(isolate, key),
                     v8::Number::New(isolate, (double) num));
        }
        else
        {
            obj_ptr<Int64> int64 = new Int64(num);
            obj->Set(v8::String::NewFromUtf8(isolate, key), int64->wrap());
        }
        break;
    }
    case BSON_DOUBLE:
        obj->Set(v8::String::NewFromUtf8(isolate, key),
                 v8::Number::New(isolate, bson_iterator_double(it)));
        break;
    case BSON_DATE:
        obj->Set(v8::String::NewFromUtf8(isolate, key),
                 v8::Date::New(isolate, (double) bson_iterator_date(it)));
        break;
    case BSON_BINDATA:
    {
        obj_ptr<Buffer_base> buf = new Buffer(
            std::string(bson_iterator_bin_data(it),
                        bson_iterator_bin_len(it)));

        obj->Set(v8::String::NewFromUtf8(isolate, key), buf->wrap());
        break;
    }
    case BSON_OID:
    {
        obj_ptr<MongoID> oid = new MongoID(bson_iterator_oid(it));
        obj->Set(v8::String::NewFromUtf8(isolate, key), oid->wrap());
        break;
    }
    case BSON_REGEX:
    {
        v8::RegExp::Flags flgs = v8::RegExp::kNone;
        const char *opts = bson_iterator_regex_opts(it);
        char ch;

        while ((ch = *opts++) != 0)
            if (ch == 'm')
                flgs = (v8::RegExp::Flags) (flgs | v8::RegExp::kMultiline);
            else if (ch == 'g')
                flgs = (v8::RegExp::Flags) (flgs | v8::RegExp::kGlobal);
            else if (ch == 'i')
                flgs = (v8::RegExp::Flags) (flgs | v8::RegExp::kIgnoreCase);

        obj->Set(v8::String::NewFromUtf8(isolate, key),
                 v8::RegExp::New(v8::String::NewFromUtf8(isolate, bson_iterator_regex(it)),
                                 flgs));
        break;
    }
    case BSON_OBJECT:
    case BSON_ARRAY:
    {
        bson_iterator it1;

        bson_iterator_subiterator(it, &it1);
        obj->Set(v8::String::NewFromUtf8(isolate, key), decodeObject(&it1, type == BSON_ARRAY));
        break;
    }
    default:
        printf("unknown type: %d\n", type);
        break;
    }
}