00001
00002
00019
00020
00021
00022
00023
00024
00025 #pragma once
00026
00027 #include "../pch.h"
00028 #include "security.h"
00029 #include "namespace-inl.h"
00030 #include "lasterror.h"
00031 #include "stats/top.h"
00032
00033 namespace mongo {
00034
00035 extern class ReplSet *theReplSet;
00036 class AuthenticationInfo;
00037 class Database;
00038 class CurOp;
00039 class Command;
00040 class Client;
00041 class MessagingPort;
00042
00043 extern boost::thread_specific_ptr<Client> currentClient;
00044
00045 typedef long long ConnectionId;
00046
00047 class Client : boost::noncopyable {
00048 public:
00049 class Context;
00050
00051 static mongo::mutex clientsMutex;
00052 static set<Client*> clients;
00053 static int recommendedYieldMicros( int * writers = 0 , int * readers = 0 );
00054 static int getActiveClientCount( int& writers , int& readers );
00055
00056 static Client *syncThread;
00057
00058
00059
00060
00061
00062 static Client& initThread(const char *desc, MessagingPort *mp = 0);
00063
00064
00065
00066
00067
00068 bool shutdown();
00069
00070
00071 ~Client();
00072
00073 void iAmSyncThread() {
00074 wassert( syncThread == 0 );
00075 syncThread = this;
00076 }
00077 bool isSyncThread() const { return this == syncThread; }
00078
00079
00080 string clientAddress(bool includePort=false) const;
00081 AuthenticationInfo * getAuthenticationInfo() { return &_ai; }
00082 bool isAdmin() { return _ai.isAuthorized( "admin" ); }
00083 CurOp* curop() const { return _curOp; }
00084 Context* getContext() const { return _context; }
00085 Database* database() const { return _context ? _context->db() : 0; }
00086 const char *ns() const { return _context->ns(); }
00087 const char *desc() const { return _desc; }
00088 void setLastOp( ReplTime op ) { _lastOp = op; }
00089 ReplTime getLastOp() const { return _lastOp; }
00090
00091
00092 void appendLastOp( BSONObjBuilder& b ) const;
00093
00094 bool isGod() const { return _god; }
00095 string toString() const;
00096 void gotHandshake( const BSONObj& o );
00097 BSONObj getRemoteID() const { return _remoteId; }
00098 BSONObj getHandshake() const { return _handshake; }
00099
00100 MessagingPort * port() const { return _mp; }
00101
00102 ConnectionId getConnectionId() const { return _connectionId; }
00103
00104 private:
00105 ConnectionId _connectionId;
00106 CurOp * _curOp;
00107 Context * _context;
00108 bool _shutdown;
00109 const char *_desc;
00110 bool _god;
00111 AuthenticationInfo _ai;
00112 ReplTime _lastOp;
00113 BSONObj _handshake;
00114 BSONObj _remoteId;
00115 MessagingPort * const _mp;
00116
00117 Client(const char *desc, MessagingPort *p = 0);
00118
00119 friend class CurOp;
00120
00121 public:
00122
00123
00124 class GodScope {
00125 bool _prev;
00126 public:
00127 GodScope();
00128 ~GodScope();
00129 };
00130
00131
00132
00133
00134
00135 class Context : boost::noncopyable {
00136 public:
00141 Context(const string& ns, string path=dbpath, mongolock * lock = 0 , bool doauth=true );
00142
00143
00144 Context();
00145
00150 Context( string ns , Database * db, bool doauth=true );
00151
00152 ~Context();
00153
00154 Client* getClient() const { return _client; }
00155 Database* db() const { return _db; }
00156 const char * ns() const { return _ns.c_str(); }
00157
00159 bool justCreated() const { return _justCreated; }
00160
00161 bool equals( const string& ns , const string& path=dbpath ) const { return _ns == ns && _path == path; }
00162
00166 bool inDB( const string& db , const string& path=dbpath ) const;
00167
00168 void clear() { _ns = ""; _db = 0; }
00169
00173 void unlocked() { _db = 0; }
00174
00178 void relocked() { _finishInit(); }
00179
00180 friend class CurOp;
00181
00182 private:
00189 void _finishInit( bool doauth=true);
00190
00191 void _auth( int lockState = dbMutex.getState() );
00192
00193 Client * _client;
00194 Context * _oldContext;
00195
00196 string _path;
00197 mongolock * _lock;
00198 bool _justCreated;
00199
00200 string _ns;
00201 Database * _db;
00202
00203 };
00204
00205
00206 };
00207
00209 inline Client& cc() {
00210 Client * c = currentClient.get();
00211 assert( c );
00212 return *c;
00213 }
00214
00215 inline Client::GodScope::GodScope() {
00216 _prev = cc()._god;
00217 cc()._god = true;
00218 }
00219
00220 inline Client::GodScope::~GodScope() { cc()._god = _prev; }
00221
00222
00223 inline void mongolock::releaseAndWriteLock() {
00224 if( !_writelock ) {
00225
00226 #if BOOST_VERSION >= 103500
00227 int s = dbMutex.getState();
00228 if( s != -1 ) {
00229 log() << "error: releaseAndWriteLock() s == " << s << endl;
00230 msgasserted( 12600, "releaseAndWriteLock: unlock_shared failed, probably recursive" );
00231 }
00232 #endif
00233
00234 _writelock = true;
00235 dbMutex.unlock_shared();
00236 dbMutex.lock();
00237
00238 if ( cc().getContext() )
00239 cc().getContext()->unlocked();
00240 }
00241 }
00242
00243 string sayClientState();
00244
00245 inline bool haveClient() { return currentClient.get() > 0; }
00246 };