// on input, _initLock is held, so this can be called by only one thread at a time, // also, on input, the CollectionMap must be allocated Collection *CollectionMap::open_ns(const StringData& ns, const bool bulkLoad) { verify(allocated()); BSONObj serialized; BSONObj nsobj = BSON("ns" << ns); storage::Key sKey(nsobj, NULL); DBT ndbt = sKey.dbt(); // If this transaction is read only, then we cannot possible already // hold a lock in the metadb and we certainly don't need to hold one // for the duration of this operation. So we use an alternate txn stack. const bool needAltTxn = !cc().hasTxn() || cc().txn().readOnly(); scoped_ptr<Client::AlternateTransactionStack> altStack(!needAltTxn ? NULL : new Client::AlternateTransactionStack()); scoped_ptr<Client::Transaction> altTxn(!needAltTxn ? NULL : new Client::Transaction(0)); // Pass flags that get us a write lock on the metadb row // for the ns we'd like to open. DB *db = _metadb->db(); const int r = db->getf_set(db, cc().txn().db_txn(), DB_SERIALIZABLE | DB_RMW, &ndbt, getf_serialized, &serialized); if (r == 0) { // We found an entry for this ns and we have the row lock. // First check if someone got the lock before us and already // did the open. Collection *cl = find_ns(ns); if (cl != NULL) { return cl; } // No need to hold the openRWLock during Collection::make(), // the fact that we have the row lock ensures only one thread will // be here for a particular ns at a time. shared_ptr<Collection> details = Collection::make( serialized, bulkLoad ); SimpleRWLock::Exclusive lk(_openRWLock); verify(!_collections[ns]); _collections[ns] = details; return details.get(); } else if (r != DB_NOTFOUND) { storage::handle_ydb_error(r); } return NULL; }
void Dictionary::open(const BSONObj &info, const mongo::Descriptor &descriptor, const bool may_create, const bool hot_index) { int readPageSize = 65536; int pageSize = 4 * 1024 * 1024; TOKU_COMPRESSION_METHOD compression = TOKU_ZLIB_WITHOUT_CHECKSUM_METHOD; BSONObj key_pattern = info["key"].Obj(); BSONElement e; e = info["readPageSize"]; if (e.ok() && !e.isNull()) { readPageSize = BytesQuantity<int>(e); uassert(16743, "readPageSize must be a number > 0.", readPageSize > 0); TOKULOG(1) << "db " << _dname << ", using read page size " << readPageSize << endl; } e = info["pageSize"]; if (e.ok() && !e.isNull()) { pageSize = BytesQuantity<int>(e); uassert(16445, "pageSize must be a number > 0.", pageSize > 0); TOKULOG(1) << "db " << _dname << ", using page size " << pageSize << endl; } e = info["compression"]; if (e.ok() && !e.isNull()) { std::string str = e.String(); if (str == "lzma") { compression = TOKU_LZMA_METHOD; } else if (str == "quicklz") { compression = TOKU_QUICKLZ_METHOD; } else if (str == "zlib") { compression = TOKU_ZLIB_WITHOUT_CHECKSUM_METHOD; } else if (str == "none") { compression = TOKU_NO_COMPRESSION; } else { uassert(16442, "compression must be one of: lzma, quicklz, zlib, none.", false); } TOKULOG(1) << "db " << _dname << ", using compression method \"" << str << "\"" << endl; } int r = _db->set_readpagesize(_db, readPageSize); if (r != 0) { handle_ydb_error(r); } r = _db->set_pagesize(_db, pageSize); if (r != 0) { handle_ydb_error(r); } r = _db->set_compression_method(_db, compression); if (r != 0) { handle_ydb_error(r); } // If this is a non-creating open for a read-only (or non-existent) // transaction, we can use an alternate stack since there's nothing // to roll back and no locktree locks to hold. const bool needAltTxn = !may_create && (!cc().hasTxn() || cc().txn().readOnly()); scoped_ptr<Client::AlternateTransactionStack> altStack(!needAltTxn ? NULL : new Client::AlternateTransactionStack()); scoped_ptr<Client::Transaction> altTxn(!needAltTxn ? NULL : new Client::Transaction(0)); const int db_flags = may_create ? DB_CREATE : 0; r = _db->open(_db, cc().txn().db_txn(), _dname.c_str(), NULL, DB_BTREE, db_flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (r == ENOENT && !may_create) { throw NeedsCreate(); } if (r != 0) { handle_ydb_error(r); } if (may_create) { set_db_descriptor(_db, descriptor, hot_index); } verify_or_upgrade_db_descriptor(_db, descriptor, hot_index); if (altTxn.get() != NULL) { altTxn->commit(); } }