static bool handle_ismaster (mock_server_t *server, mongoc_stream_t *client, mongoc_rpc_t *rpc, const bson_t *doc) { bson_t reply_doc = BSON_INITIALIZER; time_t now = time (NULL); BSON_ASSERT (server); BSON_ASSERT (client); BSON_ASSERT (rpc); BSON_ASSERT (doc); bson_append_bool (&reply_doc, "ismaster", -1, server->isMaster); bson_append_int32 (&reply_doc, "maxBsonObjectSize", -1, server->maxBsonObjectSize); bson_append_int32 (&reply_doc, "maxMessageSizeBytes", -1, server->maxMessageSizeBytes); bson_append_int32 (&reply_doc, "minWireVersion", -1, server->minWireVersion); bson_append_int32 (&reply_doc, "maxWireVersion", -1, server->maxWireVersion); bson_append_double (&reply_doc, "ok", -1, 1.0); bson_append_time_t (&reply_doc, "localtime", -1, now); mock_server_reply_simple (server, client, rpc, MONGOC_REPLY_NONE, &reply_doc); bson_destroy (&reply_doc); return true; }
/* Saves accounting information */ static int mongo_account(void *instance, REQUEST *request) { rlm_mongo_t *data = (rlm_mongo_t *)instance; bson b; bson_buffer buf; const char *attr; char value[MAX_STRING_LEN+1]; VALUE_PAIR *vp = request->packet->vps; // shall we insert this packet or not int insert; bson_buffer_init(&buf); bson_append_new_oid(&buf, "_id"); insert = 0; while (vp) { attr = vp->name; if ((strcmp(attr, "Acct-Status-Type") == 0) && ((strcmp(data->only_stop, "") != 0))) { if ((vp->vp_integer & 0xffffff) != 2) { break; } else { insert = 1; } } switch (vp->type) { case PW_TYPE_INTEGER: bson_append_int(&buf, attr, vp->vp_integer & 0xffffff); break; case PW_TYPE_BYTE: case PW_TYPE_SHORT: bson_append_int(&buf, attr, vp->vp_integer); break; case PW_TYPE_DATE: bson_append_time_t(&buf, attr, vp->vp_date); break; default: vp_prints_value(value, sizeof(value), vp, 0); bson_append_string(&buf, attr, value); // akh RDEBUG("mongo default insert %s", value); break; } vp = vp->next; } bson_from_buffer(&b, &buf); MONGO_TRY { if (insert == 1) { mongo_insert(conn, data->acct_base, &b); RDEBUG("accounting record was inserted"); } } MONGO_CATCH { radlog(L_ERR, "mongo_insert failed"); return RLM_MODULE_FAIL; } bson_destroy(&b); return RLM_MODULE_OK; }
int commit_inode(struct inode * e) { bson cond, doc; mongo * conn = get_conn(); char istr[4]; struct dirent * cde = e->dirents; int res; bson_init(&doc); bson_append_start_object(&doc, "$set"); bson_append_start_array(&doc, "dirents"); res = 0; while(cde) { bson_numstr(istr, res++); bson_append_string(&doc, istr, cde->path); cde = cde->next; } bson_append_finish_array(&doc); bson_append_int(&doc, "mode", e->mode); bson_append_long(&doc, "owner", e->owner); bson_append_long(&doc, "group", e->group); bson_append_long(&doc, "size", e->size); bson_append_time_t(&doc, "created", e->created); bson_append_time_t(&doc, "modified", e->modified); if(e->data && e->datalen > 0) bson_append_string_n(&doc, "data", e->data, e->datalen); bson_append_finish_object(&doc); bson_finish(&doc); bson_init(&cond); bson_append_oid(&cond, "_id", &e->oid); bson_finish(&cond); res = mongo_update(conn, inodes_name, &cond, &doc, MONGO_UPDATE_UPSERT, NULL); bson_destroy(&cond); bson_destroy(&doc); if(res != MONGO_OK) { fprintf(stderr, "Error committing inode %s\n", mongo_get_server_err_string(conn)); return -EIO; } return 0; }
static void test_bson_as_json (void) { bson_oid_t oid; bson_decimal128_t decimal128; bson_t *b; bson_t *b2; char *str; size_t len; int i; decimal128.high = 0x3040000000000000ULL; decimal128.low = 0x000000000000000B; bson_oid_init_from_string(&oid, "123412341234abcdabcdabcd"); b = bson_new(); assert(bson_append_utf8(b, "utf8", -1, "bar", -1)); assert(bson_append_int32(b, "int32", -1, 1234)); assert(bson_append_int64(b, "int64", -1, 4321)); assert(bson_append_double(b, "double", -1, 123.4)); assert(bson_append_undefined(b, "undefined", -1)); assert(bson_append_null(b, "null", -1)); assert(bson_append_oid(b, "oid", -1, &oid)); assert(bson_append_bool(b, "true", -1, true)); assert(bson_append_bool(b, "false", -1, false)); assert(bson_append_time_t(b, "date", -1, time(NULL))); assert(bson_append_timestamp(b, "timestamp", -1, (uint32_t)time(NULL), 1234)); assert(bson_append_regex(b, "regex", -1, "^abcd", "xi")); assert(bson_append_dbpointer(b, "dbpointer", -1, "mycollection", &oid)); assert(bson_append_minkey(b, "minkey", -1)); assert(bson_append_maxkey(b, "maxkey", -1)); assert(bson_append_symbol(b, "symbol", -1, "var a = {};", -1)); assert(bson_append_decimal128(b, "decimal128", -1, &decimal128)); b2 = bson_new(); assert(bson_append_int32(b2, "0", -1, 60)); assert(bson_append_document(b, "document", -1, b2)); assert(bson_append_array(b, "array", -1, b2)); { const uint8_t binary[] = { 0, 1, 2, 3, 4 }; assert(bson_append_binary(b, "binary", -1, BSON_SUBTYPE_BINARY, binary, sizeof binary)); } for (i = 0; i < 1000; i++) { str = bson_as_json(b, &len); bson_free(str); } bson_destroy(b); bson_destroy(b2); }
static void test_bson_iter_mixed (void) { bson_iter_t iter; bson_decimal128_t iter_value; bson_decimal128_t value; bson_t *b; bson_t *b2; b = bson_new(); b2 = bson_new(); value.high = 0; value.low = 1; assert(bson_append_utf8(b2, "foo", -1, "bar", -1)); assert(bson_append_code(b, "0", -1, "var a = {};")); assert(bson_append_code_with_scope(b, "1", -1, "var b = {};", b2)); assert(bson_append_int32(b, "2", -1, 1234)); assert(bson_append_int64(b, "3", -1, 4567)); assert(bson_append_time_t(b, "4", -1, 123456)); assert(bson_append_decimal128(b, "5", -1, &value)); assert(bson_iter_init(&iter, b)); assert(bson_iter_next(&iter)); assert(BSON_ITER_HOLDS_CODE(&iter)); assert(bson_iter_next(&iter)); assert(BSON_ITER_HOLDS_CODEWSCOPE(&iter)); assert(bson_iter_next(&iter)); assert(BSON_ITER_HOLDS_INT32(&iter)); assert(bson_iter_next(&iter)); assert(BSON_ITER_HOLDS_INT64(&iter)); assert(bson_iter_next(&iter)); assert(BSON_ITER_HOLDS_DATE_TIME(&iter)); assert(bson_iter_next(&iter)); assert(BSON_ITER_HOLDS_DECIMAL128(&iter)); assert(!bson_iter_next(&iter)); assert(bson_iter_init_find(&iter, b, "3")); assert(!strcmp(bson_iter_key(&iter), "3")); assert(bson_iter_int64(&iter) == 4567); assert(bson_iter_next(&iter)); assert(BSON_ITER_HOLDS_DATE_TIME(&iter)); assert(bson_iter_time_t(&iter) == 123456); assert(bson_iter_date_time(&iter) == 123456000); assert(bson_iter_next(&iter)); /* This test uses memcmp because libbson lacks decimal128 comparison. */ bson_iter_decimal128(&iter, &iter_value); assert(memcmp(&iter_value, &value, sizeof(value)) == 0); assert(!bson_iter_next(&iter)); bson_destroy(b); bson_destroy(b2); }
static void test_bson_append_time_t (void) { bson_t *b; bson_t *b2; time_t t; t = 1234567890; b = bson_new(); assert(bson_append_time_t(b, "time_t", -1, t)); b2 = get_bson("test26.bson"); assert_bson_equal(b, b2); bson_destroy(b); bson_destroy(b2); }
int main (int argc, char *argv[]) { mongoc_client_t *client; mongoc_collection_t *collection; mongoc_cursor_t *cursor; bson_error_t error; const bson_t *doc; const char *uristr = "mongodb://*****:*****@localhost/?authMechanism=PLAIN&authSource=$external"; const char *database_name = "test"; const char *collection_name = "query1"; const char *user_role = "ro"; if (argc == 2 && !strcmp("--help",argv[1])) { printf ("Usage: [uri [database [collection [ro|rw]]]]\n"); return EXIT_FAILURE; } if (argc > 1) { uristr = argv [1]; } if (argc > 2) { database_name = argv [2]; } if (argc > 3) { collection_name = argv [3]; } if (argc > 4) { user_role = argv [4]; } mongoc_init (); client = mongoc_client_new (uristr); collection = mongoc_client_get_collection (client, database_name, collection_name); if (!client) { fprintf (stderr, "Failed to parse URI.\n"); return EXIT_FAILURE; } // write if (!strcasecmp(user_role,"rw")) { bson_t *rwbson; bson_error_t rwerror; rwbson = bson_new(); time_t now = time(NULL); bson_append_utf8(rwbson,"db",-1,database_name,-1); bson_append_time_t(rwbson,"date",-1,now); mongoc_client_get_database(client, database_name); bool ret = mongoc_collection_insert(collection, MONGOC_INSERT_NONE, rwbson, NULL, &rwerror); bson_destroy(rwbson); if (!ret) return EXIT_FAILURE; } // read bson_t roquery; bson_init (&roquery); char *str; #if 0 eson_append_utf8 (&roquery, "hello", -1, "world", -1); #endif cursor = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, &roquery, NULL, /* Fields, NULL for all. */ NULL); /* Read Prefs, NULL for default */ while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_json (doc, NULL); fprintf (stdout, "%s\n", str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, "Cursor Failure: %s\n", error.message); return EXIT_FAILURE; } bson_destroy (&roquery); // close server connection mongoc_cursor_destroy (cursor); mongoc_collection_destroy (collection); mongoc_client_destroy (client); mongoc_cleanup (); return EXIT_SUCCESS; }
/* * Add key-op-value to a bson filter document */ int db_mongodb_bson_filter_add(bson_t *doc, const db_key_t* _k, const db_op_t* _op, const db_val_t* _v, int idx) { bson_t mdoc; db_key_t tkey; const db_val_t *tval; int vtype; str ocmp; tkey = _k[idx]; tval = _v + idx; vtype = VAL_TYPE(tval); /* OP_EQ is handled separately */ if(!strcmp(_op[idx], OP_LT)) { ocmp.s = "$lt"; ocmp.len = 3; } else if(!strcmp(_op[idx], OP_LEQ)) { ocmp.s = "$lte"; ocmp.len = 4; } else if(!strcmp(_op[idx], OP_GT)) { ocmp.s = "$gt"; ocmp.len = 3; } else if(!strcmp(_op[idx], OP_GEQ)) { ocmp.s = "$gte"; ocmp.len = 4; } else if(!strcmp(_op[idx], OP_NEQ) || !strcmp(_op[idx], "!=")) { ocmp.s = "$ne"; ocmp.len = 3; } else { LM_ERR("unsuported match operator: %s\n", _op[idx]); goto error; } if(!bson_append_document_begin(doc, tkey->s, tkey->len, &mdoc)) { LM_ERR("failed to append start to bson doc %.*s %s ... [%d]\n", tkey->len, tkey->s, ocmp.s, idx); goto error; } if(VAL_NULL(tval)) { if(!bson_append_null(&mdoc, ocmp.s, ocmp.len)) { LM_ERR("failed to append null to bson doc %.*s %s null [%d]\n", tkey->len, tkey->s, ocmp.s, idx); goto error; } goto done; } switch(vtype) { case DB1_INT: if(!bson_append_int32(&mdoc, ocmp.s, ocmp.len, VAL_INT(tval))) { LM_ERR("failed to append int to bson doc %.*s %s %d [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_INT(tval), idx); goto error; } break; case DB1_BIGINT: if(!bson_append_int64(&mdoc, ocmp.s, ocmp.len, VAL_BIGINT(tval ))) { LM_ERR("failed to append bigint to bson doc %.*s %s %lld [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_BIGINT(tval), idx); goto error; } return -1; case DB1_DOUBLE: if(!bson_append_double(&mdoc, ocmp.s, ocmp.len, VAL_DOUBLE(tval))) { LM_ERR("failed to append double to bson doc %.*s %s %f [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_DOUBLE(tval), idx); goto error; } break; case DB1_STRING: if(!bson_append_utf8(&mdoc, ocmp.s, ocmp.len, VAL_STRING(tval), strlen(VAL_STRING(tval))) ) { LM_ERR("failed to append string to bson doc %.*s %s %s [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_STRING(tval), idx); goto error; } break; case DB1_STR: if(!bson_append_utf8(&mdoc, ocmp.s, ocmp.len, VAL_STR(tval).s, VAL_STR(tval).len) ) { LM_ERR("failed to append str to bson doc %.*s %s %.*s [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_STR(tval).len, VAL_STR(tval).s, idx); goto error; } break; case DB1_DATETIME: if(!bson_append_time_t(&mdoc, ocmp.s, ocmp.len, VAL_TIME(tval))) { LM_ERR("failed to append time to bson doc %.*s %s %ld [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_TIME(tval), idx); goto error; } break; case DB1_BLOB: if(!bson_append_binary(&mdoc, ocmp.s, ocmp.len, BSON_SUBTYPE_BINARY, (const uint8_t *)VAL_BLOB(tval).s, VAL_BLOB(tval).len) ) { LM_ERR("failed to append blob to bson doc %.*s %s [bin] [%d]\n", tkey->len, tkey->s, ocmp.s, idx); goto error; } break; case DB1_BITMAP: if(!bson_append_int32(&mdoc, ocmp.s, ocmp.len, VAL_INT(tval))) { LM_ERR("failed to append bitmap to bson doc %.*s %s %d [%d]\n", tkey->len, tkey->s, ocmp.s, VAL_INT(tval), idx); goto error; } break; default: LM_ERR("val type [%d] not supported\n", vtype); goto error; } done: if(!bson_append_document_end(doc, &mdoc)) { LM_ERR("failed to append end to bson doc %.*s %s ... [%d]\n", tkey->len, tkey->s, ocmp.s, idx); goto error; } return 0; error: return -1; }
/* * Add key-value to a bson document */ int db_mongodb_bson_add(bson_t *doc, const db_key_t _k, const db_val_t *_v, int idx) { int vtype; vtype = VAL_TYPE(_v); if(VAL_NULL(_v)) { if(!bson_append_null(doc, _k->s, _k->len)) { LM_ERR("failed to append int to bson doc %.*s = %d [%d]\n", _k->len, _k->s, VAL_INT(_v), idx); goto error; } goto done; } switch(vtype) { case DB1_INT: if(!bson_append_int32(doc, _k->s, _k->len, VAL_INT(_v))) { LM_ERR("failed to append int to bson doc %.*s = %d [%d]\n", _k->len, _k->s, VAL_INT(_v), idx); goto error; } break; case DB1_BIGINT: if(!bson_append_int64(doc, _k->s, _k->len, VAL_BIGINT(_v ))) { LM_ERR("failed to append bigint to bson doc %.*s = %lld [%d]\n", _k->len, _k->s, VAL_BIGINT(_v), idx); goto error; } return -1; case DB1_DOUBLE: if(!bson_append_double(doc, _k->s, _k->len, VAL_DOUBLE(_v))) { LM_ERR("failed to append double to bson doc %.*s = %f [%d]\n", _k->len, _k->s, VAL_DOUBLE(_v), idx); goto error; } break; case DB1_STRING: if(!bson_append_utf8(doc, _k->s, _k->len, VAL_STRING(_v), strlen(VAL_STRING(_v))) ) { LM_ERR("failed to append string to bson doc %.*s = %s [%d]\n", _k->len, _k->s, VAL_STRING(_v), idx); goto error; } break; case DB1_STR: if(!bson_append_utf8(doc, _k->s, _k->len, VAL_STR(_v).s, VAL_STR(_v).len) ) { LM_ERR("failed to append str to bson doc %.*s = %.*s [%d]\n", _k->len, _k->s, VAL_STR(_v).len, VAL_STR(_v).s, idx); goto error; } break; case DB1_DATETIME: if(!bson_append_time_t(doc, _k->s, _k->len, VAL_TIME(_v))) { LM_ERR("failed to append time to bson doc %.*s = %ld [%d]\n", _k->len, _k->s, VAL_TIME(_v), idx); goto error; } break; case DB1_BLOB: if(!bson_append_binary(doc, _k->s, _k->len, BSON_SUBTYPE_BINARY, (const uint8_t *)VAL_BLOB(_v).s, VAL_BLOB(_v).len) ) { LM_ERR("failed to append blob to bson doc %.*s = [bin] [%d]\n", _k->len, _k->s, idx); goto error; } break; case DB1_BITMAP: if(!bson_append_int32(doc, _k->s, _k->len, VAL_INT(_v))) { LM_ERR("failed to append bitmap to bson doc %.*s = %d [%d]\n", _k->len, _k->s, VAL_INT(_v), idx); goto error; } break; default: LM_ERR("val type [%d] not supported\n", vtype); return -1; } done: return 0; error: return -1; }
static void ngx_wirte_tracking_into_mongodb(ngx_http_request_t *r, ngx_http_vesb_aio_log_main_conf_t *valcf,ngx_http_vesb_aio_log_loc_conf_t *vallcf,int timeuse) { mongo conn[1]; char *conn_str; int port,status,insertstatus; time_t timenow; ngx_list_part_t *part = &r->headers_in.headers.part; ngx_table_elt_t *header = part->elts; ngx_uint_t i; if(r->headers_out.status == NGX_HTTP_OK) { conn_str = (char *)valcf->mongodb_conn_str.data; port = (int)valcf->mongodb_conn_port; status = mongo_client( conn, conn_str, port ); if( status == MONGO_OK ) { mongo_set_op_timeout( conn, 10000 );//time oust 10000 ms time ( &timenow ); bson b[1]; bson_init( b ); bson_append_new_oid( b, "_id" ); if( r->headers_in.x_forwarded_for == NULL ) { bson_append_string_n( b, "realclientip" , (char *)r->connection->addr_text.data, r->connection->addr_text.len); } else { bson_append_string_n( b, "realclientip" , (char *)r->headers_in.x_forwarded_for->value.data,r->headers_in.x_forwarded_for->value.len); } bson_append_int( b,"statuscode",r->headers_out.status); bson_append_int( b,"usetime",timeuse); bson_append_long( b,"requestsize",r->request_length); bson_append_long( b,"responsesize",r->headers_out.content_length_n); bson_append_time_t( b,"invoketime",timenow ); if(vallcf->app_name.data != NULL) { bson_append_string_n( b,"appname",(char *)vallcf->app_name.data,vallcf->app_name.len); } else { bson_append_string( b,"appname","undefine"); } /*get method name*/ for(i=0;/* void */; ++i) { if(i >= part->nelts) { if(part->next == NULL) { break; } part = part->next; header = part->elts; i=0; } if(header[i].hash == 0) { continue; } if(ngx_strstr(header[i].key.data,"SOAPAction") != NULL) { bson_append_string_n( b,"SOAPAction",(char *)header[i].value.data,header[i].value.len); } else if(ngx_strstr(header[i].key.data,"Content-Type") != NULL) { bson_append_string_n( b,"Content-Type",(char *)header[i].value.data,header[i].value.len); } } bson_finish( b ); insertstatus = mongo_insert( conn,"vesb.tracking", b , NULL ); if( insertstatus != MONGO_OK ) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "insert tracking log in mongodb is failed!(error:%d)",conn[0].err); } bson_destroy( b ); } else { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "mongodb is unconnection!(error:%d)",status); } mongo_destroy( conn ); } }
static bcon_error_t bson_bcon_key_value(bson *b, const char *key, const char *typespec, const bcon bci) { bcon_error_t ret = BCON_OK; bson_oid_t oid; char ptype = typespec ? typespec[1] : '_'; char utype = typespec ? typespec[2] : '_'; switch (ptype) { case '_': /* kv(b, key, utype, bci) */ switch (utype) { case '_': /* fall through */ case 's': bson_append_string( b, key, bci.s ); break; /* common case */ case 'f': bson_append_double( b, key, bci.f ); break; case 'D': bson_append_start_object( b, key ); ret = bson_append_bcon( b, bci.D ); bson_append_finish_object( b ); break; case 'A': bson_append_start_array( b, key ); ret = bson_append_bcon_array( b, bci.A ); bson_append_finish_array( b ); break; case 'o': if (*bci.o == '\0') bson_oid_gen( &oid ); else bson_oid_from_string( &oid, bci.o ); bson_append_oid( b, key, &oid ); break; case 'b': bson_append_bool( b, key, bci.b ); break; case 't': bson_append_time_t( b, key, bci.t ); break; case 'v': bson_append_null( b, key ); break; /* void */ case 'x': bson_append_symbol( b, key, bci.x ); break; case 'i': bson_append_int( b, key, bci.i ); break; case 'l': bson_append_long( b, key, bci.l ); break; default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break; } break; case 'R': /* krv(b, key, utype, bci) */ switch (utype) { case 'f': bson_append_double( b, key, *bci.Rf ); break; case 's': bson_append_string( b, key, bci.Rs ); break; case 'D': bson_append_start_object( b, key ); ret = bson_append_bcon( b, bci.RD ); bson_append_finish_object( b ); break; case 'A': bson_append_start_array( b, key ); ret = bson_append_bcon_array( b, bci.RA ); bson_append_finish_array( b ); break; case 'o': if (*bci.o == '\0') bson_oid_gen( &oid ); else bson_oid_from_string( &oid, bci.o ); bson_append_oid( b, key, &oid ); break; case 'b': bson_append_bool( b, key, *bci.Rb ); break; case 't': bson_append_time_t( b, key, *bci.Rt ); break; case 'x': bson_append_symbol( b, key, bci.Rx ); break; case 'i': bson_append_int( b, key, *bci.Ri ); break; case 'l': bson_append_long( b, key, *bci.Rl ); break; default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break; } break; case 'P': /* kpv(b, key, utype, bci) */ if (*bci.Pv != 0) { switch (utype) { case 'f': bson_append_double( b, key, **bci.Pf ); break; case 's': bson_append_string( b, key, *bci.Ps ); break; case 'D': bson_append_start_object( b, key ); ret = bson_append_bcon( b, *bci.PD ); bson_append_finish_object( b ); break; case 'A': bson_append_start_array( b, key ); ret = bson_append_bcon_array( b, *bci.PA ); bson_append_finish_array( b ); break; case 'o': if (**bci.Po == '\0') bson_oid_gen( &oid ); else bson_oid_from_string( &oid, *bci.Po ); bson_append_oid( b, key, &oid ); break; case 'b': bson_append_bool( b, key, **bci.Pb ); break; case 't': bson_append_time_t( b, key, **bci.Pt ); break; case 'x': if (*bci.Px != 0) bson_append_symbol( b, key, *bci.Px ); break; case 'i': bson_append_int( b, key, **bci.Pi ); break; case 'l': bson_append_long( b, key, **bci.Pl ); break; default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break; } } break; default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break; } return ret; }
int mongo_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { struct inode * e; int res; size_t reallen; int32_t realend = size, blk_offset = 0; const off_t write_end = size + offset; char * lock; bson doc, cond; mongo * conn = get_conn(); uint8_t hash[20]; time_t now = time(NULL); e = (struct inode*)fi->fh; if((res = get_cached_inode(path, e)) != 0) return res; if(e->mode & S_IFDIR) return -EISDIR; /* Uncomment this for incredibly slow length calculations. for(;realend >= 0 && buf[realend] == '\0'; realend--); realend++; for(blk_offset = 0; blk_offset < realend && buf[blk_offset] == 0; blk_offset++); blk_offset -= blk_offset > 0 ? 1 : 0; * The code below uses SSE4 instructions to find the first/last * zero bytes by doing 16-byte comparisons at a time. This should give * a ~16 speed boost on blocks with lots of zero bytes over the dumb * method above. */ if(size >= 16) { __m128i zero = _mm_setzero_si128(); lock = (char*)buf + size - 16; while(lock >= buf) { __m128i x = _mm_loadu_si128((__m128i*)lock); res = _mm_movemask_epi8(_mm_cmpeq_epi8(zero, x)); if(res == 0xffff) { lock -= 16; continue; } realend = lock - buf + fls(res ^ 0xffff); break; } if(lock <= buf) realend = 0; lock = (char*)buf; while(lock - buf < realend) { __m128i x = _mm_loadu_si128((__m128i*)lock); res = _mm_movemask_epi8(_mm_cmpeq_epi8(zero, x)); if(res == 0xffff) { lock += 16; continue; } blk_offset = lock - buf + ffs(res ^ 0xffff) - 1; break; } } reallen = realend - blk_offset; if(reallen == 0) { pthread_mutex_lock(&e->wr_lock); res = insert_empty(&e->wr_extent, offset, size); goto end; } #ifdef __APPLE__ CC_SHA1(buf, size, hash); #else SHA1(buf, size, hash); #endif bson_init(&cond); bson_append_binary(&cond, "_id", 0, (char*)hash, sizeof(hash)); bson_finish(&cond); bson_init(&doc); bson_append_start_object(&doc, "$setOnInsert"); char * comp_out = get_compress_buf(); size_t comp_size = snappy_max_compressed_length(reallen); if((res = snappy_compress(buf + blk_offset, reallen, comp_out, &comp_size)) != SNAPPY_OK) { fprintf(stderr, "Error compressing input: %d\n", res); return -EIO; } bson_append_binary(&doc, "data", 0, comp_out, comp_size); bson_append_int(&doc, "offset", blk_offset); bson_append_int(&doc, "size", size); bson_append_time_t(&doc, "created", now); bson_append_finish_object(&doc); bson_finish(&doc); res = mongo_update(conn, blocks_name, &cond, &doc, MONGO_UPDATE_UPSERT, NULL); bson_destroy(&doc); bson_destroy(&cond); if(res != MONGO_OK) { fprintf(stderr, "Error committing block %s\n", conn->lasterrstr); return -EIO; } pthread_mutex_lock(&e->wr_lock); res = insert_hash(&e->wr_extent, offset, size, hash); end: if(write_end > e->size) e->size = write_end; if(now - e->wr_age > 3) { res = serialize_extent(e, e->wr_extent); if(res != 0) { pthread_mutex_unlock(&e->wr_lock); return res; } e->wr_age = now; } pthread_mutex_unlock(&e->wr_lock); if(res != 0) return res; res = update_filesize(e, write_end); if(res != 0) return res; return size; }