Example #1
0
/*
 * __wt_metadata_read --
 *	Reads and copies a row from the metadata.
 *	The caller is responsible for freeing the allocated memory.
 */
int
__wt_metadata_read(
    WT_SESSION_IMPL *session, const char *key, const char **valuep)
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	const char *value;

	*valuep = NULL;

	if (__metadata_turtle(key))
		return (__wt_meta_turtle_read(session, key, valuep));

	WT_RET(__wt_metadata_cursor(session, NULL, &cursor));
	cursor->set_key(cursor, key);
	WT_ERR(cursor->search(cursor));
	WT_ERR(cursor->get_value(cursor, &value));
	WT_ERR(__wt_strdup(session, value, valuep));

err:	WT_TRET(cursor->close(cursor));
	return (ret);
}
Example #2
0
StatusWith<std::string> WiredTigerUtil::getMetadata(OperationContext* opCtx, StringData uri) {
    invariant(opCtx);
    WiredTigerCursor curwrap("metadata:create", WiredTigerSession::kMetadataTableId, false, opCtx);
    WT_CURSOR* cursor = curwrap.get();
    invariant(cursor);
    std::string strUri = uri.toString();
    cursor->set_key(cursor, strUri.c_str());
    int ret = cursor->search(cursor);
    if (ret == WT_NOTFOUND) {
        return StatusWith<std::string>(ErrorCodes::NoSuchKey,
                                       str::stream() << "Unable to find metadata for " << uri);
    } else if (ret != 0) {
        return StatusWith<std::string>(wtRCToStatus(ret));
    }
    const char* metadata = NULL;
    ret = cursor->get_value(cursor, &metadata);
    if (ret != 0) {
        return StatusWith<std::string>(wtRCToStatus(ret));
    }
    invariant(metadata);
    return StatusWith<std::string>(metadata);
}
Example #3
0
// static
StatusWith<uint64_t> WiredTigerUtil::getStatisticsValue(WT_SESSION* session,
                                                        const std::string& uri,
                                                        const std::string& config,
                                                        int statisticsKey) {
    invariant(session);
    WT_CURSOR* cursor = NULL;
    const char* cursorConfig = config.empty() ? NULL : config.c_str();
    int ret = session->open_cursor(session, uri.c_str(), NULL, cursorConfig, &cursor);
    if (ret != 0) {
        return StatusWith<uint64_t>(ErrorCodes::CursorNotFound,
                                    str::stream() << "unable to open cursor at URI " << uri
                                                  << ". reason: "
                                                  << wiredtiger_strerror(ret));
    }
    invariant(cursor);
    ON_BLOCK_EXIT(cursor->close, cursor);

    cursor->set_key(cursor, statisticsKey);
    ret = cursor->search(cursor);
    if (ret != 0) {
        return StatusWith<uint64_t>(
            ErrorCodes::NoSuchKey,
            str::stream() << "unable to find key " << statisticsKey << " at URI " << uri
                          << ". reason: "
                          << wiredtiger_strerror(ret));
    }

    uint64_t value;
    ret = cursor->get_value(cursor, NULL, NULL, &value);
    if (ret != 0) {
        return StatusWith<uint64_t>(
            ErrorCodes::BadValue,
            str::stream() << "unable to get value for key " << statisticsKey << " at URI " << uri
                          << ". reason: "
                          << wiredtiger_strerror(ret));
    }

    return StatusWith<uint64_t>(value);
}
Example #4
0
int 
print_overflow_pages(WT_SESSION *session)
{
	/*! [statistics retrieve by key] */
	WT_CURSOR *cursor;
	const char *desc, *pvalue;
	uint64_t value;
	int ret;

	if ((ret = session->open_cursor(session,
	    "statistics:table:access", NULL, NULL, &cursor)) != 0)
		return (ret);

	cursor->set_key(cursor, WT_STAT_DSRC_BTREE_OVERFLOW);
	ret = cursor->search(cursor);
	ret = cursor->get_value(cursor, &desc, &pvalue, &value);
	printf("%s=%s\n", desc, pvalue);

	ret = cursor->close(cursor);
	/*! [statistics retrieve by key] */

	return (ret);
}
Example #5
0
StatusWith<std::string> WiredTigerUtil::getMetadataRaw(WT_SESSION* session, StringData uri) {
    WT_CURSOR* cursor;
    invariantWTOK(session->open_cursor(session, "metadata:create", nullptr, "", &cursor));
    invariant(cursor);
    ON_BLOCK_EXIT([cursor] { invariantWTOK(cursor->close(cursor)); });

    std::string strUri = uri.toString();
    cursor->set_key(cursor, strUri.c_str());
    int ret = cursor->search(cursor);
    if (ret == WT_NOTFOUND) {
        return StatusWith<std::string>(ErrorCodes::NoSuchKey,
                                       str::stream() << "Unable to find metadata for " << uri);
    } else if (ret != 0) {
        return StatusWith<std::string>(wtRCToStatus(ret));
    }
    const char* metadata = NULL;
    ret = cursor->get_value(cursor, &metadata);
    if (ret != 0) {
        return StatusWith<std::string>(wtRCToStatus(ret));
    }
    invariant(metadata);
    return StatusWith<std::string>(metadata);
}
	void indexSearch(size_t indexId, fstring key, valvec<llong>* recIdvec) override {
		assert(started == m_status);
		assert(indexId < m_indices.size());
		WT_ITEM item;
		WT_SESSION* ses = m_session.ses;
		const Schema& schema = m_sconf.getIndexSchema(indexId);
		WT_CURSOR* cur = m_indices[indexId].insert;
		WtWritableIndex::setKeyVal(schema, cur, key, 0, &item, &m_wrtBuf);
		recIdvec->erase_all();
		if (schema.m_isUnique) {
			int err = cur->search(cur);
			BOOST_SCOPE_EXIT(cur) { cur->reset(cur); } BOOST_SCOPE_EXIT_END;
			if (WT_NOTFOUND == err) {
				return;
			}
			if (err) {
				THROW_STD(invalid_argument
					, "ERROR: wiredtiger search: %s", ses->strerror(ses, err));
			}
			llong recId = 0;
			cur->get_value(cur, &recId);
			recIdvec->push_back(recId);
		}
Example #7
0
    void WiredTigerSizeStorer::loadFrom( WiredTigerSession* session,
                                         const std::string& uri ) {
        _checkMagic();

        Map m;
        {
            WT_SESSION* s = session->getSession();
            WT_CURSOR* c = NULL;
            int ret = s->open_cursor( s, uri.c_str(), NULL, NULL, &c );
            if ( ret == ENOENT ) {
                // doesn't exist, we'll create later
                return;
            }
            invariantWTOK( ret );

            while ( c->next(c) == 0 ) {
                WT_ITEM key;
                WT_ITEM value;
                invariantWTOK( c->get_key(c, &key ) );
                invariantWTOK( c->get_value(c, &value ) );
                std::string uriKey( reinterpret_cast<const char*>( key.data ), key.size );
                BSONObj data( reinterpret_cast<const char*>( value.data ) );

                LOG(2) << "WiredTigerSizeStorer::loadFrom " << uriKey << " -> " << data;

                Entry& e = m[uriKey];
                e.numRecords = data["numRecords"].safeNumberLong();
                e.dataSize = data["dataSize"].safeNumberLong();
                e.dirty = false;
                e.rs = NULL;
            }
            invariantWTOK( c->close(c) );
        }

        boost::mutex::scoped_lock lk( _entriesMutex );
        _entries = m;
    }
Example #8
0
/*
 * __wt_metadata_search --
 *	Return a copied row from the metadata.
 *	The caller is responsible for freeing the allocated memory.
 */
int
__wt_metadata_search(WT_SESSION_IMPL *session, const char *key, char **valuep)
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	const char *value;

	*valuep = NULL;

	WT_RET(__wt_verbose(session, WT_VERB_METADATA,
	    "Search: key: %s, tracking: %s, %s" "turtle",
	    key, WT_META_TRACKING(session) ? "true" : "false",
	    __metadata_turtle(key) ? "" : "not "));

	if (__metadata_turtle(key))
		return (__wt_turtle_read(session, key, valuep));

	/*
	 * All metadata reads are at read-uncommitted isolation.  That's
	 * because once a schema-level operation completes, subsequent
	 * operations must see the current version of checkpoint metadata, or
	 * they may try to read blocks that may have been freed from a file.
	 * Metadata updates use non-transactional techniques (such as the
	 * schema and metadata locks) to protect access to in-flight updates.
	 */
	WT_RET(__wt_metadata_cursor(session, &cursor));
	cursor->set_key(cursor, key);
	WT_WITH_TXN_ISOLATION(session, WT_ISO_READ_UNCOMMITTED,
	    ret = cursor->search(cursor));
	WT_ERR(ret);

	WT_ERR(cursor->get_value(cursor, &value));
	WT_ERR(__wt_strdup(session, value, valuep));
err:	WT_TRET(__wt_metadata_cursor_release(session, &cursor));
	return (ret);
}
int main(void)
{
	int count, exact, ret;
	WT_CONNECTION *conn;
	WT_SESSION *session;
	WT_CURSOR *cursor;
	CUSTOMER cust, *custp, cust_sample[] = {
		{ 0, "Professor Oak", "LeafGreen Avenue", "123-456-7890" },
		{ 0, "Lorelei", "Sevii Islands", "098-765-4321" },
		{ 0, NULL, NULL, NULL }
	};
	CALL call, *callp, call_sample[] = {
		{ 0, 32, 1, 2, "billing", "unavailable" },
		{ 0, 33, 1, 2, "billing", "available" },
		{ 0, 34, 1, 2, "reminder", "unavailable" },
		{ 0, 35, 1, 2, "reminder", "available" },
		{ 0, 0, 0, 0, NULL, NULL }
	};

	ret = wiredtiger_open(home, NULL, "create", &conn);
	if (ret != 0) {
		fprintf(stderr, "Error connecting to %s: %s\n",
		    home, wiredtiger_strerror(ret));
		return (1);
	}
	/* Note: further error checking omitted for clarity. */

	/*! [call-center work] */
	ret = conn->open_session(conn, NULL, NULL, &session);

	/*
	 * Create the customers table, give names and types to the columns.
	 * The columns will be stored in two groups: "main" and "address",
	 * created below.
	 */
	ret = session->create(session, "table:customers",
	    "key_format=r,"
	    "value_format=SSS,"
	    "columns=(id,name,address,phone),"
	    "colgroups=(main,address)");

	/* Create the main column group with value columns except address. */
	ret = session->create(session,
	    "colgroup:customers:main", "columns=(name,phone)");

	/* Create the address column group with just the address. */
	ret = session->create(session,
	    "colgroup:customers:address", "columns=(address)");

	/* Create an index on the customer table by phone number. */
	ret = session->create(session,
	    "index:customers:phone", "columns=(phone)");

	/* Populate the customers table with some data. */
	ret = session->open_cursor(
	    session, "table:customers", NULL, "append", &cursor);
	for (custp = cust_sample; custp->name != NULL; custp++) {
		cursor->set_value(cursor,
		    custp->name, custp->address, custp->phone);
		ret = cursor->insert(cursor);
	}
	ret = cursor->close(cursor);

	/*
	 * Create the calls table, give names and types to the columns.  All the
	 * columns will be stored together, so no column groups are declared.
	 */
	ret = session->create(session, "table:calls",
	    "key_format=r,"
	    "value_format=qrrSS,"
	    "columns=(id,call_date,cust_id,emp_id,call_type,notes)");

	/*
	 * Create an index on the calls table with a composite key of cust_id
	 * and call_date.
	 */
	ret = session->create(session, "index:calls:cust_date",
	    "columns=(cust_id,call_date)");

	/* Populate the calls table with some data. */
	ret = session->open_cursor(
	    session, "table:calls", NULL, "append", &cursor);
	for (callp = call_sample; callp->call_type != NULL; callp++) {
		cursor->set_value(cursor, callp->call_date, callp->cust_id,
		    callp->emp_id, callp->call_type, callp->notes);
		ret = cursor->insert(cursor);
	}
	ret = cursor->close(cursor);

	/*
	 * First query: a call arrives.  In SQL:
	 *
	 * SELECT id, name FROM Customers WHERE phone=?
	 *
	 * Use the cust_phone index, lookup by phone number to fill the
	 * customer record.  The cursor will have a key format of "S" for a
	 * string because the cust_phone index has a single column ("phone"),
	 * which is of type "S".
	 *
	 * Specify the columns we want: the customer ID and the name.  This
	 * means the cursor's value format will be "rS".
	 */
	ret = session->open_cursor(session,
	    "index:customers:phone(id,name)", NULL, NULL, &cursor);
	cursor->set_key(cursor, "123-456-7890");
	ret = cursor->search(cursor);
	if (ret == 0) {
		ret = cursor->get_value(cursor, &cust.id, &cust.name);
		printf("Read customer record for %s (ID %" PRIu64 ")\n",
		    cust.name, cust.id);
	}
	ret = cursor->close(cursor);

	/*
	 * Next query: get the recent order history.  In SQL:
	 *
	 * SELECT * FROM Calls WHERE cust_id=? ORDER BY call_date DESC LIMIT 3
	 *
	 * Use the call_cust_date index to find the matching calls.  Since it is
	 * is in increasing order by date for a given customer, we want to start
	 * with the last record for the customer and work backwards.
	 *
	 * Specify a subset of columns to be returned.  (Note that if these were
	 * all covered by the index, the primary would not have to be accessed.)
	 * Stop after getting 3 records.
	 */
	ret = session->open_cursor(session,
	    "index:calls:cust_date(cust_id,call_type,notes)",
	    NULL, NULL, &cursor);

	/*
	 * The keys in the index are (cust_id,call_date) -- we want the largest
	 * call date for a given cust_id.  Search for (cust_id+1,0), then work
	 * backwards.
	 */
	cust.id = 1;
	cursor->set_key(cursor, cust.id + 1, 0);
	ret = cursor->search_near(cursor, &exact);

	/*
	 * If the table is empty, search_near will return WT_NOTFOUND, else the
	 * cursor will be positioned on a matching key if one exists, or an
	 * adjacent key if one does not.  If the positioned key is equal to or
	 * larger than the search key, go back one.
	 */
	if (ret == 0 && exact >= 0)
		ret = cursor->prev(cursor);
	for (count = 0; ret == 0 && count < 3; ++count) {
		ret = cursor->get_value(cursor,
		    &call.cust_id, &call.call_type, &call.notes);
		if (call.cust_id != cust.id)
			break;
		printf("Call record: customer %" PRIu64 " (%s: %s)\n",
		    call.cust_id, call.call_type, call.notes);
		ret = cursor->prev(cursor);
	}
	/*! [call-center work] */

	ret = conn->close(conn, NULL);

	return (ret);
}
int64_t WiredTigerRecordStore::cappedDeleteAsNeeded_inlock(OperationContext* txn,
                                                           const RecordId& justInserted) {
    // we do this is a side transaction in case it aborts
    WiredTigerRecoveryUnit* realRecoveryUnit =
        checked_cast<WiredTigerRecoveryUnit*>(txn->releaseRecoveryUnit());
    invariant(realRecoveryUnit);
    WiredTigerSessionCache* sc = realRecoveryUnit->getSessionCache();
    OperationContext::RecoveryUnitState const realRUstate =
        txn->setRecoveryUnit(new WiredTigerRecoveryUnit(sc), OperationContext::kNotInUnitOfWork);

    WiredTigerRecoveryUnit::get(txn)->markNoTicketRequired();  // realRecoveryUnit already has
    WT_SESSION* session = WiredTigerRecoveryUnit::get(txn)->getSession(txn)->getSession();

    int64_t dataSize = _dataSize.load();
    int64_t numRecords = _numRecords.load();

    int64_t sizeOverCap = (dataSize > _cappedMaxSize) ? dataSize - _cappedMaxSize : 0;
    int64_t sizeSaved = 0;
    int64_t docsOverCap = 0, docsRemoved = 0;
    if (_cappedMaxDocs != -1 && numRecords > _cappedMaxDocs)
        docsOverCap = numRecords - _cappedMaxDocs;

    try {
        WriteUnitOfWork wuow(txn);

        WiredTigerCursor curwrap(_uri, _tableId, true, txn);
        WT_CURSOR* c = curwrap.get();
        RecordId newestOld;
        int ret = 0;
        while ((sizeSaved < sizeOverCap || docsRemoved < docsOverCap) && (docsRemoved < 20000) &&
               (ret = WT_OP_CHECK(c->next(c))) == 0) {
            int64_t key;
            ret = c->get_key(c, &key);
            invariantWTOK(ret);

            // don't go past the record we just inserted
            newestOld = _fromKey(key);
            if (newestOld >= justInserted)  // TODO: use oldest uncommitted instead
                break;

            if (_shuttingDown)
                break;

            WT_ITEM old_value;
            invariantWTOK(c->get_value(c, &old_value));

            ++docsRemoved;
            sizeSaved += old_value.size;

            if (_cappedDeleteCallback) {
                uassertStatusOK(_cappedDeleteCallback->aboutToDeleteCapped(
                    txn,
                    newestOld,
                    RecordData(static_cast<const char*>(old_value.data), old_value.size)));
            }
        }

        if (ret != WT_NOTFOUND) {
            invariantWTOK(ret);
        }

        if (docsRemoved > 0) {
            // if we scanned to the end of the collection or past our insert, go back one
            if (ret == WT_NOTFOUND || newestOld >= justInserted) {
                ret = WT_OP_CHECK(c->prev(c));
            }
            invariantWTOK(ret);

            WiredTigerCursor startWrap(_uri, _tableId, true, txn);
            WT_CURSOR* start = startWrap.get();
            ret = WT_OP_CHECK(start->next(start));
            invariantWTOK(ret);

            ret = session->truncate(session, NULL, start, c, NULL);
            if (ret == ENOENT || ret == WT_NOTFOUND) {
                // TODO we should remove this case once SERVER-17141 is resolved
                log() << "Soft failure truncating capped collection. Will try again later.";
                docsRemoved = 0;
            } else {
                invariantWTOK(ret);
                _changeNumRecords(txn, -docsRemoved);
                _increaseDataSize(txn, -sizeSaved);
                wuow.commit();
            }
        }
    } catch (const WriteConflictException& wce) {
        delete txn->releaseRecoveryUnit();
        txn->setRecoveryUnit(realRecoveryUnit, realRUstate);
        log() << "got conflict truncating capped, ignoring";
        return 0;
    } catch (...) {
        delete txn->releaseRecoveryUnit();
        txn->setRecoveryUnit(realRecoveryUnit, realRUstate);
        throw;
    }

    delete txn->releaseRecoveryUnit();
    txn->setRecoveryUnit(realRecoveryUnit, realRUstate);
    return docsRemoved;
}
Example #11
0
/*
 * __schema_open_index --
 *	Open one or more indices for a table (internal version).
 */
static int
__schema_open_index(WT_SESSION_IMPL *session,
    WT_TABLE *table, const char *idxname, size_t len, WT_INDEX **indexp)
{
	WT_CURSOR *cursor;
	WT_DECL_ITEM(tmp);
	WT_DECL_RET;
	WT_INDEX *idx;
	u_int i;
	int cmp;
	bool match;
	const char *idxconf, *name, *tablename, *uri;

	/* Check if we've already done the work. */
	if (idxname == NULL && table->idx_complete)
		return (0);

	cursor = NULL;
	idx = NULL;
	match = false;

	/* Build a search key. */
	tablename = table->name;
	(void)WT_PREFIX_SKIP(tablename, "table:");
	WT_ERR(__wt_scr_alloc(session, 512, &tmp));
	WT_ERR(__wt_buf_fmt(session, tmp, "index:%s:", tablename));

	/* Find matching indices. */
	WT_ERR(__wt_metadata_cursor(session, &cursor));
	cursor->set_key(cursor, tmp->data);
	if ((ret = cursor->search_near(cursor, &cmp)) == 0 && cmp < 0)
		ret = cursor->next(cursor);
	for (i = 0; ret == 0; i++, ret = cursor->next(cursor)) {
		WT_ERR(cursor->get_key(cursor, &uri));
		name = uri;
		if (!WT_PREFIX_SKIP(name, tmp->data))
			break;

		/* Is this the index we are looking for? */
		match = idxname == NULL || WT_STRING_MATCH(name, idxname, len);

		/*
		 * Ensure there is space, including if we have to make room for
		 * a new entry in the middle of the list.
		 */
		WT_ERR(__wt_realloc_def(session, &table->idx_alloc,
		    WT_MAX(i, table->nindices) + 1, &table->indices));

		/* Keep the in-memory list in sync with the metadata. */
		cmp = 0;
		while (table->indices[i] != NULL &&
		    (cmp = strcmp(uri, table->indices[i]->name)) > 0) {
			/* Index no longer exists, remove it. */
			__wt_free(session, table->indices[i]);
			memmove(&table->indices[i], &table->indices[i + 1],
			    (table->nindices - i) * sizeof(WT_INDEX *));
			table->indices[--table->nindices] = NULL;
		}
		if (cmp < 0) {
			/* Make room for a new index. */
			memmove(&table->indices[i + 1], &table->indices[i],
			    (table->nindices - i) * sizeof(WT_INDEX *));
			table->indices[i] = NULL;
			++table->nindices;
		}

		if (!match)
			continue;

		if (table->indices[i] == NULL) {
			WT_ERR(cursor->get_value(cursor, &idxconf));
			WT_ERR(__wt_calloc_one(session, &idx));
			WT_ERR(__wt_strdup(session, uri, &idx->name));
			WT_ERR(__wt_strdup(session, idxconf, &idx->config));
			WT_ERR(__open_index(session, table, idx));

			/*
			 * If we're checking the creation of an index before a
			 * table is fully created, don't save the index: it
			 * will need to be reopened once the table is complete.
			 */
			if (!table->cg_complete) {
				WT_ERR(
				    __wt_schema_destroy_index(session, &idx));
				if (idxname != NULL)
					break;
				continue;
			}

			table->indices[i] = idx;
			idx = NULL;

			/*
			 * If the slot is bigger than anything else we've seen,
			 * bump the number of indices.
			 */
			if (i >= table->nindices)
				table->nindices = i + 1;
		}

		/* If we were looking for a single index, we're done. */
		if (indexp != NULL)
			*indexp = table->indices[i];
		if (idxname != NULL)
			break;
	}
	WT_ERR_NOTFOUND_OK(ret);
	if (idxname != NULL && !match)
		ret = WT_NOTFOUND;

	/* If we did a full pass, we won't need to do it again. */
	if (idxname == NULL) {
		table->nindices = i;
		table->idx_complete = true;
	}

err:	WT_TRET(__wt_metadata_cursor_release(session, &cursor));
	WT_TRET(__wt_schema_destroy_index(session, &idx));

	__wt_scr_free(session, &tmp);
	return (ret);
}
Example #12
0
/*
 * wts_stats --
 *	Dump the run's statistics.
 */
void
wts_stats(void)
{
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_SESSION *session;
	FILE *fp;
	char *stat_name;
	const char *pval, *desc;
	uint64_t v;
	int ret;

	track("stat", 0ULL, NULL);

	conn = g.wts_conn;
	if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
		die(ret, "connection.open_session");

	if ((fp = fopen("RUNDIR/stats", "w")) == NULL)
		die(errno, "fopen: RUNDIR/stats");

	/* Connection statistics. */
	fprintf(fp, "====== Connection statistics:\n");
	if ((ret = session->open_cursor(session,
	    "statistics:", NULL, NULL, &cursor)) != 0)
		die(ret, "session.open_cursor");

	while ((ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0)
		if (fprintf(fp, "%s=%s\n", desc, pval) < 0)
			die(errno, "fprintf");

	if (ret != WT_NOTFOUND)
		die(ret, "cursor.next");
	if ((ret = cursor->close(cursor)) != 0)
		die(ret, "cursor.close");

	/*
	 * XXX
	 * WiredTiger only supports file object statistics.
	 */
	if (strcmp(g.c_data_source, "file") != 0)
		goto skip;

	/* File statistics. */
	fprintf(fp, "\n\n====== File statistics:\n");
	if ((stat_name =
	    malloc(strlen("statistics:") + strlen(g.uri) + 1)) == NULL)
		syserr("malloc");
	sprintf(stat_name, "statistics:%s", g.uri);
	if ((ret = session->open_cursor(
	    session, stat_name, NULL, NULL, &cursor)) != 0)
		die(ret, "session.open_cursor");
	free(stat_name);

	while ((ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0)
		if (fprintf(fp, "%s=%s\n", desc, pval) < 0)
			die(errno, "fprintf");

	if (ret != WT_NOTFOUND)
		die(ret, "cursor.next");
	if ((ret = cursor->close(cursor)) != 0)
		die(ret, "cursor.close");

skip:	if ((ret = fclose(fp)) != 0)
		die(ret, "fclose");

	if ((ret = session->close(session, NULL)) != 0)
		die(ret, "session.close");
}
Example #13
0
int
util_read(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	uint64_t recno;
	int ch;
	bool rkey, rval;
	char *uri, *value;

	uri = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	/* The remaining arguments are a uri followed by a list of keys. */
	if (argc < 2)
		return (usage());
	if ((uri = util_uri(session, *argv, "table")) == NULL)
		return (1);

	/*
	 * Open the object; free allocated memory immediately to simplify
	 * future error handling.
	 */
	if ((ret =
	    session->open_cursor(session, uri, NULL, NULL, &cursor)) != 0)
		(void)util_err(session, ret, "%s: session.open_cursor", uri);
	free(uri);
	if (ret != 0)
		return (ret);

	/*
	 * A simple search only makes sense if the key format is a string or a
	 * record number, and the value format is a single string.
	 */
	if (strcmp(cursor->key_format, "r") != 0 &&
	    strcmp(cursor->key_format, "S") != 0) {
		fprintf(stderr,
		    "%s: read command only possible when the key format is "
		    "a record number or string\n",
		    progname);
		return (1);
	}
	rkey = strcmp(cursor->key_format, "r") == 0;
	if (strcmp(cursor->value_format, "S") != 0) {
		fprintf(stderr,
		    "%s: read command only possible when the value format is "
		    "a string\n",
		    progname);
		return (1);
	}

	/*
	 * Run through the keys, returning non-zero on error or if any requested
	 * key isn't found.
	 */
	for (rval = false; *++argv != NULL;) {
		if (rkey) {
			if (util_str2recno(session, *argv, &recno))
				return (1);
			cursor->set_key(cursor, recno);
		} else
			cursor->set_key(cursor, *argv);

		switch (ret = cursor->search(cursor)) {
		case 0:
			if ((ret = cursor->get_value(cursor, &value)) != 0)
				return (util_cerr(cursor, "get_value", ret));
			if (printf("%s\n", value) < 0)
				return (util_err(session, EIO, NULL));
			break;
		case WT_NOTFOUND:
			(void)util_err(session, 0, "%s: not found", *argv);
			rval = true;
			break;
		default:
			return (util_cerr(cursor, "search", ret));
		}
	}

	return (rval ? 1 : 0);
}
Example #14
0
int
util_stat(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	size_t urilen;
	int ch;
	bool objname_free;
	const char *config, *pval, *desc;
	char *objname, *uri;

	objname_free = false;
	objname = uri = NULL;
	config = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "af")) != EOF)
		switch (ch) {
		case 'a':
			/*
			 * Historically, the -a option meant include all of the
			 * statistics; because we are opening the database with
			 * statistics=(all), that is now the default, allow the
			 * option for compatibility.
			 */
			config = NULL;
			break;
		case 'f':
			config = "statistics=(fast)";
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	/*
	 * If there are no arguments, the statistics cursor operates on the
	 * connection, otherwise, the optional remaining argument is a file
	 * or LSM name.
	 */
	switch (argc) {
	case 0:
		objname = (char *)"";
		break;
	case 1:
		if ((objname = util_name(session, *argv, "table")) == NULL)
			return (1);
		objname_free = true;
		break;
	default:
		return (usage());
	}

	urilen = strlen("statistics:") + strlen(objname) + 1;
	if ((uri = calloc(urilen, 1)) == NULL) {
		fprintf(stderr, "%s: %s\n", progname, strerror(errno));
		goto err;
	}
	snprintf(uri, urilen, "statistics:%s", objname);

	if ((ret =
	    session->open_cursor(session, uri, NULL, config, &cursor)) != 0) {
		fprintf(stderr, "%s: cursor open(%s) failed: %s\n",
		    progname, uri, session->strerror(session, ret));
		goto err;
	}

	/* List the statistics. */
	while (
	    (ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, NULL)) == 0)
		if (printf("%s=%s\n", desc, pval) < 0) {
			ret = errno;
			break;
		}
	if (ret == WT_NOTFOUND)
		ret = 0;

	if (ret != 0) {
		fprintf(stderr, "%s: cursor get(%s) failed: %s\n",
		    progname, objname, session->strerror(session, ret));
		goto err;
	}

	if (0) {
err:		ret = 1;
	}
	if (objname_free)
		free(objname);
	free(uri);

	return (ret);
}
Example #15
0
File: main.c Project: jbreams/mongo
int
main(int argc, char *argv[])
{
	TEST_OPTS *opts, _opts;
	WT_CURSOR *c;
	WT_SESSION *session;
	clock_t ce, cs;
	pthread_t id[100];
	uint64_t current_value;
	int i;

	opts = &_opts;
	if (testutil_disable_long_tests())
		return (0);
	memset(opts, 0, sizeof(*opts));
	opts->nthreads = 10;
	opts->nrecords = 1000;
	opts->table_type = TABLE_ROW;
	testutil_check(testutil_parse_opts(argc, argv, opts));
	testutil_make_work_dir(opts->home);

	testutil_check(wiredtiger_open(opts->home, NULL,
	    "create,"
	    "cache_size=2G,"
	    "eviction=(threads_max=5),"
	    "statistics=(fast)", &opts->conn));
	testutil_check(
	    opts->conn->open_session(opts->conn, NULL, NULL, &session));
	testutil_check(session->create(session, opts->uri,
	    "key_format=Q,value_format=Q,"
	    "leaf_page_max=32k,"));

	/* Create the single record. */
	testutil_check(
	    session->open_cursor(session, opts->uri, NULL, NULL, &c));
	c->set_key(c, 1);
	c->set_value(c, 0);
	testutil_check(c->insert(c));
	testutil_check(c->close(c));
	cs = clock();
	for (i = 0; i < (int)opts->nthreads; ++i) {
		testutil_check(pthread_create(
		    &id[i], NULL, thread_insert_race, (void *)opts));
	}
	while (--i >= 0)
		testutil_check(pthread_join(id[i], NULL));
	testutil_check(
	    session->open_cursor(session, opts->uri, NULL, NULL, &c));
	c->set_key(c, 1);
	testutil_check(c->search(c));
	testutil_check(c->get_value(c, &current_value));
	if (current_value != opts->nthreads * opts->nrecords) {
		fprintf(stderr,
		    "ERROR: didn't get expected number of changes\n");
		fprintf(stderr, "got: %" PRIu64 ", expected: %" PRIu64 "\n",
		    current_value, opts->nthreads * opts->nrecords);
		return (EXIT_FAILURE);
	}
	testutil_check(session->close(session, NULL));
	ce = clock();
	printf("%" PRIu64 ": %.2lf\n",
	    opts->nrecords, (ce - cs) / (double)CLOCKS_PER_SEC);

	testutil_cleanup(opts);
	return (EXIT_SUCCESS);
}
Example #16
0
/*
 * __wt_schema_open_table --
 *	Open a named table.
 */
int
__wt_schema_open_table(WT_SESSION_IMPL *session,
    const char *name, size_t namelen, WT_TABLE **tablep)
{
	WT_CONFIG cparser;
	WT_CONFIG_ITEM ckey, cval;
	WT_CURSOR *cursor;
	WT_DECL_RET;
	WT_ITEM buf;
	WT_TABLE *table;
	const char *tconfig;
	char *tablename;

	cursor = NULL;
	table = NULL;

	WT_CLEAR(buf);
	WT_RET(__wt_buf_fmt(session, &buf, "table:%.*s", (int)namelen, name));
	tablename = __wt_buf_steal(session, &buf, NULL);

	WT_ERR(__wt_metadata_cursor(session, NULL, &cursor));
	cursor->set_key(cursor, tablename);
	WT_ERR(cursor->search(cursor));
	WT_ERR(cursor->get_value(cursor, &tconfig));

	WT_ERR(__wt_calloc_def(session, 1, &table));
	table->name = tablename;
	tablename = NULL;

	WT_ERR(__wt_config_getones(session, tconfig, "columns", &cval));

	WT_ERR(__wt_config_getones(session, tconfig, "key_format", &cval));
	WT_ERR(__wt_strndup(session, cval.str, cval.len, &table->key_format));
	WT_ERR(__wt_config_getones(session, tconfig, "value_format", &cval));
	WT_ERR(__wt_strndup(session, cval.str, cval.len, &table->value_format));
	WT_ERR(__wt_strdup(session, tconfig, &table->config));

	/* Point to some items in the copy to save re-parsing. */
	WT_ERR(__wt_config_getones(session, table->config,
	    "columns", &table->colconf));

	/*
	 * Count the number of columns: tables are "simple" if the columns
	 * are not named.
	 */
	WT_ERR(__wt_config_subinit(session, &cparser, &table->colconf));
	table->is_simple = 1;
	while ((ret = __wt_config_next(&cparser, &ckey, &cval)) == 0)
		table->is_simple = 0;
	if (ret != WT_NOTFOUND)
		goto err;

	/* Check that the columns match the key and value formats. */
	if (!table->is_simple)
		WT_ERR(__wt_schema_colcheck(session,
		    table->key_format, table->value_format, &table->colconf,
		    &table->nkey_columns, NULL));

	WT_ERR(__wt_config_getones(session, table->config,
	    "colgroups", &table->cgconf));

	/* Count the number of column groups. */
	WT_ERR(__wt_config_subinit(session, &cparser, &table->cgconf));
	table->ncolgroups = 0;
	while ((ret = __wt_config_next(&cparser, &ckey, &cval)) == 0)
		++table->ncolgroups;
	if (ret != WT_NOTFOUND)
		goto err;

	WT_ERR(__wt_calloc_def(session, WT_COLGROUPS(table), &table->cgroups));
	WT_ERR(__wt_schema_open_colgroups(session, table));
	*tablep = table;

	if (0) {
err:		if (table != NULL)
			__wt_schema_destroy_table(session, table);
	}
	if (cursor != NULL)
		WT_TRET(cursor->close(cursor));
	__wt_free(session, tablename);
	return (ret);
}
Example #17
0
int
util_stat(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	uint64_t v;
	size_t urilen;
	int ch, objname_free, ret;
	const char *pval, *desc;
	char *objname, *uri;

	objname_free = 0;
	objname = uri = NULL;
	while ((ch = util_getopt(argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/*
	 * If there are no arguments, the statistics cursor operates on the
	 * connection, otherwise, the optional remaining argument is a file
	 * name.
	 */
	switch (argc) {
	case 0:
		objname = (char *)"";
		break;
	case 1:
		if ((objname = util_name(*argv, "file", UTIL_FILE_OK)) == NULL)
			return (1);
		objname_free = 1;
		break;
	default:
		return (usage());
	}

	urilen = strlen("statistics:") + strlen(objname) + 1;
	if ((uri = calloc(urilen, 1)) == NULL) {
		fprintf(stderr, "%s: %s\n", progname, strerror(errno));
		return (1);
	}
	snprintf(uri, urilen, "statistics:%s", objname);

	if ((ret = session->open_cursor(
	    session, uri, NULL, NULL, &cursor)) != 0) {
		fprintf(stderr, "%s: cursor open(%s) failed: %s\n",
		    progname, uri, wiredtiger_strerror(ret));
		goto err;
	}

	/* List the statistics. */
	while (
	    (ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0)
		if (printf("%s=%s\n", desc, pval) < 0) {
			ret = errno;
			break;
		}
	if (ret == WT_NOTFOUND)
		ret = 0;

	if (ret != 0) {
		fprintf(stderr, "%s: cursor get(%s) failed: %s\n",
		    progname, objname, wiredtiger_strerror(ret));
		goto err;
	}

err:	if (objname_free)
		free(objname);
	free(uri);

	return (ret);
}
Example #18
0
/*
 * __curjoin_entry_member --
 *	Do a membership check for a particular index that was joined,
 *	if not a member, returns WT_NOTFOUND.
 */
static int
__curjoin_entry_member(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
    WT_CURSOR_JOIN_ENTRY *entry, bool skip_left)
{
	WT_CURJOIN_EXTRACTOR extract_cursor;
	WT_CURSOR *c;
	WT_CURSOR_STATIC_INIT(iface,
	    __wt_cursor_get_key,	/* get-key */
	    __wt_cursor_get_value,	/* get-value */
	    __wt_cursor_set_key,	/* set-key */
	    __wt_cursor_set_value,	/* set-value */
	    __wt_cursor_notsup,		/* compare */
	    __wt_cursor_notsup,		/* equals */
	    __wt_cursor_notsup,		/* next */
	    __wt_cursor_notsup,		/* prev */
	    __wt_cursor_notsup,		/* reset */
	    __wt_cursor_notsup,		/* search */
	    __wt_cursor_notsup,		/* search-near */
	    __curjoin_extract_insert,	/* insert */
	    __wt_cursor_notsup,		/* update */
	    __wt_cursor_notsup,		/* reconfigure */
	    __wt_cursor_notsup,		/* remove */
	    __wt_cursor_notsup);	/* close */
	WT_DECL_RET;
	WT_INDEX *idx;
	WT_ITEM *key, v;
	bool bloom_found;

	key = cjoin->iter->curkey;
	entry->stats.accesses++;
	bloom_found = false;

	if (entry->bloom != NULL) {
		/*
		 * If we don't own the Bloom filter, we must be sharing one
		 * in a previous entry. So the shared filter has already
		 * been checked and passed.
		 */
		if (!F_ISSET(entry, WT_CURJOIN_ENTRY_OWN_BLOOM))
			return (0);

		/*
		 * If the item is not in the Bloom filter, we return
		 * immediately, otherwise, we still need to check the
		 * long way.
		 */
		WT_ERR(__wt_bloom_inmem_get(entry->bloom, key));
		bloom_found = true;
	}
	if (entry->index != NULL) {
		memset(&v, 0, sizeof(v));  /* Keep lint quiet. */
		c = entry->main;
		c->set_key(c, key);
		if ((ret = c->search(c)) == 0)
			ret = c->get_value(c, &v);
		else if (ret == WT_NOTFOUND)
			WT_ERR_MSG(session, WT_ERROR,
			    "main table for join is missing entry.");
		WT_TRET(c->reset(c));
		WT_ERR(ret);
	} else
		v = *key;

	if ((idx = entry->index) != NULL && idx->extractor != NULL) {
		extract_cursor.iface = iface;
		extract_cursor.iface.session = &session->iface;
		extract_cursor.iface.key_format = idx->exkey_format;
		extract_cursor.ismember = 0;
		extract_cursor.entry = entry;
		WT_ERR(idx->extractor->extract(idx->extractor,
		    &session->iface, key, &v, &extract_cursor.iface));
		if (!extract_cursor.ismember)
			WT_ERR(WT_NOTFOUND);
	} else
		WT_ERR(__curjoin_entry_in_range(session, entry, &v, skip_left));

	if (0) {
err:		if (ret == WT_NOTFOUND && bloom_found)
			entry->stats.bloom_false_positive++;
	}
	return (ret);
}
Example #19
0
    Status WiredTigerUtil::exportTableToBSON(WT_SESSION* session,
                                             const std::string& uri, const std::string& config,
                                             BSONObjBuilder* bob) {
        invariant(session);
        invariant(bob);
        WT_CURSOR* c = NULL;
        const char *cursorConfig = config.empty() ? NULL : config.c_str();
        int ret = session->open_cursor(session, uri.c_str(), NULL, cursorConfig, &c);
        if (ret != 0) {
            return Status(ErrorCodes::CursorNotFound, str::stream()
                << "unable to open cursor at URI " << uri
                << ". reason: " << wiredtiger_strerror(ret));
        }
        bob->append("uri", uri);
        invariant(c);
        ON_BLOCK_EXIT(c->close, c);

        std::map<string,BSONObjBuilder*> subs;
        const char *desc, *pvalue;
        uint64_t value;
        while (c->next(c) == 0 && c->get_value(c, &desc, &pvalue, &value) == 0) {
            StringData key( desc );

            StringData prefix;
            StringData suffix;

            size_t idx = key.find( ':' );
            if ( idx != string::npos ) {
                prefix = key.substr( 0, idx );
                suffix = key.substr( idx + 1 );
            }
            else {
                idx = key.find( ' ' );
            }

            if ( idx != string::npos ) {
                prefix = key.substr( 0, idx );
                suffix = key.substr( idx + 1 );
            }
            else {
                prefix = key;
                suffix = "num";
            }

            // Convert unsigned 64-bit integral value of statistic to BSON-friendly long long.
            // If there is an overflow, set statistic value to max(long long).
            const long long maxLL = std::numeric_limits<long long>::max();
            long long v =  value > static_cast<uint64_t>(maxLL) ?
                maxLL : static_cast<long long>(value);

            if ( prefix.size() == 0 ) {
                bob->appendNumber(desc, v);
            }
            else {
                BSONObjBuilder*& sub = subs[prefix.toString()];
                if ( !sub )
                    sub = new BSONObjBuilder();
                sub->appendNumber(mongoutils::str::ltrim(suffix.toString()), v);
            }
        }

        for ( std::map<string,BSONObjBuilder*>::const_iterator it = subs.begin();
              it != subs.end(); ++it ) {
            const std::string& s = it->first;
            bob->append( s, it->second->obj() );
            delete it->second;
        }
        return Status::OK();
    }
Example #20
0
void *
stat_worker(void *arg)
{
	CONFIG *cfg;
	WT_CONNECTION *conn;
	WT_SESSION *session;
	WT_CURSOR *cursor;
	const char *desc, *pvalue;
	char *lsm_uri;
	double secs;
	int ret;
	struct timeval e;
	uint64_t value;

	cfg = (CONFIG *)arg;
	conn = cfg->conn;
	lsm_uri = NULL;

	if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
		fprintf(stderr,
		    "open_session failed in read thread: %d\n", ret);
		return (NULL);
	}

	if (strncmp(cfg->uri, "lsm:", strlen("lsm:")) == 0) {
		lsm_uri = calloc(
		    strlen(cfg->uri) + strlen("statistics:") + 1, 1);
		if (lsm_uri == NULL) {
			fprintf(stderr, "No memory in stat thread.\n");
			goto err;
		}
		sprintf(lsm_uri, "statistics:%s", cfg->uri);
	}

	while (stat_running) {
		sleep(cfg->report_interval);
		/* Generic header. */
		fprintf(cfg->logf, "=======================================\n");
		gettimeofday(&e, NULL);
		secs = e.tv_sec + e.tv_usec / 1000000.0;
		secs -= (cfg->phase_start_time.tv_sec +
		    cfg->phase_start_time.tv_usec / 1000000.0);
		if (secs == 0)
			++secs;
		fprintf(cfg->logf,
		    "%s completed: %" PRIu64", elapsed time: %.2f\n",
		    cfg->phase == LSM_TEST_PERF_READ ? "reads" : "inserts",
		    nops, secs);
		/* Report LSM tree stats, if using LSM. */
		if (lsm_uri != NULL) {
			if ((ret = session->open_cursor(session, lsm_uri,
			    NULL, NULL, &cursor)) != 0) {
				fprintf(stderr,
				    "open_cursor LSM statistics: %d\n", ret);
				goto err;
			}
			while (
			    (ret = cursor->next(cursor)) == 0 &&
			    (ret = cursor->get_value(
			    cursor, &desc, &pvalue, &value)) == 0)
				fprintf(cfg->logf,
				    "stat:lsm: %s=%s\n", desc, pvalue);
			cursor->close(cursor);
			fprintf(cfg->logf, "\n");
		}

		/* Dump the connection statistics since last time. */
		if ((ret = session->open_cursor(session, "statistics:",
		    NULL, "statistics_clear", &cursor)) != 0) {
			fprintf(stderr,
			    "open_cursor statistics: %d\n", ret);
			goto err;
		}
		while (
		    (ret = cursor->next(cursor)) == 0 &&
		    (ret = cursor->get_value(
		    cursor, &desc, &pvalue, &value)) == 0)
			fprintf(cfg->logf,
			    "stat:conn: %s=%s\n", desc, pvalue);
		cursor->close(cursor);

	}
err:	session->close(session, NULL);
	if (lsm_uri != NULL)
		free(lsm_uri);
	return (arg);
}
Example #21
0
/*
 * __curjoin_entry_member --
 *	Do a membership check for a particular index that was joined,
 *	if not a member, returns WT_NOTFOUND.
 */
static int
__curjoin_entry_member(WT_SESSION_IMPL *session, WT_CURSOR_JOIN_ENTRY *entry,
    WT_ITEM *key, WT_CURSOR_JOIN_ITER *iter)
{
	WT_CURJOIN_EXTRACTOR extract_cursor;
	WT_CURSOR *c;
	WT_CURSOR_STATIC_INIT(iface,
	    __wt_cursor_get_key,		/* get-key */
	    __wt_cursor_get_value,		/* get-value */
	    __wt_cursor_set_key,		/* set-key */
	    __wt_cursor_set_value,		/* set-value */
	    __wt_cursor_compare_notsup,		/* compare */
	    __wt_cursor_equals_notsup,		/* equals */
	    __wt_cursor_notsup,			/* next */
	    __wt_cursor_notsup,			/* prev */
	    __wt_cursor_notsup,			/* reset */
	    __wt_cursor_notsup,			/* search */
	    __wt_cursor_search_near_notsup,	/* search-near */
	    __curjoin_extract_insert,		/* insert */
	    __wt_cursor_modify_notsup,		/* modify */
	    __wt_cursor_notsup,			/* update */
	    __wt_cursor_notsup,			/* remove */
	    __wt_cursor_notsup,			/* reserve */
	    __wt_cursor_reconfigure_notsup,	/* reconfigure */
	    __wt_cursor_notsup,			/* cache */
	    __wt_cursor_reopen_notsup,		/* reopen */
	    __wt_cursor_notsup);		/* close */
	WT_DECL_RET;
	WT_INDEX *idx;
	WT_ITEM v;
	bool bloom_found;

	if (entry->subjoin == NULL && iter != NULL &&
	    (iter->end_pos + iter->end_skip >= entry->ends_next ||
	    (iter->end_skip > 0 &&
	    F_ISSET(entry, WT_CURJOIN_ENTRY_DISJUNCTION))))
		return (0);	/* no checks to make */

	entry->stats.membership_check++;
	bloom_found = false;

	if (entry->bloom != NULL) {
		/*
		 * If the item is not in the Bloom filter, we return
		 * immediately, otherwise, we still may need to check the
		 * long way, since it may be a false positive.
		 *
		 * If we don't own the Bloom filter, we must be sharing one
		 * in a previous entry. So the shared filter has already
		 * been checked and passed, we don't need to check it again.
		 * We'll still need to check the long way.
		 */
		if (F_ISSET(entry, WT_CURJOIN_ENTRY_OWN_BLOOM))
			WT_ERR(__wt_bloom_inmem_get(entry->bloom, key));
		if (F_ISSET(entry, WT_CURJOIN_ENTRY_FALSE_POSITIVES))
			return (0);
		bloom_found = true;
	}
	if (entry->subjoin != NULL) {
		WT_ASSERT(session,
		    iter == NULL || entry->subjoin == iter->child->cjoin);
		ret = __curjoin_entries_in_range(session, entry->subjoin,
		    key, iter == NULL ? NULL : iter->child);
		if (iter != NULL &&
		    WT_CURJOIN_ITER_CONSUMED(iter->child)) {
			WT_ERR(__curjoin_iter_bump(iter));
			ret = WT_NOTFOUND;
		}
		return (ret);
	}
	if (entry->index != NULL) {
		/*
		 * If this entry is used by the iterator, then we already
		 * have the index key, and we won't have to do any
		 * extraction either.
		 */
		if (iter != NULL && entry == iter->entry)
			WT_ITEM_SET(v, iter->idxkey);
		else {
			memset(&v, 0, sizeof(v));	/* Keep lint quiet. */
			c = entry->main;
			c->set_key(c, key);
			entry->stats.main_access++;
			if ((ret = c->search(c)) == 0)
				ret = c->get_value(c, &v);
			else if (ret == WT_NOTFOUND) {
				__wt_err(session, ret,
				    "main table for join is missing entry");
				ret = WT_ERROR;
			}
			WT_TRET(c->reset(c));
			WT_ERR(ret);
		}
	} else
		WT_ITEM_SET(v, *key);

	if ((idx = entry->index) != NULL && idx->extractor != NULL &&
	    (iter == NULL || entry != iter->entry)) {
		WT_CLEAR(extract_cursor);
		extract_cursor.iface = iface;
		extract_cursor.iface.session = &session->iface;
		extract_cursor.iface.key_format = idx->exkey_format;
		extract_cursor.ismember = false;
		extract_cursor.entry = entry;
		WT_ERR(idx->extractor->extract(idx->extractor,
		    &session->iface, key, &v, &extract_cursor.iface));
		__wt_buf_free(session, &extract_cursor.iface.key);
		__wt_buf_free(session, &extract_cursor.iface.value);
		if (!extract_cursor.ismember)
			WT_ERR(WT_NOTFOUND);
	} else
		WT_ERR(__curjoin_entry_in_range(session, entry, &v, iter));

	if (0) {
err:		if (ret == WT_NOTFOUND && bloom_found)
			entry->stats.bloom_false_positive++;
	}
	return (ret);
}
Example #22
0
int
main(void)
{
	/*! [access example connection] */
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_SESSION *session;
	const char *key, *value;
	int ret;

	/*
	 * Create a clean test directory for this run of the test program if the
	 * environment variable isn't already set (as is done by make check).
	 */
	if (getenv("WIREDTIGER_HOME") == NULL) {
		home = "WT_HOME";
		ret = system("rm -rf WT_HOME && mkdir WT_HOME");
	} else
		home = NULL;

	/* Open a connection to the database, creating it if necessary. */
	if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
	    (ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
		fprintf(stderr, "Error connecting to %s: %s\n",
		    home, wiredtiger_strerror(ret));
		return (ret);
	}
	/*! [access example connection] */

	/*! [access example table create] */
	ret = session->create(session,
	    "table:access", "key_format=S,value_format=S");
	/*! [access example table create] */

	/*! [access example cursor open] */
	ret = session->open_cursor(session,
	    "table:access", NULL, NULL, &cursor);
	/*! [access example cursor open] */

	/*! [access example cursor insert] */
	cursor->set_key(cursor, "key1");	/* Insert a record. */
	cursor->set_value(cursor, "value1");
	ret = cursor->insert(cursor);
	/*! [access example cursor insert] */

	/*! [access example cursor list] */
	ret = cursor->reset(cursor);	        /* Restart the scan. */
	while ((ret = cursor->next(cursor)) == 0) {
		ret = cursor->get_key(cursor, &key);
		ret = cursor->get_value(cursor, &value);

		printf("Got record: %s : %s\n", key, value);
	}
	/*! [access example cursor list] */

	/*! [access example close] */
	ret = conn->close(conn, NULL);
	/*! [access example close] */

	return (ret);
}
Example #23
0
/*
 * __las_page_instantiate --
 *	Instantiate lookaside update records in a recently read page.
 */
static int
__las_page_instantiate(WT_SESSION_IMPL *session,
    WT_REF *ref, uint32_t read_id, const uint8_t *addr, size_t addr_size)
{
	WT_CURSOR *cursor;
	WT_CURSOR_BTREE cbt;
	WT_DECL_ITEM(current_key);
	WT_DECL_ITEM(las_addr);
	WT_DECL_ITEM(las_key);
	WT_DECL_ITEM(las_value);
	WT_DECL_RET;
	WT_PAGE *page;
	WT_UPDATE *first_upd, *last_upd, *upd;
	size_t incr, total_incr;
	uint64_t current_recno, las_counter, las_txnid, recno, upd_txnid;
	uint32_t las_id, upd_size, session_flags;
	int exact;
	const uint8_t *p;

	cursor = NULL;
	page = ref->page;
	first_upd = last_upd = upd = NULL;
	total_incr = 0;
	current_recno = recno = WT_RECNO_OOB;
	session_flags = 0;		/* [-Werror=maybe-uninitialized] */

	__wt_btcur_init(session, &cbt);
	__wt_btcur_open(&cbt);

	WT_ERR(__wt_scr_alloc(session, 0, &current_key));
	WT_ERR(__wt_scr_alloc(session, 0, &las_addr));
	WT_ERR(__wt_scr_alloc(session, 0, &las_key));
	WT_ERR(__wt_scr_alloc(session, 0, &las_value));

	/* Open a lookaside table cursor. */
	WT_ERR(__wt_las_cursor(session, &cursor, &session_flags));

	/*
	 * The lookaside records are in key and update order, that is, there
	 * will be a set of in-order updates for a key, then another set of
	 * in-order updates for a subsequent key. We process all of the updates
	 * for a key and then insert those updates into the page, then all the
	 * updates for the next key, and so on.
	 *
	 * Search for the block's unique prefix, stepping through any matching
	 * records.
	 */
	las_addr->data = addr;
	las_addr->size = addr_size;
	las_key->size = 0;
	cursor->set_key(
	    cursor, read_id, las_addr, (uint64_t)0, (uint32_t)0, las_key);
	if ((ret = cursor->search_near(cursor, &exact)) == 0 && exact < 0)
		ret = cursor->next(cursor);
	for (; ret == 0; ret = cursor->next(cursor)) {
		WT_ERR(cursor->get_key(cursor,
		    &las_id, las_addr, &las_counter, &las_txnid, las_key));

		/*
		 * Confirm the search using the unique prefix; if not a match,
		 * we're done searching for records for this page.
		 */
		if (las_id != read_id ||
		    las_addr->size != addr_size ||
		    memcmp(las_addr->data, addr, addr_size) != 0)
			break;

		/*
		 * If the on-page value has become globally visible, this record
		 * is no longer needed.
		 */
		if (__wt_txn_visible_all(session, las_txnid))
			continue;

		/* Allocate the WT_UPDATE structure. */
		WT_ERR(cursor->get_value(
		    cursor, &upd_txnid, &upd_size, las_value));
		WT_ERR(__wt_update_alloc(session,
		    (upd_size == WT_UPDATE_DELETED_VALUE) ? NULL : las_value,
		    &upd, &incr));
		total_incr += incr;
		upd->txnid = upd_txnid;

		switch (page->type) {
		case WT_PAGE_COL_FIX:
		case WT_PAGE_COL_VAR:
			p = las_key->data;
			WT_ERR(__wt_vunpack_uint(&p, 0, &recno));
			if (current_recno == recno)
				break;
			WT_ASSERT(session, current_recno < recno);

			if (first_upd != NULL) {
				WT_ERR(__col_instantiate(session,
				    current_recno, ref, &cbt, first_upd));
				first_upd = NULL;
			}
			current_recno = recno;
			break;
		case WT_PAGE_ROW_LEAF:
			if (current_key->size == las_key->size &&
			    memcmp(current_key->data,
			    las_key->data, las_key->size) == 0)
				break;

			if (first_upd != NULL) {
				WT_ERR(__row_instantiate(session,
				    current_key, ref, &cbt, first_upd));
				first_upd = NULL;
			}
			WT_ERR(__wt_buf_set(session,
			    current_key, las_key->data, las_key->size));
			break;
		WT_ILLEGAL_VALUE_ERR(session);
		}

		/* Append the latest update to the list. */
		if (first_upd == NULL)
			first_upd = last_upd = upd;
		else {
			last_upd->next = upd;
			last_upd = upd;
		}
		upd = NULL;
	}
	WT_ERR_NOTFOUND_OK(ret);

	/* Insert the last set of updates, if any. */
	if (first_upd != NULL)
		switch (page->type) {
		case WT_PAGE_COL_FIX:
		case WT_PAGE_COL_VAR:
			WT_ERR(__col_instantiate(session,
			    current_recno, ref, &cbt, first_upd));
			first_upd = NULL;
			break;
		case WT_PAGE_ROW_LEAF:
			WT_ERR(__row_instantiate(session,
			    current_key, ref, &cbt, first_upd));
			first_upd = NULL;
			break;
		WT_ILLEGAL_VALUE_ERR(session);
		}

	/* Discard the cursor. */
	WT_ERR(__wt_las_cursor_close(session, &cursor, session_flags));

	if (total_incr != 0) {
		__wt_cache_page_inmem_incr(session, page, total_incr);

		/*
		 * We've modified/dirtied the page, but that's not necessary and
		 * if we keep the page clean, it's easier to evict. We leave the
		 * lookaside table updates in place, so if we evict this page
		 * without dirtying it, any future instantiation of it will find
		 * the records it needs. If the page is dirtied before eviction,
		 * then we'll write any needed lookaside table records for the
		 * new location of the page.
		 */
		__wt_page_modify_clear(session, page);
	}

err:	WT_TRET(__wt_las_cursor_close(session, &cursor, session_flags));
	WT_TRET(__wt_btcur_close(&cbt, 1));

	/*
	 * On error, upd points to a single unlinked WT_UPDATE structure,
	 * first_upd points to a list.
	 */
	if (upd != NULL)
		__wt_free(session, upd);
	if (first_upd != NULL)
		__wt_free_update_list(session, first_upd);

	__wt_scr_free(session, &current_key);
	__wt_scr_free(session, &las_addr);
	__wt_scr_free(session, &las_key);
	__wt_scr_free(session, &las_value);

	return (ret);
}
Example #24
0
int main(void)
{
	int ret;
	WT_CONNECTION *conn;
	WT_SESSION *session;
	WT_CURSOR *cursor;
	POP_RECORD *p, *endp;
	const char *country;
	uint64_t recno;
	uint16_t year;

	ret = wiredtiger_open(home, NULL, "create", &conn);
	if (ret != 0)
		fprintf(stderr, "Error connecting to %s: %s\n",
		    home, wiredtiger_strerror(ret));
	/* Note: error checking omitted for clarity. */

	/*! [schema work] */
	ret = conn->open_session(conn, NULL, NULL, &session);

	/*
	 * Create the population table.
	 * Keys are record numbers, the format for values is
	 * (5-byte string, short, long).
	 * See ::wiredtiger_struct_pack for details of the format strings.
	 *
	 * If this program is run multiple times so the table already exists,
	 * this call will verify that the table exists.  It is not required in
	 * that case, but is a safety check that the schema matches what the
	 * program expects.
	 */
	ret = session->create(session, "table:population",
	    "key_format=r,"
	    "value_format=5sHQ,"
	    "columns=(id,country,year,population),"
	    "colgroups=(main,population)");

	/* Create the column groups to store population in its own file. */
	ret = session->create(session, "colgroup:population:main",
	    "columns=(country,year)");

	ret = session->create(session, "colgroup:population:population",
	    "columns=(population)");

	/* Create an index with composite key (country,year). */
	ret = session->create(session, "index:population:country_year",
	    "columns=(country,year)");

	ret = session->open_cursor(session, "table:population",
	    NULL, "append", &cursor);

	endp = pop_data + (sizeof (pop_data) / sizeof(pop_data[0]));
	for (p = pop_data; p < endp; p++) {
		cursor->set_value(cursor, p->country, p->year, p->population);
		ret = cursor->insert(cursor);
	}
	ret = cursor->close(cursor);

	/* Now just read through the countries we know about */
	ret = session->open_cursor(session,
	    "index:population:country_year(id)",
	    NULL, NULL, &cursor);

	while ((ret = cursor->next(cursor)) == 0) {
		cursor->get_key(cursor, &country, &year);
		cursor->get_value(cursor, &recno);

		printf("Got country %s : row ID %d\n", country, (int)recno);
	}

	ret = conn->close(conn, NULL);
	/*! [schema work] */

	return (ret);
}
Example #25
0
/*
 * list_print --
 *	List the high-level objects in the database.
 */
static int
list_print(WT_SESSION *session, const char *name, int cflag, int vflag)
{
    WT_CURSOR *cursor;
    WT_DECL_RET;
    int found;
    const char *key, *value;

    /* Open the metadata file. */
    if ((ret = session->open_cursor(
                   session, WT_METADATA_URI, NULL, NULL, &cursor)) != 0) {
        /*
         * If there is no metadata (yet), this will return ENOENT.
         * Treat that the same as an empty metadata.
         */
        if (ret == ENOENT)
            return (0);

        fprintf(stderr, "%s: %s: session.open_cursor: %s\n",
                progname, WT_METADATA_URI, session->strerror(session, ret));
        return (1);
    }

    found = name == NULL;
    while ((ret = cursor->next(cursor)) == 0) {
        /* Get the key. */
        if ((ret = cursor->get_key(cursor, &key)) != 0)
            return (util_cerr(cursor, "get_key", ret));

        /*
         * If a name is specified, only show objects that match.
         */
        if (name != NULL) {
            if (!WT_PREFIX_MATCH(key, name))
                continue;
            found = 1;
        }

        /*
         * !!!
         * We don't normally say anything about the WiredTiger metadata
         * and lookaside tables, they're not application/user "objects"
         * in the database.  I'm making an exception for the checkpoint
         * and verbose options.
         */
        if (cflag || vflag ||
                (strcmp(key, WT_METADATA_URI) != 0 &&
                 strcmp(key, WT_LAS_URI) != 0))
            printf("%s\n", key);

        if (!cflag && !vflag)
            continue;

        if (cflag && (ret = list_print_checkpoint(session, key)) != 0)
            return (ret);
        if (vflag) {
            if ((ret = cursor->get_value(cursor, &value)) != 0)
                return (util_cerr(cursor, "get_value", ret));
            printf("%s\n", value);
        }
    }
    if (ret != WT_NOTFOUND)
        return (util_cerr(cursor, "next", ret));
    if (!found) {
        fprintf(stderr, "%s: %s: not found\n", progname, name);
        return (1);
    }

    return (0);
}
Example #26
0
void
worker(CONFIG *cfg, uint32_t worker_type)
{
	WT_CONNECTION *conn;
	WT_SESSION *session;
	WT_CURSOR *cursor;
	const char *op_name = "search";
	char *data_buf, *key_buf, *value;
	int ret, op_ret;
	uint64_t next_incr, next_val;

	session = NULL;
	data_buf = key_buf = NULL;
	op_ret = 0;

	conn = cfg->conn;
	key_buf = calloc(cfg->key_sz + 1, 1);
	if (key_buf == NULL) {
		lprintf(cfg, ret = ENOMEM, 0, "Populate key buffer");
		goto err;
	}
	if (worker_type == WORKER_INSERT || worker_type == WORKER_UPDATE) {
		data_buf = calloc(cfg->data_sz, 1);
		if (data_buf == NULL) {
			lprintf(cfg, ret = ENOMEM, 0, "Populate data buffer");
			goto err;
		}
		memset(data_buf, 'a', cfg->data_sz - 1);
	}

	if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
		lprintf(cfg, ret, 0,
		    "open_session failed in read thread");
		goto err;
	}
	if ((ret = session->open_cursor(session, cfg->uri,
	    NULL, NULL, &cursor)) != 0) {
		lprintf(cfg, ret, 0,
		    "open_cursor failed in read thread");
		goto err;
	}

	while (g_running) {
		/* Get a value in range, avoid zero. */
		if (worker_type == WORKER_INSERT)
			next_incr = ATOMIC_ADD(g_nins_ops, 1);

		if (!F_ISSET(cfg, PERF_RAND_WORKLOAD) &&
		    worker_type == WORKER_INSERT)
			next_val = cfg->icount + next_incr;
		else
			next_val = wtperf_rand(cfg);
		/*
		 * If the workload is started without a populate phase we
		 * rely on at least one insert to get a valid item id.
		 */
		if (worker_type != WORKER_INSERT &&
		    wtperf_value_range(cfg) < next_val)
			continue;
		sprintf(key_buf, "%0*" PRIu64, cfg->key_sz, next_val);
		cursor->set_key(cursor, key_buf);
		switch(worker_type) {
		case WORKER_READ:
			op_name = "read";
			op_ret = cursor->search(cursor);
			if (F_ISSET(cfg, PERF_RAND_WORKLOAD) &&
			    op_ret == WT_NOTFOUND)
				op_ret = 0;
			if (op_ret == 0)
				++g_nread_ops;
			break;
		case WORKER_INSERT_RMW:
			op_name="insert_rmw";
			op_ret = cursor->search(cursor);
			if (op_ret != WT_NOTFOUND)
				break;
			/* Fall through */
		case WORKER_INSERT:
			op_name = "insert";
			cursor->set_value(cursor, data_buf);
			op_ret = cursor->insert(cursor);
			if (F_ISSET(cfg, PERF_RAND_WORKLOAD) &&
			    op_ret == WT_DUPLICATE_KEY)
				op_ret = 0;
			if (op_ret != 0)
				++g_nfailedins_ops;
			break;
		case WORKER_UPDATE:
			op_name = "update";
			op_ret = cursor->search(cursor);
			if (op_ret == 0) {
				cursor->get_value(cursor, &value);
				memcpy(data_buf, value, cfg->data_sz);
				if (data_buf[0] == 'a')
					data_buf[0] = 'b';
				else
					data_buf[0] = 'a';
				cursor->set_value(cursor, data_buf);
				op_ret = cursor->update(cursor);
			}
			if (F_ISSET(cfg, PERF_RAND_WORKLOAD) &&
			    op_ret == WT_NOTFOUND)
				op_ret = 0;
			if (op_ret == 0)
				++g_nupdate_ops;
			break;
		default:
			lprintf(cfg, EINVAL, 0, "Invalid worker type");
			goto err;
		}

		/* Report errors and continue. */
		if (op_ret != 0)
			lprintf(cfg, op_ret, 0,
			    "%s failed for: %s", op_name, key_buf);
		else
			++g_nworker_ops;
	}

err:	if (ret != 0)
		++g_threads_quit;
	if (session != NULL)
		session->close(session, NULL);
	if (data_buf != NULL)
		free(data_buf);
	if (key_buf != NULL)
		free(key_buf);
}
Example #27
0
int
cursor_ops(WT_SESSION *session)
{
	WT_CURSOR *cursor;
	int ret;

	/*! [Open a cursor] */
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	/*! [Open a cursor] */

	/*! [Open a cursor on the metadata] */
	ret = session->open_cursor(
	    session, "metadata:", NULL, NULL, &cursor);
	/*! [Open a cursor on the metadata] */

	{
	WT_CURSOR *duplicate;
	const char *key = "some key";
	/*! [Duplicate a cursor] */
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	cursor->set_key(cursor, key);
	ret = cursor->search(cursor);

	/* Duplicate the cursor. */
	ret = session->open_cursor(session, NULL, cursor, NULL, &duplicate);
	/*! [Duplicate a cursor] */
	}

	{
	WT_CURSOR *overwrite_cursor;
	const char *key = "some key", *value = "some value";
	/*! [Reconfigure a cursor] */
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	cursor->set_key(cursor, key);

	/* Reconfigure the cursor to overwrite the record. */
	ret = session->open_cursor(
	    session, NULL, cursor, "overwrite", &overwrite_cursor);
	ret = cursor->close(cursor);

	overwrite_cursor->set_value(overwrite_cursor, value);
	ret = overwrite_cursor->insert(cursor);
	/*! [Reconfigure a cursor] */
	}

	{
	/*! [boolean configuration string example] */
	ret = session->open_cursor(session, "table:mytable", NULL,
	    "overwrite", &cursor);
	ret = session->open_cursor(session, "table:mytable", NULL,
	    "overwrite=true", &cursor);
	ret = session->open_cursor(session, "table:mytable", NULL,
	    "overwrite=1", &cursor);
	/*! [boolean configuration string example] */
	}

	{
	/*! [open a named checkpoint] */
	ret = session->open_cursor(session,
	    "table:mytable", NULL, "checkpoint=midnight", &cursor);
	/*! [open a named checkpoint] */
	}

	{
	/*! [open the default checkpoint] */
	ret = session->open_cursor(session,
	    "table:mytable", NULL, "checkpoint=WiredTigerCheckpoint", &cursor);
	/*! [open the default checkpoint] */
	}

	{
	/*! [Get the cursor's string key] */
	const char *key;	/* Get the cursor's string key. */
	ret = cursor->get_key(cursor, &key);
	/*! [Get the cursor's string key] */
	}

	{
	/*! [Set the cursor's string key] */
				/* Set the cursor's string key. */
	const char *key = "another key";
	cursor->set_key(cursor, key);
	/*! [Set the cursor's string key] */
	}

	{
	/*! [Get the cursor's record number key] */
	uint64_t recno;		/* Get the cursor's record number key. */
	ret = cursor->get_key(cursor, &recno);
	/*! [Get the cursor's record number key] */
	}

	{
	/*! [Set the cursor's record number key] */
	uint64_t recno = 37;	/* Set the cursor's record number key. */
	cursor->set_key(cursor, recno);
	/*! [Set the cursor's record number key] */
	}

	{
	/*! [Get the cursor's composite key] */
			/* Get the cursor's "SiH" format composite key. */
	const char *first;
	int32_t second;
	uint16_t third;
	cursor->get_key(cursor, &first, &second, &third);
	/*! [Get the cursor's composite key] */
	}

	{
	/*! [Set the cursor's composite key] */
			/* Set the cursor's "SiH" format composite key. */
	cursor->set_key(cursor, "first", (int32_t)5, (uint16_t)7);
	/*! [Set the cursor's composite key] */
	}

	{
	/*! [Get the cursor's string value] */
	const char *value;	/* Get the cursor's string value. */
	ret = cursor->get_value(cursor, &value);
	/*! [Get the cursor's string value] */
	}

	{
	/*! [Set the cursor's string value] */
				/* Set the cursor's string value. */
	const char *value = "another value";
	cursor->set_value(cursor, value);
	/*! [Set the cursor's string value] */
	}

	{
	/*! [Get the cursor's raw value] */
	WT_ITEM value;		/* Get the cursor's raw value. */
	ret = cursor->get_value(cursor, &value);
	/*! [Get the cursor's raw value] */
	}

	{
	/*! [Set the cursor's raw value] */
	WT_ITEM value;		/* Set the cursor's raw value. */
	value.data = "another value";
	value.size = strlen("another value");
	cursor->set_value(cursor, &value);
	/*! [Set the cursor's raw value] */
	}

	/*! [Return the next record] */
	ret = cursor->next(cursor);
	/*! [Return the next record] */

	/*! [Return the previous record] */
	ret = cursor->prev(cursor);
	/*! [Return the previous record] */

	/*! [Reset the cursor] */
	ret = cursor->reset(cursor);
	/*! [Reset the cursor] */

	{
	WT_CURSOR *other = NULL;
	/*! [Cursor comparison] */
	int compare;
	ret = cursor->compare(cursor, other, &compare);
	if (compare == 0) {
		/* Cursors reference the same key */
	} else if (compare < 0) {
		/* Cursor key less than other key */
	} else if (compare > 0) {
		/* Cursor key greater than other key */
	}
	/*! [Cursor comparison] */
	}

	{
	/*! [Search for an exact match] */
	const char *key = "some key";
	cursor->set_key(cursor, key);
	ret = cursor->search(cursor);
	/*! [Search for an exact match] */
	}

	cursor_search_near(cursor);

	{
	/*! [Insert a new record or overwrite an existing record] */
	/* Insert a new record or overwrite an existing record. */
	const char *key = "some key", *value = "some value";
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	cursor->set_key(cursor, key);
	cursor->set_value(cursor, value);
	ret = cursor->insert(cursor);
	/*! [Insert a new record or overwrite an existing record] */
	}

	{
	/*! [Insert a new record and fail if the record exists] */
	/* Insert a new record and fail if the record exists. */
	const char *key = "some key", *value = "some value";
	ret = session->open_cursor(
	    session, "table:mytable", NULL, "overwrite=false", &cursor);
	cursor->set_key(cursor, key);
	cursor->set_value(cursor, value);
	ret = cursor->insert(cursor);
	/*! [Insert a new record and fail if the record exists] */
	}

	{
	/*! [Insert a new record and assign a record number] */
	/* Insert a new record and assign a record number. */
	uint64_t recno;
	const char *value = "some value";
	ret = session->open_cursor(
	    session, "table:mytable", NULL, "append", &cursor);
	cursor->set_value(cursor, value);
	ret = cursor->insert(cursor);
	if (ret == 0)
		ret = cursor->get_key(cursor, &recno);
	/*! [Insert a new record and assign a record number] */
	}

	{
	/*! [Update an existing record or insert a new record] */
	const char *key = "some key", *value = "some value";
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	cursor->set_key(cursor, key);
	cursor->set_value(cursor, value);
	ret = cursor->update(cursor);
	/*! [Update an existing record or insert a new record] */
	}

	{
	/*! [Update an existing record and fail if DNE] */
	const char *key = "some key", *value = "some value";
	ret = session->open_cursor(
	    session, "table:mytable", NULL, "overwrite=false", &cursor);
	cursor->set_key(cursor, key);
	cursor->set_value(cursor, value);
	ret = cursor->update(cursor);
	/*! [Update an existing record and fail if DNE] */
	}

	{
	/*! [Remove a record] */
	const char *key = "some key";
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	cursor->set_key(cursor, key);
	ret = cursor->remove(cursor);
	/*! [Remove a record] */
	}

	{
	/*! [Remove a record and fail if DNE] */
	const char *key = "some key";
	ret = session->open_cursor(
	    session, "table:mytable", NULL, "overwrite=false", &cursor);
	cursor->set_key(cursor, key);
	ret = cursor->remove(cursor);
	/*! [Remove a record and fail if DNE] */
	}

	{
	/*! [Display an error] */
	const char *key = "non-existent key";
	cursor->set_key(cursor, key);
	if ((ret = cursor->remove(cursor)) != 0) {
		fprintf(stderr,
		    "cursor.remove: %s\n", wiredtiger_strerror(ret));
		return (ret);
	}
	/*! [Display an error] */
	}

	/*! [Close the cursor] */
	ret = cursor->close(cursor);
	/*! [Close the cursor] */

	return (ret);
}
Example #28
0
void *
stat_worker(void *arg)
{
	CONFIG *cfg;
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_SESSION *session;
	const char *desc, *pvalue;
	char *stat_uri;
	double secs;
	int ret;
	size_t uri_len;
	struct timeval e;
	uint32_t i;
	uint64_t value;

	session = NULL;
	cfg = (CONFIG *)arg;
	conn = cfg->conn;
	stat_uri = NULL;

	if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
		lprintf(cfg, ret, 0,
		    "open_session failed in statistics thread.");
		goto err;
	}

	uri_len = strlen("statistics:") + strlen(cfg->uri) + 1;
	if ((stat_uri = malloc(uri_len)) == NULL) {
		lprintf(cfg, ENOMEM, 0, "Statistics thread uri create.");
		goto err;
	}
	(void)snprintf(stat_uri, uri_len, "statistics:%s", cfg->uri);

	while (g_util_running) {
		/* Break the sleep up, so we notice interrupts faster. */
		for (i = 0; i < cfg->stat_interval; i++) {
			sleep(cfg->report_interval);
			if (!g_util_running)
				break;
		}
		/* Generic header. */
		lprintf(cfg, 0, cfg->verbose,
		    "=======================================");
		gettimeofday(&e, NULL);
		secs = e.tv_sec + e.tv_usec / 1000000.0;
		secs -= (cfg->phase_start_time.tv_sec +
		    cfg->phase_start_time.tv_usec / 1000000.0);
		if (secs == 0)
			++secs;
		if (cfg->phase == WT_PERF_POP)
			lprintf(cfg, 0, cfg->verbose,
			    "inserts: %" PRIu64 ", elapsed time: %.2f",
			    g_npop_ops, secs);
		else
			lprintf(cfg, 0, cfg->verbose,
			    "reads: %" PRIu64 " inserts: %" PRIu64
			    " updates: %" PRIu64 ", elapsed time: %.2f",
			    g_nread_ops, g_nins_ops, g_nupdate_ops, secs);

		/* Report data source stats. */
		if ((ret = session->open_cursor(session, stat_uri,
		    NULL, "statistics_fast", &cursor)) != 0) {
			lprintf(cfg, ret, 0,
			    "open_cursor failed for data source statistics");
			goto err;
		}
		while ((ret = cursor->next(cursor)) == 0 && (ret =
		    cursor->get_value(cursor, &desc, &pvalue, &value)) == 0 &&
		    value != 0)
			lprintf(cfg, 0, cfg->verbose,
			    "stat:lsm: %s=%s", desc, pvalue);
		cursor->close(cursor);
		lprintf(cfg, 0, cfg->verbose, "-----------------");

		/* Dump the connection statistics since last time. */
		if ((ret = session->open_cursor(session, "statistics:",
		    NULL, "statistics_clear", &cursor)) != 0) {
			lprintf(cfg, ret, 0,
			    "open_cursor failed in statistics");
			goto err;
		}
		while ((ret = cursor->next(cursor)) == 0 && (ret =
		    cursor->get_value(cursor, &desc, &pvalue, &value)) == 0 &&
		    value != 0)
			lprintf(cfg, 0, cfg->verbose,
			    "stat:conn: %s=%s", desc, pvalue);
		cursor->close(cursor);
	}
err:	if (session != NULL)
		session->close(session, NULL);
	if (stat_uri != NULL)
		free(stat_uri);
	return (arg);
}
Example #29
0
/*
 * __schema_open_table --
 *	Open a named table (internal version).
 */
static int
__schema_open_table(WT_SESSION_IMPL *session,
    const char *name, size_t namelen, bool ok_incomplete, WT_TABLE **tablep)
{
	WT_CONFIG cparser;
	WT_CONFIG_ITEM ckey, cval;
	WT_CURSOR *cursor;
	WT_DECL_ITEM(buf);
	WT_DECL_RET;
	WT_TABLE *table;
	const char *tconfig;
	char *tablename;

	cursor = NULL;
	table = NULL;
	tablename = NULL;

	WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_TABLE));

	WT_ERR(__wt_scr_alloc(session, 0, &buf));
	WT_ERR(__wt_buf_fmt(session, buf, "table:%.*s", (int)namelen, name));
	WT_ERR(__wt_strndup(session, buf->data, buf->size, &tablename));

	WT_ERR(__wt_metadata_cursor(session, &cursor));
	cursor->set_key(cursor, tablename);
	WT_ERR(cursor->search(cursor));
	WT_ERR(cursor->get_value(cursor, &tconfig));

	WT_ERR(__wt_calloc_one(session, &table));
	table->name = tablename;
	tablename = NULL;
	table->name_hash = __wt_hash_city64(name, namelen);

	WT_ERR(__wt_config_getones(session, tconfig, "columns", &cval));

	WT_ERR(__wt_config_getones(session, tconfig, "key_format", &cval));
	WT_ERR(__wt_strndup(session, cval.str, cval.len, &table->key_format));
	WT_ERR(__wt_config_getones(session, tconfig, "value_format", &cval));
	WT_ERR(__wt_strndup(session, cval.str, cval.len, &table->value_format));
	WT_ERR(__wt_strdup(session, tconfig, &table->config));

	/* Point to some items in the copy to save re-parsing. */
	WT_ERR(__wt_config_getones(session, table->config,
	    "columns", &table->colconf));

	/*
	 * Count the number of columns: tables are "simple" if the columns
	 * are not named.
	 */
	WT_ERR(__wt_config_subinit(session, &cparser, &table->colconf));
	table->is_simple = true;
	while ((ret = __wt_config_next(&cparser, &ckey, &cval)) == 0)
		table->is_simple = false;
	if (ret != WT_NOTFOUND)
		goto err;

	/* Check that the columns match the key and value formats. */
	if (!table->is_simple)
		WT_ERR(__wt_schema_colcheck(session,
		    table->key_format, table->value_format, &table->colconf,
		    &table->nkey_columns, NULL));

	WT_ERR(__wt_config_getones(session, table->config,
	    "colgroups", &table->cgconf));

	/* Count the number of column groups. */
	WT_ERR(__wt_config_subinit(session, &cparser, &table->cgconf));
	table->ncolgroups = 0;
	while ((ret = __wt_config_next(&cparser, &ckey, &cval)) == 0)
		++table->ncolgroups;
	if (ret != WT_NOTFOUND)
		goto err;

	if (table->ncolgroups > 0 && table->is_simple)
		WT_ERR_MSG(session, EINVAL,
		    "%s requires a table with named columns", tablename);

	WT_ERR(__wt_calloc_def(session, WT_COLGROUPS(table), &table->cgroups));
	WT_ERR(__wt_schema_open_colgroups(session, table));

	if (!ok_incomplete && !table->cg_complete)
		WT_ERR_MSG(session, EINVAL, "'%s' cannot be used "
		    "until all column groups are created",
		    table->name);

	/* Copy the schema generation into the new table. */
	table->schema_gen = S2C(session)->schema_gen;

	*tablep = table;

	if (0) {
err:		WT_TRET(__wt_schema_destroy_table(session, &table));
	}
	WT_TRET(__wt_metadata_cursor_release(session, &cursor));

	__wt_free(session, tablename);
	__wt_scr_free(session, &buf);
	return (ret);
}
Example #30
0
int
cursor_ops(WT_SESSION *session)
{
	WT_CURSOR *cursor;
	int ret;

	/*! [Open a cursor] */
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	/*! [Open a cursor] */

	{
	WT_CURSOR *duplicate;
	const char *key = "some key";
	/*! [Duplicate a cursor] */
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	cursor->set_key(cursor, key);
	ret = cursor->search(cursor);

	/* Duplicate the cursor. */
	ret = session->open_cursor(session, NULL, cursor, NULL, &duplicate);
	/*! [Duplicate a cursor] */
	}

	{
	WT_CURSOR *overwrite_cursor;
	const char *key = "some key", *value = "some value";
	/*! [Reconfigure a cursor] */
	ret = session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor);
	cursor->set_key(cursor, key);

	/* Reconfigure the cursor to overwrite the record. */
	ret = session->open_cursor(
	    session, NULL, cursor, "overwrite=true", &overwrite_cursor);
	ret = cursor->close(cursor);

	overwrite_cursor->set_value(overwrite_cursor, value);
	ret = overwrite_cursor->insert(cursor);
	/*! [Reconfigure a cursor] */
	}

	{
	/*! [Get the cursor's string key] */
	const char *key;	/* Get the cursor's string key. */
	ret = cursor->get_key(cursor, &key);
	/*! [Get the cursor's string key] */
	}

	{
	/*! [Get the cursor's record number key] */
	uint64_t recno;		/* Get the cursor's record number key. */
	ret = cursor->get_key(cursor, &recno);
	/*! [Get the cursor's record number key] */
	}

	{
	/*! [Get the cursor's string value] */
	const char *value;	/* Get the cursor's string value. */
	ret = cursor->get_value(cursor, &value);
	/*! [Get the cursor's string value] */
	}

	{
	/*! [Get the cursor's raw value] */
	WT_ITEM value;		/* Get the cursor's raw value. */
	ret = cursor->get_value(cursor, &value);
	/*! [Get the cursor's raw value] */
	}

	{
	/*! [Set the cursor's string key] */
				/* Set the cursor's string key. */
	const char *key = "another key";
	cursor->set_key(cursor, key);
	/*! [Set the cursor's string key] */
	}

	{
	/*! [Set the cursor's record number key] */
	uint64_t recno = 37;	/* Set the cursor's record number key. */
	cursor->set_key(cursor, recno);
	/*! [Set the cursor's record number key] */
	}

	{
	/*! [Set the cursor's string value] */
				/* Set the cursor's string value. */
	const char *value = "another value";
	cursor->set_value(cursor, value);
	/*! [Set the cursor's string value] */
	}
	{
	/*! [Set the cursor's raw value] */
	WT_ITEM value;		/* Set the cursor's raw value. */
	value.data = "another value";
	value.size = strlen("another value");
	cursor->set_value(cursor, &value);
	/*! [Set the cursor's raw value] */
	}

	/*! [Return the next record] */
	ret = cursor->next(cursor);
	/*! [Return the next record] */

	/*! [Return the previous record] */
	ret = cursor->prev(cursor);
	/*! [Return the previous record] */

	/*! [Reset the cursor] */
	ret = cursor->reset(cursor);
	/*! [Reset the cursor] */

	{
	WT_CURSOR *other = NULL;
	/*! [Cursor comparison] */
	int compare;
	ret = cursor->compare(cursor, other, &compare);
	if (compare == 0) {
		/* Cursors reference the same key */
	} else if (compare < 0) {
		/* Cursor key less than other key */
	} else if (compare > 0) {
		/* Cursor key greater than other key */
	}
	/*! [Cursor comparison] */
	}

	{
	/*! [Search for an exact match] */
	const char *key = "some key";
	cursor->set_key(cursor, key);
	ret = cursor->search(cursor);
	/*! [Search for an exact match] */
	}

	cursor_search_near(cursor);

	{
	/*! [Insert a new record] */
	/* Insert a new record. */
	const char *key = "some key", *value = "some value";
	cursor->set_key(cursor, key);
	cursor->set_value(cursor, value);
	ret = cursor->insert(cursor);
	/*! [Insert a new record] */
	}

	{
	const char *key = "some key", *value = "some value";
	/*! [Insert a new record or overwrite an existing record] */
	/* Insert a new record or overwrite an existing record. */
	ret = session->open_cursor(
	    session, "table:mytable", NULL, "overwrite", &cursor);
	cursor->set_key(cursor, key);
	cursor->set_value(cursor, value);
	ret = cursor->insert(cursor);
	/*! [Insert a new record or overwrite an existing record] */
	}

	{
	/*! [Insert a new record and assign a record number] */
	/* Insert a new record and assign a record number. */
	uint64_t recno;
	const char *value = "some value";
	ret = session->open_cursor(
	    session, "table:mytable", NULL, "append", &cursor);
	cursor->set_value(cursor, value);
	ret = cursor->insert(cursor);
	if (ret == 0)
		recno = cursor->get_key(cursor, &recno);
	/*! [Insert a new record and assign a record number] */
	}

	{
	/*! [Update an existing record] */
	const char *key = "some key", *value = "some value";
	cursor->set_key(cursor, key);
	cursor->set_value(cursor, value);
	ret = cursor->update(cursor);
	/*! [Update an existing record] */
	}

	{
	/*! [Remove a record] */
	const char *key = "some key";
	cursor->set_key(cursor, key);
	ret = cursor->remove(cursor);
	/*! [Remove a record] */
	}

	{
	/*! [Display an error] */
	const char *key = "some key";
	cursor->set_key(cursor, key);
	if ((ret = cursor->remove(cursor)) != 0) {
		fprintf(stderr,
		    "cursor.remove: %s\n", wiredtiger_strerror(ret));
		return (ret);
	}
	/*! [Display an error] */
	}

	/*! [Close the cursor] */
	ret = cursor->close(cursor);
	/*! [Close the cursor] */

	return (ret);
}