示例#1
0
int mongodb_module_process(fieldset_t *fs)
{
	bson_t *doc;

	if (!bulk) {
		return EXIT_FAILURE;
	}

	if (buffer_fill == BUFFER_SIZE) {
		if (mongodb_module_flush()) {
			return EXIT_FAILURE;
		}
	}

	doc = bson_new();
	for (int i=0; i < fs->len; i++) {
		field_t *f = &(fs->fields[i]);
		if (f->type == FS_STRING) {
			BSON_APPEND_UTF8(doc,f->name,f->value.ptr);
		} else if (f->type == FS_UINT64) {
			BSON_APPEND_INT64(doc,f->name,(uint64_t) f->value.num);
		} else if (f->type == FS_BINARY) {
			BSON_APPEND_BINARY(doc,f->name, BSON_SUBTYPE_BINARY,f->value.ptr, f->len);
		} else if (f->type == FS_NULL) {
			// do nothing
		} else {
			log_fatal("mongodb", "received unknown output type");
		}
	}
	mongoc_bulk_operation_insert(bulk,doc);
	buffer_fill++;
	return EXIT_SUCCESS;
}
示例#2
0
int database_find_blockchain_transaction(struct database* db, unsigned char* hash, size_t max_height, struct transaction** tx, size_t* height)
{
    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");

    // Build a query doc
    bson_t* query = bson_new();

    // Set the hash
    BSON_APPEND_BINARY(query, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)hash, 32);

    // Force the height to be valid (on the main chain)
    bson_t* height_doc = bson_new();
    BSON_APPEND_DOCUMENT_BEGIN(query, "height", height_doc);
    BSON_APPEND_INT32(height_doc, "$lte", (int)max_height);
    BSON_APPEND_INT32(height_doc, "$gte", 0);
    bson_append_document_end(query, height_doc);

    // Perform find
    mongoc_cursor_t* cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL);

    bson_error_t error;
    if(cursor == NULL || mongoc_cursor_error(cursor, &error)) {
        printf("MongoDB error: %s\n", (cursor == NULL) ? "NULL cursor" : error.message);
        return -1;
    }

    bson_t const* doc;
    int found = 0;
    while(mongoc_cursor_next(cursor, &doc) != 0) {
        if(height != NULL) {
            bson_iter_t iter;
            if(!bson_iter_init_find(&iter, doc, "height") || !BSON_ITER_HOLDS_INT32(&iter)) {
                printf("MongoDB error: tx doesn't have height!\n");
                return -1;
            }
            *height = (size_t)bson_iter_int32(&iter);
        }

        if(tx != NULL) {
            *tx = transaction_from_bson(doc);
        }

        found = 1;
        break;
    }

    mongoc_cursor_destroy(cursor);
    bson_destroy(height_doc);
    bson_destroy(query);
    mongoc_collection_destroy(collection);
    return found;
}
示例#3
0
// Find the spend of a specified output_reference within a given blockheight range (main chain only)
// if found, load tx and the input that spends it
int database_find_blockchain_spend(struct database* db, struct transaction_output_reference* output_reference, size_t start_height, size_t max_height, struct transaction** tx)
{
    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");

    // Build a query doc
    bson_t* query = bson_new();

    // Build a query that tries to find where this output_reference is spent
    unsigned char hash[32];
    transaction_output_reference_hash(output_reference, hash);

    bson_t* output_reference_doc = bson_new();
    BSON_APPEND_DOCUMENT_BEGIN(query, "inputs.output_reference", output_reference_doc);
    BSON_APPEND_BINARY(output_reference_doc, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)hash, 32);
    BSON_APPEND_INT32(output_reference_doc, "index", transaction_output_reference_index(output_reference));
    bson_append_document_end(query, output_reference_doc);

    // Force the height to be valid
    bson_t* height_doc = bson_new();
    BSON_APPEND_DOCUMENT_BEGIN(query, "height", height_doc);
    BSON_APPEND_INT32(height_doc, "$lte", (int)max_height);
    BSON_APPEND_INT32(height_doc, "$gte", start_height);
    bson_append_document_end(query, height_doc);

    // Perform find
    mongoc_cursor_t* cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL);

    bson_error_t error;
    if(cursor == NULL || mongoc_cursor_error(cursor, &error)) {
        printf("MongoDB error: %s\n", (cursor == NULL) ? "NULL cursor" : error.message);
        return -1;
    }

    bson_t const* doc;
    int found = 0;
    while(mongoc_cursor_next(cursor, &doc) != 0) {
        if(tx != NULL) {
            *tx = transaction_from_bson(doc);
        }

        found = 1;
        break;
    }

    mongoc_cursor_destroy(cursor);
    bson_destroy(height_doc);
    bson_destroy(output_reference_doc);
    bson_destroy(query);
    mongoc_collection_destroy(collection);
    return found;
}
示例#4
0
int database_has_transaction(struct database* db, unsigned char const* hash)
{
    int result = 0;

    // TODO check cache
    // check db
    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");

    // Convert the transaction to a bson document
    bson_t* query = bson_new();

    // Set the hash
    BSON_APPEND_BINARY(query, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)hash, 32);

    // Setup an empty projection so that the query returns less data
    bson_t* proj = bson_new();

    // Find
    mongoc_cursor_t* cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 1, 0, query, proj, NULL);

    bson_error_t error;
    if(cursor == NULL || mongoc_cursor_error(cursor, &error)) {
        printf("MongoDB error: %s\n", (cursor == NULL) ? "NULL cursor" : error.message);
    }

    bson_t const* doc;
    if(mongoc_cursor_next(cursor, &doc) != 0) {
        result = 1;
    }

    mongoc_cursor_destroy(cursor);
    bson_destroy(proj);
    bson_destroy(query);
    mongoc_collection_destroy(collection);

    return result;
}
示例#5
0
int database_add_orphan_transaction(struct database* db, unsigned char const* hash, struct transaction const* tx)
{
    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");
    
    // Convert the transaction to a bson document
    bson_t* doc = bson_new();
    transaction_bson(tx, doc);

    // Set the hash
    BSON_APPEND_BINARY(doc, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)hash, 32);

    // Give it a new id
    bson_oid_t oid;
    bson_oid_init(&oid, NULL);
    BSON_APPEND_OID(doc, "_id", &oid);

    // Orphan -> height = -1
    BSON_APPEND_INT32(doc, "height", -1);

#if 0
    // Print json
    char* str = bson_as_json(doc, NULL);
    printf("%s\n", str);
    bson_free(str);
#endif

    // Perform insert
    bson_error_t error;
    if(mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error) == 0) {
        printf("MongoDB error: %s\n", error.message);
    }

    bson_destroy(doc);
    mongoc_collection_destroy(collection);
    return 0;
}
示例#6
0
void switch_value(lua_State *L, int index, bson_t* bson, int level, const char* key)
{
    switch(lua_type(L, index))
    {
      case LUA_TTABLE:
      {
        int is_a=is_array(L, index);

        if (is_a)
        {
          bson_t child;
          //start array
          BSON_APPEND_ARRAY_BEGIN(bson, key, &child);
          iterate_table(L, index, &child, 0, level+1, NULL);
          bson_append_array_end(bson, &child);
        }
        else
        {
          bson_t child;
          //start map
          BSON_APPEND_DOCUMENT_BEGIN(bson, key, &child);
          iterate_table(L, index, &child, 1, level+1, NULL);
          bson_append_document_end(bson, &child);
        }
        break;
      }

      case LUA_TNIL:
      {
        BSON_APPEND_NULL(bson, key);
        break;
      }

      case LUA_TNUMBER:
      {
        BSON_APPEND_DOUBLE(bson, key, lua_tonumber(L, index));
        break;
      }

      case LUA_TBOOLEAN:
      {
        BSON_APPEND_BOOL(bson, key, lua_toboolean(L, index));
        break;
      }

      case LUA_TSTRING:
      {
        BSON_APPEND_UTF8(bson, key, lua_tostring(L, index));
        break;
      }

      case LUA_TUSERDATA:
      {
        // switch userdata type
        if (luaL_checkudata_ex(L, index, REGEX_METATABLE))
        {
          cbson_regex_t* regex = check_cbson_regex(L, index);

          BSON_APPEND_REGEX (bson, key, regex->regex, regex->options);
        }
        else if (luaL_checkudata_ex(L, index, OID_METATABLE))
        {
          cbson_oid_t* oid = check_cbson_oid(L, index);
          bson_oid_t boid;

          bson_oid_init_from_string (&boid, oid->oid);

          BSON_APPEND_OID (bson, key, &boid);
        }
        else if (luaL_checkudata_ex(L, index, BINARY_METATABLE))
        {
          cbson_binary_t* bin = check_cbson_binary(L, index);

          size_t binary_len = b64_pton (bin->data, NULL, 0);
          unsigned char* buf=malloc(binary_len+1);
          b64_pton(bin->data, buf, binary_len+1);

          BSON_APPEND_BINARY(bson, key, bin->type, buf, binary_len);

          free(buf);
        }
        else if (luaL_checkudata_ex(L, index, SYMBOL_METATABLE))
        {
          cbson_symbol_t* sym = check_cbson_symbol(L, index);

          BSON_APPEND_SYMBOL(bson, key, sym->symbol);
        }
        else if (luaL_checkudata_ex(L, index, REF_METATABLE))
        {
          cbson_ref_t* ref = check_cbson_ref(L, index);

          bson_oid_t boid;
          bson_oid_init_from_string (&boid, ref->id);

          BSON_APPEND_DBPOINTER(bson, key, ref->ref, &boid);
        }
        else if (luaL_checkudata_ex(L, index, MINKEY_METATABLE))
        {
          check_cbson_minkey(L, index);
          BSON_APPEND_MINKEY(bson, key);
        }
        else if (luaL_checkudata_ex(L, index, MAXKEY_METATABLE))
        {
          check_cbson_maxkey(L, index);
          BSON_APPEND_MAXKEY(bson, key);
        }
        else if (luaL_checkudata_ex(L, index, TIMESTAMP_METATABLE))
        {
          cbson_timestamp_t* time = check_cbson_timestamp(L, index);
          BSON_APPEND_TIMESTAMP(bson, key, time->timestamp, time->increment);
        }
        else if (luaL_checkudata_ex(L, index, INT64_METATABLE) || luaL_checkudata_ex(L, index, UINT64_METATABLE))
        {
          cbson_int64_t i = cbson_int64_check(L, index);
          if (i < INT32_MIN || i > INT32_MAX)
          {
            BSON_APPEND_INT64(bson, key, i);
          }
          else
          {
            BSON_APPEND_INT32(bson, key, (int32_t)i);
          }
        }
        else if (luaL_checkudata_ex(L, index, CODE_METATABLE))
        {
          cbson_code_t* code = check_cbson_code(L, index);
          BSON_APPEND_CODE(bson, key, code->code);
        }
        else if (luaL_checkudata_ex(L, index, CODEWSCOPE_METATABLE))
        {
          cbson_codewscope_t* code = check_cbson_codewscope(L, index);
          BSON_APPEND_CODE_WITH_SCOPE(bson, key, code->code, NULL);
        }
        else if (luaL_checkudata_ex(L, index, UNDEFINED_METATABLE))
        {
          check_cbson_undefined(L, index);
          BSON_APPEND_UNDEFINED(bson, key);
        }
        else if (luaL_checkudata_ex(L, index, DATE_METATABLE))
        {
          BSON_APPEND_DATE_TIME(bson, key, cbson_date_check(L, index));
        }
        break;
      }
      case LUA_TFUNCTION:
      case LUA_TTHREAD:
      case LUA_TLIGHTUSERDATA:
      default:
        break; // or bail out?
    }

}
示例#7
0
void transaction_bson(struct transaction const* tx, bson_t* out)
{
    char key[9];

    bson_t* input_list = bson_new();

    // Version
    BSON_APPEND_INT32(out, "version", (int)transaction_version(tx));

    // Inputs
    BSON_APPEND_ARRAY_BEGIN(out, "inputs", input_list);
    size_t num_inputs = transaction_num_inputs(tx);
    for(size_t i = 0; i < num_inputs; i++) {
        struct transaction_input* input = transaction_input(tx, i);
        
        bson_snprintf(key, sizeof(key), "%u", (unsigned int)i);
        key[sizeof(key) - 1] = '\0';

        bson_t* member = bson_new();
        bson_append_document_begin(input_list, key, -1, member);

        // Output Reference
        struct transaction_output_reference* output_reference = transaction_input_output_reference(input);
        unsigned char prevout_hash[32];
        transaction_output_reference_hash(output_reference, prevout_hash);
        bson_t* prevout = bson_new();
        bson_append_document_begin(member, "output_reference", -1, prevout);
        BSON_APPEND_BINARY(prevout, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)prevout_hash, 32);
        BSON_APPEND_INT32(prevout, "index", transaction_output_reference_index(output_reference));
        bson_append_document_end(member, prevout);

        // Script
        struct script* script = transaction_input_script(input);
        BSON_APPEND_BINARY(member, "script", BSON_SUBTYPE_BINARY, (uint8_t*)script_data(script), script_size(script));

        // Sequence
        BSON_APPEND_INT32(member, "sequence", transaction_input_sequence(input));

        bson_append_document_end(input_list, member);
    }
    bson_append_array_end(out, input_list);

    // Outputs
    bson_t* output_list = bson_new();
    BSON_APPEND_ARRAY_BEGIN(out, "outputs", output_list);
    size_t num_outputs = transaction_num_outputs(tx);
    for(size_t i = 0; i < num_outputs; i++) {
        struct transaction_output* output = transaction_output(tx, i);
        
        bson_snprintf(key, sizeof(key), "%u", (unsigned int)i);
        key[sizeof(key) - 1] = '\0';

        bson_t* member = bson_new();
        bson_append_document_begin(output_list, key, -1, member);

        // Value
        BSON_APPEND_INT64(member, "value", transaction_output_value(output));

        // Script
        struct script* script = transaction_output_script(output);
        BSON_APPEND_BINARY(member, "script", BSON_SUBTYPE_BINARY, (uint8_t*)script_data(script), script_size(script));

        bson_append_document_end(output_list, member);
    }
    bson_append_array_end(out, output_list);

    // Lock time
    BSON_APPEND_INT32(out, "lock_time", (int)transaction_lock_time(tx));
}
示例#8
0
static bool appendBsonValue(bson_t *bson, const QString &key, const QVariant &value)
{
    const QLatin1String oidkey("_id");
    bool ok = true;
    int type = value.type();

    // _id
    if (key == oidkey) {
        QByteArray oidVal = value.toByteArray();
        if (oidVal.length() == 24) {
            // ObjectId
            bson_oid_t oid;
            bson_oid_init_from_string(&oid, oidVal.data());
            BSON_APPEND_OID(bson, oidkey.latin1(), &oid);
        } else {
            int id = value.toInt(&ok);
            if (ok) {
                BSON_APPEND_INT32(bson, oidkey.latin1(), id);
            } else {
                BSON_APPEND_UTF8(bson, oidkey.latin1(), value.toString().toUtf8().data());
            }
        }
        return true;
    }

    switch (type) {
    case QVariant::Int:
        BSON_APPEND_INT32(bson, qPrintable(key), value.toInt(&ok));
        break;

    case QVariant::String:
        BSON_APPEND_UTF8(bson, qPrintable(key), value.toString().toUtf8().data());
        break;

    case QVariant::LongLong:
        BSON_APPEND_INT64(bson, qPrintable(key), value.toLongLong(&ok));
        break;

    case QVariant::Map:
        BSON_APPEND_DOCUMENT(bson, qPrintable(key), (const bson_t *)TBson::toBson(value.toMap()).constData());
        break;

    case QVariant::Double:
        BSON_APPEND_DOUBLE(bson, qPrintable(key), value.toDouble(&ok));
        break;

    case QVariant::Bool:
        BSON_APPEND_BOOL(bson, qPrintable(key), value.toBool());
        break;

    case QVariant::DateTime: {
#if QT_VERSION >= 0x040700
        BSON_APPEND_DATE_TIME(bson, qPrintable(key), value.toDateTime().toMSecsSinceEpoch());
#else
        QDateTime utcDate = value.toDateTime().toUTC();
        qint64 ms = utcDate.time().msec();
        qint64 tm = utcDate.toTime_t() * 1000LL;
        if (ms > 0) {
          tm += ms;
        }
        BSON_APPEND_DATE_TIME(bson, qPrintable(key), tm);
#endif
        break; }

    case QVariant::ByteArray: {
        QByteArray ba = value.toByteArray();
        BSON_APPEND_BINARY(bson, qPrintable(key), BSON_SUBTYPE_BINARY, (uint8_t *)ba.constData(), ba.length());
        break; }

    case QVariant::List:  // FALL THROUGH
    case QVariant::StringList: {
        bson_t child;
        BSON_APPEND_ARRAY_BEGIN(bson, qPrintable(key), &child);

        int i = 0;
        for (auto &var : value.toList()) {
            appendBsonValue(&child, QString::number(i++), var);
        }
        bson_append_array_end(bson, &child);
        break; }

    case QVariant::Invalid:
        BSON_APPEND_UNDEFINED(bson, qPrintable(key));
        break;

    default:
        tError("toBson() failed to convert  name:%s  type:%d", qPrintable(key), type);
        ok = false;
        break;
    }
    return ok;
}