summaryrefslogtreecommitdiff
path: root/db/database.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'db/database.cpp')
-rw-r--r--db/database.cpp327
1 files changed, 0 insertions, 327 deletions
diff --git a/db/database.cpp b/db/database.cpp
deleted file mode 100644
index 97b3fa011cb..00000000000
--- a/db/database.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-// database.cpp
-
-/**
-* Copyright (C) 2008 10gen Inc.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License, version 3,
-* as published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "pch.h"
-#include "pdfile.h"
-#include "database.h"
-#include "instance.h"
-#include "clientcursor.h"
-
-namespace mongo {
-
- bool Database::_openAllFiles = false;
-
- Database::~Database() {
- magic = 0;
- size_t n = files.size();
- for ( size_t i = 0; i < n; i++ )
- delete files[i];
- if( ccByLoc.size() ) {
- log() << "\n\n\nWARNING: ccByLoc not empty on database close! " << ccByLoc.size() << ' ' << name << endl;
- }
- }
-
- Database::Database(const char *nm, bool& newDb, const string& _path )
- : name(nm), path(_path), namespaceIndex( path, name ),
- profileName(name + ".system.profile") {
- try {
-
- {
- // check db name is valid
- size_t L = strlen(nm);
- uassert( 10028 , "db name is empty", L > 0 );
- uassert( 10029 , "bad db name [1]", *nm != '.' );
- uassert( 10030 , "bad db name [2]", nm[L-1] != '.' );
- uassert( 10031 , "bad char(s) in db name", strchr(nm, ' ') == 0 );
- uassert( 10032 , "db name too long", L < 64 );
- }
-
- newDb = namespaceIndex.exists();
- profile = cmdLine.defaultProfile;
-
- checkDuplicateUncasedNames();
-
- // If already exists, open. Otherwise behave as if empty until
- // there's a write, then open.
- if ( ! newDb || cmdLine.defaultProfile ) {
- namespaceIndex.init();
- if( _openAllFiles )
- openAllFiles();
-
- }
-
-
- magic = 781231;
- } catch(...) {
- // since destructor won't be called:
- for ( size_t i = 0; i < files.size(); i++ )
- delete files[i];
- throw;
- }
- }
-
- void Database::checkDuplicateUncasedNames() const {
- string duplicate = duplicateUncasedName( name, path );
- if ( !duplicate.empty() ) {
- stringstream ss;
- ss << "db already exists with different case other: [" << duplicate << "] me [" << name << "]";
- uasserted( DatabaseDifferCaseCode , ss.str() );
- }
- }
-
- string Database::duplicateUncasedName( const string &name, const string &path, set< string > *duplicates ) {
- if ( duplicates ) {
- duplicates->clear();
- }
-
- vector<string> others;
- getDatabaseNames( others , path );
-
- set<string> allShortNames;
- dbHolder.getAllShortNames( allShortNames );
-
- others.insert( others.end(), allShortNames.begin(), allShortNames.end() );
-
- for ( unsigned i=0; i<others.size(); i++ ) {
-
- if ( strcasecmp( others[i].c_str() , name.c_str() ) )
- continue;
-
- if ( strcmp( others[i].c_str() , name.c_str() ) == 0 )
- continue;
-
- if ( duplicates ) {
- duplicates->insert( others[i] );
- } else {
- return others[i];
- }
- }
- if ( duplicates ) {
- return duplicates->empty() ? "" : *duplicates->begin();
- }
- return "";
- }
-
- boost::filesystem::path Database::fileName( int n ) const {
- stringstream ss;
- ss << name << '.' << n;
- boost::filesystem::path fullName;
- fullName = boost::filesystem::path(path);
- if ( directoryperdb )
- fullName /= name;
- fullName /= ss.str();
- return fullName;
- }
-
- void Database::openAllFiles() {
- int n = 0;
- while( exists(n) ) {
- getFile(n);
- n++;
- }
- // If last file is empty, consider it preallocated and make sure it's not mapped
- // until a write is requested
- if ( n > 1 && getFile( n - 1 )->getHeader()->isEmpty() ) {
- delete files[ n - 1 ];
- files.pop_back();
- }
- }
-
- MongoDataFile* Database::getFile( int n, int sizeNeeded , bool preallocateOnly) {
- assert(this);
-
- namespaceIndex.init();
- if ( n < 0 || n >= DiskLoc::MaxFiles ) {
- out() << "getFile(): n=" << n << endl;
- massert( 10295 , "getFile(): bad file number value (corrupt db?): run repair", false);
- }
- DEV {
- if ( n > 100 )
- out() << "getFile(): n=" << n << "?" << endl;
- }
- MongoDataFile* p = 0;
- if ( !preallocateOnly ) {
- while ( n >= (int) files.size() )
- files.push_back(0);
- p = files[n];
- }
- if ( p == 0 ) {
- boost::filesystem::path fullName = fileName( n );
- string fullNameString = fullName.string();
- p = new MongoDataFile(n);
- int minSize = 0;
- if ( n != 0 && files[ n - 1 ] )
- minSize = files[ n - 1 ]->getHeader()->fileLength;
- if ( sizeNeeded + DataFileHeader::HeaderSize > minSize )
- minSize = sizeNeeded + DataFileHeader::HeaderSize;
- try {
- p->open( fullNameString.c_str(), minSize, preallocateOnly );
- }
- catch ( AssertionException& ) {
- delete p;
- throw;
- }
- if ( preallocateOnly )
- delete p;
- else
- files[n] = p;
- }
- return preallocateOnly ? 0 : p;
- }
-
- MongoDataFile* Database::addAFile( int sizeNeeded, bool preallocateNextFile ) {
- int n = (int) files.size();
- MongoDataFile *ret = getFile( n, sizeNeeded );
- if ( preallocateNextFile )
- preallocateAFile();
- return ret;
- }
-
- bool fileIndexExceedsQuota( const char *ns, int fileIndex, bool enforceQuota ) {
- return
- cmdLine.quota &&
- enforceQuota &&
- fileIndex >= cmdLine.quotaFiles &&
- // we don't enforce the quota on "special" namespaces as that could lead to problems -- e.g.
- // rejecting an index insert after inserting the main record.
- !NamespaceString::special( ns ) &&
- NamespaceString( ns ).db != "local";
- }
-
- MongoDataFile* Database::suitableFile( const char *ns, int sizeNeeded, bool preallocate, bool enforceQuota ) {
-
- // check existing files
- for ( int i=numFiles()-1; i>=0; i-- ) {
- MongoDataFile* f = getFile( i );
- if ( f->getHeader()->unusedLength >= sizeNeeded ) {
- if ( fileIndexExceedsQuota( ns, i-1, enforceQuota ) ) // NOTE i-1 is the value used historically for this check.
- ;
- else
- return f;
- }
- }
-
- if ( fileIndexExceedsQuota( ns, numFiles(), enforceQuota ) )
- uasserted(12501, "quota exceeded");
-
- // allocate files until we either get one big enough or hit maxSize
- for ( int i = 0; i < 8; i++ ) {
- MongoDataFile* f = addAFile( sizeNeeded, preallocate );
-
- if ( f->getHeader()->unusedLength >= sizeNeeded )
- return f;
-
- if ( f->getHeader()->fileLength >= MongoDataFile::maxSize() ) // this is as big as they get so might as well stop
- return f;
- }
-
- uasserted(14810, "couldn't allocate space (suitableFile)"); // callers don't check for null return code
- return 0;
- }
-
- MongoDataFile* Database::newestFile() {
- int n = numFiles();
- if ( n == 0 )
- return 0;
- return getFile(n-1);
- }
-
-
- Extent* Database::allocExtent( const char *ns, int size, bool capped, bool enforceQuota ) {
- Extent *e = DataFileMgr::allocFromFreeList( ns, size, capped );
- if( e )
- return e;
- return suitableFile( ns, size, !capped, enforceQuota )->createExtent( ns, size, capped );
- }
-
-
- bool Database::setProfilingLevel( int newLevel , string& errmsg ) {
- if ( profile == newLevel )
- return true;
-
- if ( newLevel < 0 || newLevel > 2 ) {
- errmsg = "profiling level has to be >=0 and <= 2";
- return false;
- }
-
- if ( newLevel == 0 ) {
- profile = 0;
- return true;
- }
-
- assert( cc().database() == this );
-
- if ( ! namespaceIndex.details( profileName.c_str() ) ) {
- log() << "creating profile collection: " << profileName << endl;
- BSONObjBuilder spec;
- spec.appendBool( "capped", true );
- spec.append( "size", 1024*1024 );
- if ( ! userCreateNS( profileName.c_str(), spec.done(), errmsg , false /* we don't replica profile messages */ ) ) {
- return false;
- }
- }
- profile = newLevel;
- return true;
- }
-
- bool Database::validDBName( const string& ns ) {
- if ( ns.size() == 0 || ns.size() > 64 )
- return false;
- size_t good = strcspn( ns.c_str() , "/\\. \"" );
- return good == ns.size();
- }
-
- void Database::flushFiles( bool sync ) const {
- dbMutex.assertAtLeastReadLocked();
- for ( unsigned i=0; i<files.size(); i++ ) {
- files[i]->flush( sync );
- }
- }
-
- long long Database::fileSize() const {
- long long size=0;
- for (int n=0; exists(n); n++)
- size += boost::filesystem::file_size( fileName(n) );
- return size;
- }
-
- Database* DatabaseHolder::getOrCreate( const string& ns , const string& path , bool& justCreated ) {
- dbMutex.assertWriteLocked();
- DBs& m = _paths[path];
-
- string dbname = _todb( ns );
-
- Database* & db = m[dbname];
- if ( db ) {
- justCreated = false;
- return db;
- }
-
- log(1) << "Accessing: " << dbname << " for the first time" << endl;
- try {
- db = new Database( dbname.c_str() , justCreated , path );
- }
- catch ( ... ) {
- m.erase( dbname );
- throw;
- }
- _size++;
- return db;
- }
-
-} // namespace mongo