Beispiel #1
0
//
// Initialize the database to the specified number of accounts, branches,
// history records, and tellers.
//
int
TpcbExample::populate()
{
	DB *dbp;

	int err;
	u_int32_t balance, idnum;
	u_int32_t end_anum, end_bnum, end_tnum;
	u_int32_t start_anum, start_bnum, start_tnum;

	idnum = BEGID;
	balance = 500000;

	if ((err = db_create(&dbp, dbenv, 0)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "db_create of accounts db failed.");
		return (1);
	}
	dbp->set_h_nelem(dbp, (unsigned int)accounts);

	if ((err = dbp->open(dbp, NULL, "account", NULL, DB_HASH,
			     DB_CREATE, 0644)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "Account file create failed. error: %s.", db_strerror(err));
		return (1);
	}

	start_anum = idnum;
	if ((err =
	    populateTable(dbp, idnum, balance, accounts, "account")) != 0)
		return (1);
	idnum += accounts;
	end_anum = idnum - 1;
	if ((err = dbp->close(dbp, 0)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "Account file close failed. error: %s.", db_strerror(err));
		return (1);
	}

	if ((err = db_create(&dbp, dbenv, 0)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "db_create of branches db failed.");
		return (1);
	}
	//
	// Since the number of branches is very small, we want to use very
	// small pages and only 1 key per page.  This is the poor-man's way
	// of getting key locking instead of page locking.
	//
	dbp->set_h_ffactor(dbp, 1);
	dbp->set_h_nelem(dbp, (unsigned int)branches);
	dbp->set_pagesize(dbp, 512);

	if ((err = dbp->open(dbp, NULL, "branch", NULL, DB_HASH,
			     DB_CREATE, 0644)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "Branch file create failed. error: %s.", db_strerror(err));
		return (1);
	}
	start_bnum = idnum;
	if ((err = populateTable(dbp, idnum, balance, branches, "branch")) != 0)
		return (1);
	idnum += branches;
	end_bnum = idnum - 1;
	if ((err = dbp->close(dbp, 0)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "Close of branch file failed. error: %s.",
		    db_strerror(err));
		return (1);
	}

	if ((err = db_create(&dbp, dbenv, 0)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "db_create of teller db failed.");
		return (1);
	}
	//
	// In the case of tellers, we also want small pages, but we'll let
	// the fill factor dynamically adjust itself.
	//
	dbp->set_h_ffactor(dbp, 0);
	dbp->set_h_nelem(dbp, (unsigned int)tellers);
	dbp->set_pagesize(dbp, 512);

	if ((err = dbp->open(dbp, NULL, "teller", NULL, DB_HASH,
			     DB_CREATE, 0644)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "Teller file create failed. error: %s.", db_strerror(err));
		return (1);
	}

	start_tnum = idnum;
	if ((err = populateTable(dbp, idnum, balance, tellers, "teller")) != 0)
		return (1);
	idnum += tellers;
	end_tnum = idnum - 1;
	if ((err = dbp->close(dbp, 0)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "Close of teller file failed. error: %s.",
		    db_strerror(err));
		return (1);
	}

	if ((err = db_create(&dbp, dbenv, 0)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "db_create of history db failed.");
		return (1);
	}
	dbp->set_re_len(dbp, HISTORY_LEN);
	if ((err = dbp->open(dbp, NULL, "history", NULL, DB_RECNO,
			     DB_CREATE, 0644)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "Create of history file failed. error: %s.",
		    db_strerror(err));
		return (1);
	}

	populateHistory(dbp, history, accounts, branches, tellers);
	if ((err = dbp->close(dbp, 0)) != 0) {
		_snprintf(msgString, ERR_STRING_MAX,
		    "Close of history file failed. error: %s.",
		    db_strerror(err));
		return (1);
	}

	_snprintf(msgString, ERR_STRING_MAX, "Populated OK.");
	return (0);
}
Beispiel #2
0
/*!
 * \brief JsonDbObject::updateVersionReplicating implements a replicatedWrite
 * \param other the (remote) object to include into this one.
 * \return if the passed object was a valid replication
 */
bool JsonDbObject::updateVersionReplicating(const JsonDbObject &other)
{
    // these two will be the final _meta content
    QJsonArray history;
    QJsonArray conflicts;

    // let's go thru all version, i.e. this, this._conflicts, other, and other._conflicts
    {
        // thanks to the operator <, documents will sort and remove duplicates
        // the value is just for show, QSet is based on QHash, which does not sort
        QMap<JsonDbObject,bool> documents;

        QUuid id;
        if (!isEmpty()) {
            id = uuid();
            populateMerge(&documents, id, *this);
        } else {
            id = other.uuid();
        }
        if (!populateMerge(&documents, id, other, true))
            return false;

        // now we have all versions sorted and duplicates removed
        // let's figure out what to keep, what to toss
        // this is O(n^2) but should be fine in real world situations
        for (QMap<JsonDbObject,bool>::const_iterator ii = documents.begin(); ii != documents.end(); ii++) {
            bool alive = !ii.key().isDeleted();
            for (QMap<JsonDbObject,bool>::const_iterator jj = ii + 1; alive && jj != documents.end(); jj++)
                if (ii.key().isAncestorOf(jj.key()))
                    alive = false;

            if (ii+1 == documents.end()) {
                // last element, so found the winner,
                // assigning to *this, which is head
                *this = ii.key();
                populateHistory(&history, *this, false);
            } else if (alive) {
                // this is a conflict, strip _meta and keep it
                JsonDbObject conflict(ii.key());
                conflict.remove(JsonDbString::kMetaStr);
                conflicts.append(conflict);
            } else {
                // this version was replaced, just keep history
                populateHistory(&history, ii.key(), true);
            }
        }
    }

    // let's write a new _meta into head
    if (history.size() || conflicts.size()) {
        QJsonObject meta;
        if (history.size())
            meta.insert(QStringLiteral("history"), history);
        if (conflicts.size())
            meta.insert(JsonDbString::kConflictsStr, conflicts);
        insert(JsonDbString::kMetaStr, meta);
    } else {
        // this is really just for sanity reason, but it feels better to have it
        // aka: this branch should never be reached in real world situations
        remove(JsonDbString::kMetaStr);
    }

    return true;
}
//
// Initialize the database to the specified number of accounts, branches,
// history records, and tellers.
//
void
TpcbExample::populate(int accounts, int branches, int history, int tellers)
{
	Db *dbp;

	int err;
	u_int32_t balance, idnum;
	u_int32_t end_anum, end_bnum, end_tnum;
	u_int32_t start_anum, start_bnum, start_tnum;

	idnum = BEGID;
	balance = 500000;

	dbp = new Db(this, 0);
	dbp->set_h_nelem((unsigned int)accounts);

	if ((err = dbp->open("account", NULL, DB_HASH,
			     DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
		errExit(err, "Open of account file failed");
	}

	start_anum = idnum;
	populateTable(dbp, idnum, balance, accounts, "account");
	idnum += accounts;
	end_anum = idnum - 1;
	if ((err = dbp->close(0)) != 0) {
		errExit(err, "Account file close failed");
	}
	delete dbp;
	if (verbose)
		cout << "Populated accounts: "
		     << (long)start_anum << " - " << (long)end_anum << "\n";

	dbp = new Db(this, 0);
	//
	// Since the number of branches is very small, we want to use very
	// small pages and only 1 key per page.  This is the poor-man's way
	// of getting key locking instead of page locking.
	//
	dbp->set_h_ffactor(1);
	dbp->set_h_nelem((unsigned int)branches);
	dbp->set_pagesize(512);

	if ((err = dbp->open("branch", NULL, DB_HASH,
			     DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
		errExit(err, "Branch file create failed");
	}
	start_bnum = idnum;
	populateTable(dbp, idnum, balance, branches, "branch");
	idnum += branches;
	end_bnum = idnum - 1;
	if ((err = dbp->close(0)) != 0) {
		errExit(err, "Close of branch file failed");
	}
	delete dbp;

	if (verbose)
		cout << "Populated branches: "
		     << (long)start_bnum << " - " << (long)end_bnum << "\n";

	dbp = new Db(this, 0);
	//
	// In the case of tellers, we also want small pages, but we'll let
	// the fill factor dynamically adjust itself.
	//
	dbp->set_h_ffactor(0);
	dbp->set_h_nelem((unsigned int)tellers);
	dbp->set_pagesize(512);

	if ((err = dbp->open("teller", NULL, DB_HASH,
			     DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
		errExit(err, "Teller file create failed");
	}

	start_tnum = idnum;
	populateTable(dbp, idnum, balance, tellers, "teller");
	idnum += tellers;
	end_tnum = idnum - 1;
	if ((err = dbp->close(0)) != 0) {
		errExit(err, "Close of teller file failed");
	}
	delete dbp;
	if (verbose)
		cout << "Populated tellers: "
		     << (long)start_tnum << " - " << (long)end_tnum << "\n";

	dbp = new Db(this, 0);
	dbp->set_re_len(HISTORY_LEN);
	if ((err = dbp->open("history", NULL, DB_RECNO,
			     DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
		errExit(err, "Create of history file failed");
	}

	populateHistory(dbp, history, accounts, branches, tellers);
	if ((err = dbp->close(0)) != 0) {
		errExit(err, "Close of history file failed");
	}
	delete dbp;
}