4
* Copyright (C) 2008 10gen Inc.
6
* This program is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Affero General Public License, version 3,
8
* as published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU Affero General Public License for more details.
15
* You should have received a copy of the GNU Affero General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19
/* Client represents a connection to the database (the server-side) and corresponds
20
to an open socket (or logical connection if pooling on sockets) from a client.
22
todo: switch to asio...this will fit nicely with that.
27
#include "../stdafx.h"
28
#include "namespace.h"
29
#include "lasterror.h"
30
#include "../util/top.h"
34
class AuthenticationInfo;
40
extern boost::thread_specific_ptr<Client> currentClient;
42
bool setClient(const char *ns, const string& path=dbpath, mongolock *lock = 0);
45
class Client : boost::noncopyable {
47
static boost::mutex clientsMutex;
48
static set<Client*> clients; // always be in clientsMutex when manipulating this
57
/* Set database we want to use, then, restores when we finish (are out of scope)
58
Note this is also helpful if an exception happens as the state if fixed up.
65
Context(const char *ns)
66
: _client( currentClient.get() ) {
67
_olddb = _client->_database;
68
_oldns = _client->_ns;
72
: _client( currentClient.get() ){
73
_olddb = _client->_database;
74
_oldns = _client->_ns;
75
setClient(ns.c_str());
78
/* this version saves the context but doesn't yet set the new one: */
80
: _client( currentClient.get() ) {
81
_olddb = _client->database();
82
_oldns = _client->ns();
87
* if you are doing this after allowing a write there could be a race condition
88
* if someone closes that db. this checks that the DB is still valid
90
Context( string ns , Database * db );
93
DEV assert( _client == currentClient.get() );
94
_client->setns( _oldns.c_str(), _olddb );
100
CurOp * const _curOp;
103
//NamespaceString _nsstr;
105
list<string> _tempCollections;
109
AuthenticationInfo *ai;
112
CurOp* curop() { return _curOp; }
113
Database* database() {
116
const char *ns() { return _ns.buf; }
118
void setns(const char *ns, Database *db) {
123
void clearns() { setns("", 0); }
125
Client(const char *desc);
128
const char *desc() const { return _desc; }
130
void addTempCollection( const string& ns ){
131
_tempCollections.push_back( ns );
134
/* each thread which does db operations has a Client object in TLS.
135
call this when your thread starts.
137
static void initThread(const char *desc);
140
this has to be called as the client goes away, but before thread termination
141
@return true if anything was done
145
bool isGod() const { return _god; }
148
inline Client& cc() {
149
return *currentClient.get();
152
/* each thread which does db operations has a Client object in TLS.
153
call this when your thread starts.
155
inline void Client::initThread(const char *desc) {
156
assert( currentClient.get() == 0 );
157
currentClient.reset( new Client(desc) );
160
inline Client::GodScope::GodScope(){
165
inline Client::GodScope::~GodScope(){
169
/* this unlocks, does NOT upgrade. that works for our current usage */
170
inline void mongolock::releaseAndWriteLock() {
173
#if BOOST_VERSION >= 103500
174
int s = dbMutex.getState();
176
log() << "error: releaseAndWriteLock() s == " << s << endl;
177
msgasserted( 12600, "releaseAndWriteLock: unlock_shared failed, probably recursive" );
182
dbMutex.unlock_shared();
185
/* this is defensive; as we were unlocked for a moment above,
186
the Database object we reference could have been deleted: