~evarlast/ubuntu/utopic/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/mongo/s/shard_conn_test.cpp

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*    Copyright 2012 10gen Inc.
 
2
 *
 
3
 *    Licensed under the Apache License, Version 2.0 (the "License");
 
4
 *    you may not use this file except in compliance with the License.
 
5
 *    You may obtain a copy of the License at
 
6
 *
 
7
 *    http://www.apache.org/licenses/LICENSE-2.0
 
8
 *
 
9
 *    Unless required by applicable law or agreed to in writing, software
 
10
 *    distributed under the License is distributed on an "AS IS" BASIS,
 
11
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
12
 *    See the License for the specific language governing permissions and
 
13
 *    limitations under the License.
 
14
 */
 
15
 
 
16
#include "mongo/base/init.h"
 
17
#include "mongo/client/connpool.h"
 
18
#include "mongo/dbtests/mock/mock_conn_registry.h"
 
19
#include "mongo/dbtests/mock/mock_dbclient_connection.h"
 
20
#include "mongo/platform/cstdint.h"
 
21
#include "mongo/s/shard.h"
 
22
#include "mongo/unittest/unittest.h"
 
23
 
 
24
#include <vector>
 
25
#include <boost/scoped_ptr.hpp>
 
26
#include <boost/thread/thread.hpp>
 
27
 
 
28
/**
 
29
 * Tests for ShardConnection, particularly in connection pool management.
 
30
 * The tests focuses more on ShardConnection's logic as opposed to testing
 
31
 * the internal connections together, like in client/scoped_db_conn_test.cpp.
 
32
 */
 
33
 
 
34
using boost::scoped_ptr;
 
35
using mongo::DBClientBase;
 
36
using mongo::MockRemoteDBServer;
 
37
using mongo::ShardConnection;
 
38
using std::string;
 
39
using std::vector;
 
40
 
 
41
namespace mongo {
 
42
    // Note: these are all crutch and hopefully will eventually go away
 
43
    CmdLine cmdLine;
 
44
 
 
45
    bool inShutdown() {
 
46
        return false;
 
47
    }
 
48
 
 
49
    DBClientBase *createDirectClient() { return NULL; }
 
50
 
 
51
    void dbexit(ExitCode rc, const char *why){
 
52
        ::_exit(-1);
 
53
    }
 
54
 
 
55
    bool haveLocalShardingInfo(const string& ns) {
 
56
        return false;
 
57
    }
 
58
}
 
59
 
 
60
namespace mongo_test {
 
61
    const string TARGET_HOST = "$dummy:27017";
 
62
 
 
63
    /**
 
64
     * Warning: cannot run in parallel
 
65
     */
 
66
    class ShardConnFixture: public mongo::unittest::Test {
 
67
    public:
 
68
        void setUp() {
 
69
            _maxPoolSizePerHost = mongo::PoolForHost::getMaxPerHost();
 
70
 
 
71
            mongo::ConnectionString::setConnectionHook(
 
72
                    mongo::MockConnRegistry::get()->getConnStrHook());
 
73
            _dummyServer = new MockRemoteDBServer(TARGET_HOST);
 
74
            mongo::MockConnRegistry::get()->addServer(_dummyServer);
 
75
        }
 
76
 
 
77
        void tearDown() {
 
78
            ShardConnection::clearPool();
 
79
 
 
80
            mongo::MockConnRegistry::get()->removeServer(_dummyServer->getServerAddress());
 
81
            delete _dummyServer;
 
82
 
 
83
            mongo::PoolForHost::setMaxPerHost(_maxPoolSizePerHost);
 
84
        }
 
85
 
 
86
        void killServer() {
 
87
            _dummyServer->shutdown();
 
88
        }
 
89
 
 
90
        void restartServer() {
 
91
            _dummyServer->reboot();
 
92
        }
 
93
 
 
94
    protected:
 
95
        static void assertGreaterThan(uint64_t a, uint64_t b) {
 
96
            ASSERT_GREATER_THAN(a, b);
 
97
        }
 
98
 
 
99
        static void assertNotEqual(uint64_t a, uint64_t b) {
 
100
            ASSERT_NOT_EQUALS(a, b);
 
101
        }
 
102
 
 
103
        /**
 
104
         * Tries to grab a series of connections from the pool, perform checks on
 
105
         * them, then put them back into the pool. After that, it checks these
 
106
         * connections can be retrieved again from the pool.
 
107
         *
 
108
         * @param checkFunc method for comparing new connections and arg2.
 
109
         * @param arg2 the value to pass as the 2nd parameter of checkFunc.
 
110
         * @param newConnsToCreate the number of new connections to make.
 
111
         */
 
112
        void checkNewConns(void (*checkFunc)(uint64_t, uint64_t), uint64_t arg2,
 
113
                size_t newConnsToCreate) {
 
114
            vector<ShardConnection*> newConnList;
 
115
            for (size_t x = 0; x < newConnsToCreate; x++) {
 
116
                ShardConnection* newConn = new ShardConnection(TARGET_HOST, "test.user");
 
117
                checkFunc(newConn->get()->getSockCreationMicroSec(), arg2);
 
118
                newConnList.push_back(newConn);
 
119
            }
 
120
 
 
121
            const uint64_t oldCreationTime = mongo::curTimeMicros64();
 
122
 
 
123
            for (vector<ShardConnection*>::iterator iter = newConnList.begin();
 
124
                    iter != newConnList.end(); ++iter) {
 
125
                (*iter)->done();
 
126
                delete *iter;
 
127
            }
 
128
 
 
129
            newConnList.clear();
 
130
 
 
131
            // Check that connections created after the purge was put back to the pool.
 
132
            for (size_t x = 0; x < newConnsToCreate; x++) {
 
133
                ShardConnection* newConn = new ShardConnection(TARGET_HOST, "test.user");
 
134
                ASSERT_LESS_THAN(newConn->get()->getSockCreationMicroSec(), oldCreationTime);
 
135
                newConnList.push_back(newConn);
 
136
            }
 
137
 
 
138
            for (vector<ShardConnection*>::iterator iter = newConnList.begin();
 
139
                    iter != newConnList.end(); ++iter) {
 
140
                (*iter)->done();
 
141
                delete *iter;
 
142
            }
 
143
        }
 
144
 
 
145
    private:
 
146
        MockRemoteDBServer* _dummyServer;
 
147
        uint32_t _maxPoolSizePerHost;
 
148
    };
 
149
 
 
150
    TEST_F(ShardConnFixture, BasicShardConnection) {
 
151
        ShardConnection conn1(TARGET_HOST, "test.user");
 
152
        ShardConnection conn2(TARGET_HOST, "test.user");
 
153
 
 
154
        DBClientBase* conn1Ptr = conn1.get();
 
155
        conn1.done();
 
156
 
 
157
        ShardConnection conn3(TARGET_HOST, "test.user");
 
158
        ASSERT_EQUALS(conn1Ptr, conn3.get());
 
159
 
 
160
        conn2.done();
 
161
        conn3.done();
 
162
    }
 
163
 
 
164
    TEST_F(ShardConnFixture, InvalidateBadConnInPool) {
 
165
        ShardConnection conn1(TARGET_HOST, "test.user");
 
166
        ShardConnection conn2(TARGET_HOST, "test.user");
 
167
        ShardConnection conn3(TARGET_HOST, "test.user");
 
168
 
 
169
        conn1.done();
 
170
        conn3.done();
 
171
 
 
172
        const uint64_t badCreationTime = mongo::curTimeMicros64();
 
173
        killServer();
 
174
 
 
175
        try {
 
176
            conn2.get()->query("test.user", mongo::Query());
 
177
        }
 
178
        catch (const mongo::SocketException&) {
 
179
        }
 
180
 
 
181
        conn2.done();
 
182
 
 
183
        restartServer();
 
184
        checkNewConns(assertGreaterThan, badCreationTime, 10);
 
185
    }
 
186
 
 
187
    TEST_F(ShardConnFixture, DontReturnKnownBadConnToPool) {
 
188
        ShardConnection conn1(TARGET_HOST, "test.user");
 
189
        ShardConnection conn2(TARGET_HOST, "test.user");
 
190
        ShardConnection conn3(TARGET_HOST, "test.user");
 
191
 
 
192
        conn1.done();
 
193
        killServer();
 
194
 
 
195
        try {
 
196
            conn3.get()->query("test.user", mongo::Query());
 
197
        }
 
198
        catch (const mongo::SocketException&) {
 
199
        }
 
200
 
 
201
        restartServer();
 
202
 
 
203
        const uint64_t badCreationTime = conn3.get()->getSockCreationMicroSec();
 
204
        conn3.done();
 
205
        // attempting to put a 'bad' connection back to the pool
 
206
        conn2.done();
 
207
 
 
208
        checkNewConns(assertGreaterThan, badCreationTime, 10);
 
209
    }
 
210
 
 
211
    TEST_F(ShardConnFixture, BadConnClearsPoolWhenKilled) {
 
212
        ShardConnection conn1(TARGET_HOST, "test.user");
 
213
        ShardConnection conn2(TARGET_HOST, "test.user");
 
214
        ShardConnection conn3(TARGET_HOST, "test.user");
 
215
 
 
216
        conn1.done();
 
217
        killServer();
 
218
 
 
219
        try {
 
220
            conn3.get()->query("test.user", mongo::Query());
 
221
        }
 
222
        catch (const mongo::SocketException&) {
 
223
        }
 
224
 
 
225
        restartServer();
 
226
 
 
227
        const uint64_t badCreationTime = conn3.get()->getSockCreationMicroSec();
 
228
        conn3.kill();
 
229
        // attempting to put a 'bad' connection back to the pool
 
230
        conn2.done();
 
231
 
 
232
        checkNewConns(assertGreaterThan, badCreationTime, 10);
 
233
    }
 
234
 
 
235
    TEST_F(ShardConnFixture, KilledGoodConnShouldNotClearPool) {
 
236
        ShardConnection conn1(TARGET_HOST, "test.user");
 
237
        ShardConnection conn2(TARGET_HOST, "test.user");
 
238
        ShardConnection conn3(TARGET_HOST, "test.user");
 
239
 
 
240
        const uint64_t upperBoundCreationTime =
 
241
                conn3.get()->getSockCreationMicroSec();
 
242
        conn3.done();
 
243
 
 
244
        const uint64_t badCreationTime = conn1.get()->getSockCreationMicroSec();
 
245
        conn1.kill();
 
246
 
 
247
        conn2.done();
 
248
 
 
249
        ShardConnection conn4(TARGET_HOST, "test.user");
 
250
        ShardConnection conn5(TARGET_HOST, "test.user");
 
251
 
 
252
        ASSERT_GREATER_THAN(conn4.get()->getSockCreationMicroSec(), badCreationTime);
 
253
        ASSERT_LESS_THAN_OR_EQUALS(conn4.get()->getSockCreationMicroSec(),
 
254
                upperBoundCreationTime);
 
255
 
 
256
        ASSERT_GREATER_THAN(conn5.get()->getSockCreationMicroSec(), badCreationTime);
 
257
        ASSERT_LESS_THAN_OR_EQUALS(conn5.get()->getSockCreationMicroSec(),
 
258
                upperBoundCreationTime);
 
259
 
 
260
        checkNewConns(assertGreaterThan, upperBoundCreationTime, 10);
 
261
    }
 
262
 
 
263
    TEST_F(ShardConnFixture, InvalidateBadConnEvenWhenPoolIsFull) {
 
264
        mongo::PoolForHost::setMaxPerHost(2);
 
265
 
 
266
        ShardConnection conn1(TARGET_HOST, "test.user");
 
267
        ShardConnection conn2(TARGET_HOST, "test.user");
 
268
        ShardConnection conn3(TARGET_HOST, "test.user");
 
269
 
 
270
        conn1.done();
 
271
        conn3.done();
 
272
 
 
273
        const uint64_t badCreationTime = mongo::curTimeMicros64();
 
274
        killServer();
 
275
 
 
276
        try {
 
277
            conn2.get()->query("test.user", mongo::Query());
 
278
        }
 
279
        catch (const mongo::SocketException&) {
 
280
        }
 
281
 
 
282
        conn2.done();
 
283
 
 
284
        restartServer();
 
285
        checkNewConns(assertGreaterThan, badCreationTime, 2);
 
286
    }
 
287
 
 
288
    TEST_F(ShardConnFixture, DontReturnConnGoneBadToPool) {
 
289
        ShardConnection conn1(TARGET_HOST, "test.user");
 
290
        const uint64_t conn1CreationTime = conn1.get()->getSockCreationMicroSec();
 
291
 
 
292
        uint64_t conn2CreationTime = 0;
 
293
 
 
294
        {
 
295
            ShardConnection conn2(TARGET_HOST, "test.user");
 
296
            conn2CreationTime = conn2.get()->getSockCreationMicroSec();
 
297
 
 
298
            conn1.done();
 
299
            // conn2 gets out of scope without calling done()
 
300
        }
 
301
 
 
302
        // conn2 should not have been put back into the pool but it should
 
303
        // also not invalidate older connections since it didn't encounter
 
304
        // a socket exception.
 
305
 
 
306
        ShardConnection conn1Again(TARGET_HOST, "test.user");
 
307
        ASSERT_EQUALS(conn1CreationTime, conn1Again.get()->getSockCreationMicroSec());
 
308
 
 
309
        checkNewConns(assertNotEqual, conn2CreationTime, 10);
 
310
        conn1Again.done();
 
311
    }
 
312
}