1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
// Grid infrastructure: Servers, ReplicaSets, ConfigSets, Shards, Routers (mongos). Convenient objects and functions on top of those in shell/servers.js -Tony
load('jstests/libs/fun.js')
load('jstests/libs/network.js')
// New servers and routers take and increment port number from this.
// A comment containing FreshPorts monad implies reading and incrementing this, IO may also read/increment this.
var nextPort = 31000
/*** Server is the spec of a mongod, ie. all its command line options.
To start a server call 'begin' ***/
// new Server :: String -> FreshPorts Server
function Server (name) {
this.dbpath = '/data/db/' + name + nextPort
this.port = nextPort++
this.noprealloc = ''
this.smallfiles = ''
this.rest = ''
this.oplogSize = 8
}
Server.prototype.addr = '127.0.0.1'
// Server -> String <addr:port>
Server.prototype.host = function() {
return this.addr + ':' + this.port
}
// Start a new server with this spec and return connection to it
// Server -> IO Connection
Server.prototype.begin = function() {
return startMongodEmpty(this)
}
// Stop server and remove db directory
// Server -> IO ()
Server.prototype.end = function() {
print('Stopping mongod on port ' + this.port)
stopMongod (this.port)
resetDbpath (this.dbpath)
}
// Cut server from network so it is unreachable (but still alive)
// Requires sudo access and ipfw program (Mac OS X and BSD Unix). TODO: use iptables on Linux.
function cutServer (conn) {
var addrport = parseHost (conn.host)
cutNetwork (addrport.port)
}
// Ensure server is connected to network (undo cutServer)
// Requires sudo access and ipfw program (Mac OS X and BSD Unix). TODO: use iptables on Linux.
function uncutServer (conn) {
var iport = parseHost (conn.host)
restoreNetwork (iport.port)
}
// Kill server process at other end of this connection
function killServer (conn, _signal) {
var signal = _signal || 15
var iport = parseHost (conn.host)
stopMongod (iport.port, signal)
}
/*** ReplicaSet is the spec of a replica set, ie. options given to ReplicaSetTest.
To start a replica set call 'begin' ***/
// new ReplicaSet :: String -> Int -> FreshPorts ReplicaSet
function ReplicaSet (name, numServers) {
this.name = name
this.host = '127.0.0.1'
this.nodes = numServers
this.startPort = nextPort
this.oplogSize = 40
nextPort += numServers
}
// Start a replica set with this spec and return ReplSetTest, which hold connections to the servers including the master server. Call ReplicaSetTest.stopSet() to end all servers
// ReplicaSet -> IO ReplicaSetTest
ReplicaSet.prototype.begin = function() {
var rs = new ReplSetTest(this)
rs.startSet()
rs.initiate()
rs.awaitReplication()
return rs
}
// Create a new server and add it to replica set
// ReplicaSetTest -> IO Connection
ReplSetTest.prototype.addServer = function() {
var conn = this.add()
nextPort++
this.reInitiate()
this.awaitReplication()
assert.soon(function() {
var doc = conn.getDB('admin').isMaster()
return doc['ismaster'] || doc['secondary']
})
return conn
}
/*** ConfigSet is a set of specs (Servers) for sharding config servers.
Supply either the servers or the number of servers desired.
To start the config servers call 'begin' ***/
// new ConfigSet :: [Server] or Int -> FreshPorts ConfigSet
function ConfigSet (configSvrsOrNumSvrs) {
if (typeof configSvrsOrNumSvrs == 'number') {
this.configSvrs = []
for (var i = 0; i < configSvrsOrNumSvrs; i++)
this.configSvrs.push (new Server ('config'))
} else
this.configSvrs = configSvrs
}
// Start config servers, return list of connections to them
// ConfigSet -> IO [Connection]
ConfigSet.prototype.begin = function() {
return map (function(s) {return s.begin()}, this.configSvrs)
}
// Stop config servers
// ConfigSet -> IO ()
ConfigSet.prototype.end = function() {
return map (function(s) {return s.end()}, this.configSvrs)
}
/*** Router is the spec for a mongos, ie, its command line options.
To start a router (mongos) call 'begin' ***/
// new Router :: ConfigSet -> FreshPorts Router
function Router (configSet) {
this.port = nextPort++
this.v = 0
this.configdb = map (function(s) {return s.host()}, configSet.configSvrs) .join(',')
this.chunkSize = 1
}
// Start router (mongos) with this spec and return connection to it
// Router -> IO Connection
Router.prototype.begin = function() {
return startMongos (this)
}
// Stop router
// Router -> IO ()
Router.prototype.end = function() {
return stopMongoProgram (this.port)
}
// Add shard to config via router (mongos) connection. Shard is either a replSet name (replSet.getURL()) or single server (server.host)
// Connection -> String -> IO ()
function addShard (routerConn, repSetOrHostName) {
var ack = routerConn.getDB('admin').runCommand ({addshard: repSetOrHostName})
assert (ack['ok'], tojson(ack))
}
// Connection -> String -> IO ()
function enableSharding (routerConn, dbName) {
var ack = routerConn.getDB('admin').runCommand ({enablesharding: dbName})
assert (ack['ok'], tojson(ack))
}
// Connection -> String -> String -> String -> IO ()
function shardCollection (routerConn, dbName, collName, shardKey) {
var ack = routerConn.getDB('admin').runCommand ({shardcollection: dbName + '.' + collName, key: shardKey})
assert (ack['ok'], tojson(ack))
}
// Move db from its current primary shard to given shard. Shard is either a replSet name (replSet.getURL()) or single server (server.host)
// Connection -> String -> String -> IO ()
function moveDB (routerConn, dbname, repSetOrHostName) {
var ack = routerConn.getDB('admin').runCommand ({moveprimary: dbname, to: repSetOrHostName})
printjson(ack)
assert (ack['ok'], tojson(ack))
}
|