/* * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the * specific language governing rights and limitations under the License. */ #ifdef __MWERKS__ #define _CPP_DATABASE #endif #include #include #include #include DatabaseManager::DatabaseManager () { } DatabaseManager::~DatabaseManager () { } Database * DatabaseManager::get (const DbName &inDbName) { StLock _(mDatabaseMapLock); DatabaseMap::iterator anIterator = mDatabaseMap.find (inDbName); if (anIterator == mDatabaseMap.end()) { auto_ptr aDatabase(make(inDbName)); mDatabaseMap.insert(DatabaseMap::value_type(aDatabase->mDbName, aDatabase.get())); return aDatabase.release(); } return anIterator->second; } void DatabaseManager::removeIfUnused(Database &inDatabase) { StLock _(mDatabaseMapLock); if (!inDatabase.hasDbContexts()) { mDatabaseMap.erase(inDatabase.mDbName); delete &inDatabase; } } DbContext & DatabaseManager::dbOpen(DatabaseSession &inDatabaseSession, const DbName &inDbName, CSSM_DB_ACCESS_TYPE inAccessRequest, const AccessCredentials *inAccessCred, const void *inOpenParameters) { Database &aDatabase = *get(inDbName); try { return aDatabase._dbOpen(inDatabaseSession, inAccessRequest, inAccessCred, inOpenParameters); } catch (...) { removeIfUnused(aDatabase); throw; } } DbContext & DatabaseManager::dbCreate(DatabaseSession &inDatabaseSession, const DbName &inDbName, const CSSM_DBINFO &inDBInfo, CSSM_DB_ACCESS_TYPE inAccessRequest, const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, const void *inOpenParameters) { Database &aDatabase = *get(inDbName); try { return aDatabase._dbCreate(inDatabaseSession, inDBInfo, inAccessRequest, inCredAndAclEntry, inOpenParameters); } catch (...) { removeIfUnused(aDatabase); throw; } } // Delete a DbContext instance created by calling dbOpen or dbCreate. void DatabaseManager::dbClose(DbContext &inDbContext) { Database &aDatabase = inDbContext.mDatabase; aDatabase._dbClose(inDbContext); removeIfUnused(aDatabase); } // Delete a database. void DatabaseManager::dbDelete(DatabaseSession &inDatabaseSession, const DbName &inDbName, const AccessCredentials *inAccessCred) { Database &aDatabase = *get(inDbName); try { aDatabase.dbDelete(inDatabaseSession, inAccessCred); } catch (...) { removeIfUnused(aDatabase); throw; } removeIfUnused(aDatabase); } // List all available databases. CSSM_NAME_LIST_PTR DatabaseManager::getDbNames(DatabaseSession &inDatabaseSession) { CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } void DatabaseManager::freeNameList(DatabaseSession &inDatabaseSession, CSSM_NAME_LIST &inNameList) { CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } // Start of Database implementation. Database::Database (const DbName &inDbName) : mDbName(inDbName) { } Database::~Database () { } bool Database::hasDbContexts() { StLock _(mDbContextSetLock); return !mDbContextSet.empty(); } DbContext & Database::_dbOpen(DatabaseSession &inDatabaseSession, CSSM_DB_ACCESS_TYPE inAccessRequest, const AccessCredentials *inAccessCred, const void *inOpenParameters) { auto_ptraDbContext(makeDbContext(inDatabaseSession, inAccessRequest, inAccessCred, inOpenParameters)); { StLock _(mDbContextSetLock); mDbContextSet.insert(aDbContext.get()); // Release the mDbContextSetLock } try { dbOpen(*aDbContext); } catch (...) { StLock _(mDbContextSetLock); mDbContextSet.erase(aDbContext.get()); throw; } return *aDbContext.release(); } DbContext & Database::_dbCreate(DatabaseSession &inDatabaseSession, const CSSM_DBINFO &inDBInfo, CSSM_DB_ACCESS_TYPE inAccessRequest, const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry, const void *inOpenParameters) { auto_ptraDbContext(makeDbContext(inDatabaseSession, inAccessRequest, (inCredAndAclEntry ? AccessCredentials::optional(inCredAndAclEntry->AccessCred) : NULL), inOpenParameters)); { StLock _(mDbContextSetLock); mDbContextSet.insert(aDbContext.get()); // Release the mDbContextSetLock } try { dbCreate(*aDbContext, inDBInfo, inCredAndAclEntry ? &inCredAndAclEntry->InitialAclEntry : NULL); } catch (...) { StLock _(mDbContextSetLock); mDbContextSet.erase(aDbContext.get()); throw; } return *aDbContext.release(); } void Database::_dbClose(DbContext &dbContext) { StLock _(mDbContextSetLock); mDbContextSet.erase(&dbContext); if (mDbContextSet.empty()) dbClose(); }