~ubuntu-branches/ubuntu/trusty/mongodb/trusty-proposed

« back to all changes in this revision

Viewing changes to db/client.h

  • Committer: Bazaar Package Importer
  • Author(s): Antonin Kral
  • Date: 2010-01-29 19:48:45 UTC
  • Revision ID: james.westby@ubuntu.com-20100129194845-8wbmkf626fwcavc9
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// client.h
 
2
 
 
3
/**
 
4
*    Copyright (C) 2008 10gen Inc.
 
5
*
 
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.
 
9
*
 
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.
 
14
*
 
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/>.
 
17
*/
 
18
 
 
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.
 
21
 
 
22
   todo: switch to asio...this will fit nicely with that.
 
23
*/
 
24
 
 
25
#pragma once
 
26
 
 
27
#include "../stdafx.h"
 
28
#include "namespace.h"
 
29
#include "lasterror.h"
 
30
#include "../util/top.h"
 
31
 
 
32
namespace mongo { 
 
33
 
 
34
    class AuthenticationInfo;
 
35
    class Database;
 
36
    class CurOp;
 
37
    class Command;
 
38
    class Client;
 
39
 
 
40
    extern boost::thread_specific_ptr<Client> currentClient;
 
41
 
 
42
    bool setClient(const char *ns, const string& path=dbpath, mongolock *lock = 0);
 
43
 
 
44
 
 
45
    class Client : boost::noncopyable { 
 
46
    public:
 
47
        static boost::mutex clientsMutex;
 
48
        static set<Client*> clients; // always be in clientsMutex when manipulating this
 
49
 
 
50
        class GodScope {
 
51
            bool _prev;
 
52
        public:
 
53
            GodScope();
 
54
            ~GodScope();
 
55
        };
 
56
 
 
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.
 
59
        */
 
60
        class Context {
 
61
            Client * _client;
 
62
            Database * _olddb;
 
63
            string _oldns;
 
64
        public:
 
65
            Context(const char *ns) 
 
66
                : _client( currentClient.get() ) {
 
67
                _olddb = _client->_database;
 
68
                _oldns = _client->_ns;
 
69
                setClient(ns);
 
70
            }
 
71
            Context(string ns) 
 
72
                : _client( currentClient.get() ){
 
73
                _olddb = _client->_database;
 
74
                _oldns = _client->_ns;
 
75
                setClient(ns.c_str());
 
76
            }
 
77
            
 
78
            /* this version saves the context but doesn't yet set the new one: */
 
79
            Context() 
 
80
                : _client( currentClient.get() ) {
 
81
                _olddb = _client->database();
 
82
                _oldns = _client->ns();        
 
83
 
 
84
            }
 
85
            
 
86
            /**
 
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
 
89
             */
 
90
            Context( string ns , Database * db );
 
91
 
 
92
            ~Context() {
 
93
                DEV assert( _client == currentClient.get() );
 
94
                _client->setns( _oldns.c_str(), _olddb );
 
95
            }
 
96
 
 
97
        };
 
98
 
 
99
    private:
 
100
        CurOp * const _curOp;
 
101
        Database *_database;
 
102
        Namespace _ns;
 
103
        //NamespaceString _nsstr;
 
104
        bool _shutdown;
 
105
        list<string> _tempCollections;
 
106
        const char *_desc;
 
107
        bool _god;
 
108
    public:
 
109
        AuthenticationInfo *ai;
 
110
        Top top;
 
111
 
 
112
        CurOp* curop() { return _curOp; }
 
113
        Database* database() { 
 
114
            return _database; 
 
115
        }
 
116
        const char *ns() { return _ns.buf; }
 
117
 
 
118
        void setns(const char *ns, Database *db) { 
 
119
            _database = db;
 
120
            _ns = ns;
 
121
            //_nsstr = ns;
 
122
        }
 
123
        void clearns() { setns("", 0); }
 
124
 
 
125
        Client(const char *desc);
 
126
        ~Client();
 
127
 
 
128
        const char *desc() const { return _desc; }
 
129
 
 
130
        void addTempCollection( const string& ns ){
 
131
            _tempCollections.push_back( ns );
 
132
        }
 
133
 
 
134
        /* each thread which does db operations has a Client object in TLS.  
 
135
           call this when your thread starts. 
 
136
        */
 
137
        static void initThread(const char *desc);
 
138
 
 
139
        /* 
 
140
           this has to be called as the client goes away, but before thread termination
 
141
           @return true if anything was done
 
142
         */
 
143
        bool shutdown();
 
144
 
 
145
        bool isGod() const { return _god; }
 
146
    };
 
147
    
 
148
    inline Client& cc() { 
 
149
        return *currentClient.get();
 
150
    }
 
151
 
 
152
    /* each thread which does db operations has a Client object in TLS.  
 
153
       call this when your thread starts. 
 
154
    */
 
155
    inline void Client::initThread(const char *desc) {
 
156
        assert( currentClient.get() == 0 );
 
157
        currentClient.reset( new Client(desc) );
 
158
    }
 
159
 
 
160
    inline Client::GodScope::GodScope(){
 
161
        _prev = cc()._god;
 
162
        cc()._god = true;
 
163
    }
 
164
 
 
165
    inline Client::GodScope::~GodScope(){
 
166
        cc()._god = _prev;
 
167
    }
 
168
 
 
169
        /* this unlocks, does NOT upgrade. that works for our current usage */
 
170
    inline void mongolock::releaseAndWriteLock() { 
 
171
        if( !_writelock ) {
 
172
 
 
173
#if BOOST_VERSION >= 103500
 
174
            int s = dbMutex.getState();
 
175
            if( s != -1 ) {
 
176
                log() << "error: releaseAndWriteLock() s == " << s << endl;
 
177
                msgasserted( 12600, "releaseAndWriteLock: unlock_shared failed, probably recursive" );
 
178
            }
 
179
#endif
 
180
 
 
181
            _writelock = true;
 
182
            dbMutex.unlock_shared();
 
183
            dbMutex.lock();
 
184
 
 
185
            /* this is defensive; as we were unlocked for a moment above, 
 
186
               the Database object we reference could have been deleted:
 
187
            */
 
188
            cc().clearns();
 
189
        }
 
190
    }
 
191
    
 
192
};
 
193