PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/labix.org/v2/mgo/socket.go

http://github.com/bradfitz/camlistore
Go | 655 lines | 517 code | 77 blank | 61 comment | 101 complexity | 1b311b1161293507ddca9e87e915e904 MD5 | raw file
Possible License(s): CC0-1.0, MIT, BSD-3-Clause, 0BSD, MPL-2.0-no-copyleft-exception, BSD-2-Clause, Apache-2.0
  1. // mgo - MongoDB driver for Go
  2. //
  3. // Copyright (c) 2010-2012 - Gustavo Niemeyer <gustavo@niemeyer.net>
  4. //
  5. // All rights reserved.
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are met:
  9. //
  10. // 1. Redistributions of source code must retain the above copyright notice, this
  11. // list of conditions and the following disclaimer.
  12. // 2. Redistributions in binary form must reproduce the above copyright notice,
  13. // this list of conditions and the following disclaimer in the documentation
  14. // and/or other materials provided with the distribution.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  20. // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. package mgo
  27. import (
  28. "errors"
  29. "labix.org/v2/mgo/bson"
  30. "net"
  31. "sync"
  32. "time"
  33. )
  34. type replyFunc func(err error, reply *replyOp, docNum int, docData []byte)
  35. type mongoSocket struct {
  36. sync.Mutex
  37. server *mongoServer // nil when cached
  38. conn net.Conn
  39. timeout time.Duration
  40. addr string // For debugging only.
  41. nextRequestId uint32
  42. replyFuncs map[uint32]replyFunc
  43. references int
  44. auth []authInfo
  45. logout []authInfo
  46. cachedNonce string
  47. gotNonce sync.Cond
  48. dead error
  49. serverInfo *mongoServerInfo
  50. }
  51. type queryOpFlags uint32
  52. const (
  53. _ queryOpFlags = 1 << iota
  54. flagTailable
  55. flagSlaveOk
  56. flagLogReplay
  57. flagNoCursorTimeout
  58. flagAwaitData
  59. )
  60. type queryOp struct {
  61. collection string
  62. query interface{}
  63. skip int32
  64. limit int32
  65. selector interface{}
  66. flags queryOpFlags
  67. replyFunc replyFunc
  68. options queryWrapper
  69. hasOptions bool
  70. serverTags []bson.D
  71. }
  72. type queryWrapper struct {
  73. Query interface{} "$query"
  74. OrderBy interface{} "$orderby,omitempty"
  75. Hint interface{} "$hint,omitempty"
  76. Explain bool "$explain,omitempty"
  77. Snapshot bool "$snapshot,omitempty"
  78. ReadPreference bson.D "$readPreference,omitempty"
  79. }
  80. func (op *queryOp) finalQuery(socket *mongoSocket) interface{} {
  81. if op.flags&flagSlaveOk != 0 && len(op.serverTags) > 0 && socket.ServerInfo().Mongos {
  82. op.hasOptions = true
  83. op.options.ReadPreference = bson.D{{"mode", "secondaryPreferred"}, {"tags", op.serverTags}}
  84. }
  85. if op.hasOptions {
  86. if op.query == nil {
  87. var empty bson.D
  88. op.options.Query = empty
  89. } else {
  90. op.options.Query = op.query
  91. }
  92. debugf("final query is %#v\n", &op.options)
  93. return &op.options
  94. }
  95. return op.query
  96. }
  97. type getMoreOp struct {
  98. collection string
  99. limit int32
  100. cursorId int64
  101. replyFunc replyFunc
  102. }
  103. type replyOp struct {
  104. flags uint32
  105. cursorId int64
  106. firstDoc int32
  107. replyDocs int32
  108. }
  109. type insertOp struct {
  110. collection string // "database.collection"
  111. documents []interface{} // One or more documents to insert
  112. }
  113. type updateOp struct {
  114. collection string // "database.collection"
  115. selector interface{}
  116. update interface{}
  117. flags uint32
  118. }
  119. type deleteOp struct {
  120. collection string // "database.collection"
  121. selector interface{}
  122. flags uint32
  123. }
  124. type killCursorsOp struct {
  125. cursorIds []int64
  126. }
  127. type requestInfo struct {
  128. bufferPos int
  129. replyFunc replyFunc
  130. }
  131. func newSocket(server *mongoServer, conn net.Conn, timeout time.Duration) *mongoSocket {
  132. socket := &mongoSocket{
  133. conn: conn,
  134. addr: server.Addr,
  135. server: server,
  136. replyFuncs: make(map[uint32]replyFunc),
  137. }
  138. socket.gotNonce.L = &socket.Mutex
  139. if err := socket.InitialAcquire(server.Info(), timeout); err != nil {
  140. panic("newSocket: InitialAcquire returned error: " + err.Error())
  141. }
  142. stats.socketsAlive(+1)
  143. debugf("Socket %p to %s: initialized", socket, socket.addr)
  144. socket.resetNonce()
  145. go socket.readLoop()
  146. return socket
  147. }
  148. // Server returns the server that the socket is associated with.
  149. // It returns nil while the socket is cached in its respective server.
  150. func (socket *mongoSocket) Server() *mongoServer {
  151. socket.Lock()
  152. server := socket.server
  153. socket.Unlock()
  154. return server
  155. }
  156. // ServerInfo returns details for the server at the time the socket
  157. // was initially acquired.
  158. func (socket *mongoSocket) ServerInfo() *mongoServerInfo {
  159. socket.Lock()
  160. serverInfo := socket.serverInfo
  161. socket.Unlock()
  162. return serverInfo
  163. }
  164. // InitialAcquire obtains the first reference to the socket, either
  165. // right after the connection is made or once a recycled socket is
  166. // being put back in use.
  167. func (socket *mongoSocket) InitialAcquire(serverInfo *mongoServerInfo, timeout time.Duration) error {
  168. socket.Lock()
  169. if socket.references > 0 {
  170. panic("Socket acquired out of cache with references")
  171. }
  172. if socket.dead != nil {
  173. socket.Unlock()
  174. return socket.dead
  175. }
  176. socket.references++
  177. socket.serverInfo = serverInfo
  178. socket.timeout = timeout
  179. stats.socketsInUse(+1)
  180. stats.socketRefs(+1)
  181. socket.Unlock()
  182. return nil
  183. }
  184. // Acquire obtains an additional reference to the socket.
  185. // The socket will only be recycled when it's released as many
  186. // times as it's been acquired.
  187. func (socket *mongoSocket) Acquire() (info *mongoServerInfo) {
  188. socket.Lock()
  189. if socket.references == 0 {
  190. panic("Socket got non-initial acquire with references == 0")
  191. }
  192. // We'll track references to dead sockets as well.
  193. // Caller is still supposed to release the socket.
  194. socket.references++
  195. stats.socketRefs(+1)
  196. serverInfo := socket.serverInfo
  197. socket.Unlock()
  198. return serverInfo
  199. }
  200. // Release decrements a socket reference. The socket will be
  201. // recycled once its released as many times as it's been acquired.
  202. func (socket *mongoSocket) Release() {
  203. socket.Lock()
  204. if socket.references == 0 {
  205. panic("socket.Release() with references == 0")
  206. }
  207. socket.references--
  208. stats.socketRefs(-1)
  209. if socket.references == 0 {
  210. stats.socketsInUse(-1)
  211. server := socket.server
  212. socket.Unlock()
  213. socket.LogoutAll()
  214. // If the socket is dead server is nil.
  215. if server != nil {
  216. server.RecycleSocket(socket)
  217. }
  218. } else {
  219. socket.Unlock()
  220. }
  221. }
  222. // SetTimeout changes the timeout used on socket operations.
  223. func (socket *mongoSocket) SetTimeout(d time.Duration) {
  224. socket.Lock()
  225. socket.timeout = d
  226. socket.Unlock()
  227. }
  228. type deadlineType int
  229. const (
  230. readDeadline deadlineType = 1
  231. writeDeadline deadlineType = 2
  232. )
  233. func (socket *mongoSocket) updateDeadline(which deadlineType) {
  234. var when time.Time
  235. if socket.timeout > 0 {
  236. when = time.Now().Add(socket.timeout)
  237. }
  238. whichstr := ""
  239. switch which {
  240. case readDeadline | writeDeadline:
  241. whichstr = "read/write"
  242. socket.conn.SetDeadline(when)
  243. case readDeadline:
  244. whichstr = "read"
  245. socket.conn.SetReadDeadline(when)
  246. case writeDeadline:
  247. whichstr = "write"
  248. socket.conn.SetWriteDeadline(when)
  249. default:
  250. panic("invalid parameter to updateDeadline")
  251. }
  252. debugf("Socket %p to %s: updated %s deadline to %s ahead (%s)", socket, socket.addr, whichstr, socket.timeout, when)
  253. }
  254. // Close terminates the socket use.
  255. func (socket *mongoSocket) Close() {
  256. socket.kill(errors.New("Closed explicitly"), false)
  257. }
  258. func (socket *mongoSocket) kill(err error, abend bool) {
  259. socket.Lock()
  260. if socket.dead != nil {
  261. debugf("Socket %p to %s: killed again: %s (previously: %s)", socket, socket.addr, err.Error(), socket.dead.Error())
  262. socket.Unlock()
  263. return
  264. }
  265. logf("Socket %p to %s: closing: %s (abend=%v)", socket, socket.addr, err.Error(), abend)
  266. socket.dead = err
  267. socket.conn.Close()
  268. stats.socketsAlive(-1)
  269. replyFuncs := socket.replyFuncs
  270. socket.replyFuncs = make(map[uint32]replyFunc)
  271. server := socket.server
  272. socket.server = nil
  273. socket.Unlock()
  274. for _, f := range replyFuncs {
  275. logf("Socket %p to %s: notifying replyFunc of closed socket: %s", socket, socket.addr, err.Error())
  276. f(err, nil, -1, nil)
  277. }
  278. if abend {
  279. server.AbendSocket(socket)
  280. }
  281. }
  282. func (socket *mongoSocket) SimpleQuery(op *queryOp) (data []byte, err error) {
  283. var mutex sync.Mutex
  284. var replyData []byte
  285. var replyErr error
  286. mutex.Lock()
  287. op.replyFunc = func(err error, reply *replyOp, docNum int, docData []byte) {
  288. replyData = docData
  289. replyErr = err
  290. mutex.Unlock()
  291. }
  292. err = socket.Query(op)
  293. if err != nil {
  294. return nil, err
  295. }
  296. mutex.Lock() // Wait.
  297. if replyErr != nil {
  298. return nil, replyErr
  299. }
  300. return replyData, nil
  301. }
  302. func (socket *mongoSocket) Query(ops ...interface{}) (err error) {
  303. if lops := socket.flushLogout(); len(lops) > 0 {
  304. ops = append(lops, ops...)
  305. }
  306. buf := make([]byte, 0, 256)
  307. // Serialize operations synchronously to avoid interrupting
  308. // other goroutines while we can't really be sending data.
  309. // Also, record id positions so that we can compute request
  310. // ids at once later with the lock already held.
  311. requests := make([]requestInfo, len(ops))
  312. requestCount := 0
  313. for _, op := range ops {
  314. debugf("Socket %p to %s: serializing op: %#v", socket, socket.addr, op)
  315. start := len(buf)
  316. var replyFunc replyFunc
  317. switch op := op.(type) {
  318. case *updateOp:
  319. buf = addHeader(buf, 2001)
  320. buf = addInt32(buf, 0) // Reserved
  321. buf = addCString(buf, op.collection)
  322. buf = addInt32(buf, int32(op.flags))
  323. debugf("Socket %p to %s: serializing selector document: %#v", socket, socket.addr, op.selector)
  324. buf, err = addBSON(buf, op.selector)
  325. if err != nil {
  326. return err
  327. }
  328. debugf("Socket %p to %s: serializing update document: %#v", socket, socket.addr, op.update)
  329. buf, err = addBSON(buf, op.update)
  330. if err != nil {
  331. return err
  332. }
  333. case *insertOp:
  334. buf = addHeader(buf, 2002)
  335. buf = addInt32(buf, 0) // Reserved
  336. buf = addCString(buf, op.collection)
  337. for _, doc := range op.documents {
  338. debugf("Socket %p to %s: serializing document for insertion: %#v", socket, socket.addr, doc)
  339. buf, err = addBSON(buf, doc)
  340. if err != nil {
  341. return err
  342. }
  343. }
  344. case *queryOp:
  345. buf = addHeader(buf, 2004)
  346. buf = addInt32(buf, int32(op.flags))
  347. buf = addCString(buf, op.collection)
  348. buf = addInt32(buf, op.skip)
  349. buf = addInt32(buf, op.limit)
  350. buf, err = addBSON(buf, op.finalQuery(socket))
  351. if err != nil {
  352. return err
  353. }
  354. if op.selector != nil {
  355. buf, err = addBSON(buf, op.selector)
  356. if err != nil {
  357. return err
  358. }
  359. }
  360. replyFunc = op.replyFunc
  361. case *getMoreOp:
  362. buf = addHeader(buf, 2005)
  363. buf = addInt32(buf, 0) // Reserved
  364. buf = addCString(buf, op.collection)
  365. buf = addInt32(buf, op.limit)
  366. buf = addInt64(buf, op.cursorId)
  367. replyFunc = op.replyFunc
  368. case *deleteOp:
  369. buf = addHeader(buf, 2006)
  370. buf = addInt32(buf, 0) // Reserved
  371. buf = addCString(buf, op.collection)
  372. buf = addInt32(buf, int32(op.flags))
  373. debugf("Socket %p to %s: serializing selector document: %#v", socket, socket.addr, op.selector)
  374. buf, err = addBSON(buf, op.selector)
  375. if err != nil {
  376. return err
  377. }
  378. case *killCursorsOp:
  379. buf = addHeader(buf, 2007)
  380. buf = addInt32(buf, 0) // Reserved
  381. buf = addInt32(buf, int32(len(op.cursorIds)))
  382. for _, cursorId := range op.cursorIds {
  383. buf = addInt64(buf, cursorId)
  384. }
  385. default:
  386. panic("Internal error: unknown operation type")
  387. }
  388. setInt32(buf, start, int32(len(buf)-start))
  389. if replyFunc != nil {
  390. request := &requests[requestCount]
  391. request.replyFunc = replyFunc
  392. request.bufferPos = start
  393. requestCount++
  394. }
  395. }
  396. // Buffer is ready for the pipe. Lock, allocate ids, and enqueue.
  397. socket.Lock()
  398. if socket.dead != nil {
  399. socket.Unlock()
  400. debugf("Socket %p to %s: failing query, already closed: %s", socket, socket.addr, socket.dead.Error())
  401. // XXX This seems necessary in case the session is closed concurrently
  402. // with a query being performed, but it's not yet tested:
  403. for i := 0; i != requestCount; i++ {
  404. request := &requests[i]
  405. if request.replyFunc != nil {
  406. request.replyFunc(socket.dead, nil, -1, nil)
  407. }
  408. }
  409. return socket.dead
  410. }
  411. wasWaiting := len(socket.replyFuncs) > 0
  412. // Reserve id 0 for requests which should have no responses.
  413. requestId := socket.nextRequestId + 1
  414. if requestId == 0 {
  415. requestId++
  416. }
  417. socket.nextRequestId = requestId + uint32(requestCount)
  418. for i := 0; i != requestCount; i++ {
  419. request := &requests[i]
  420. setInt32(buf, request.bufferPos+4, int32(requestId))
  421. socket.replyFuncs[requestId] = request.replyFunc
  422. requestId++
  423. }
  424. debugf("Socket %p to %s: sending %d op(s) (%d bytes)", socket, socket.addr, len(ops), len(buf))
  425. stats.sentOps(len(ops))
  426. socket.updateDeadline(writeDeadline)
  427. _, err = socket.conn.Write(buf)
  428. if !wasWaiting && requestCount > 0 {
  429. socket.updateDeadline(readDeadline)
  430. }
  431. socket.Unlock()
  432. return err
  433. }
  434. func fill(r net.Conn, b []byte) error {
  435. l := len(b)
  436. n, err := r.Read(b)
  437. for n != l && err == nil {
  438. var ni int
  439. ni, err = r.Read(b[n:])
  440. n += ni
  441. }
  442. return err
  443. }
  444. // Estimated minimum cost per socket: 1 goroutine + memory for the largest
  445. // document ever seen.
  446. func (socket *mongoSocket) readLoop() {
  447. p := make([]byte, 36) // 16 from header + 20 from OP_REPLY fixed fields
  448. s := make([]byte, 4)
  449. conn := socket.conn // No locking, conn never changes.
  450. for {
  451. // XXX Handle timeouts, , etc
  452. err := fill(conn, p)
  453. if err != nil {
  454. socket.kill(err, true)
  455. return
  456. }
  457. totalLen := getInt32(p, 0)
  458. responseTo := getInt32(p, 8)
  459. opCode := getInt32(p, 12)
  460. // Don't use socket.server.Addr here. socket is not
  461. // locked and socket.server may go away.
  462. debugf("Socket %p to %s: got reply (%d bytes)", socket, socket.addr, totalLen)
  463. _ = totalLen
  464. if opCode != 1 {
  465. socket.kill(errors.New("opcode != 1, corrupted data?"), true)
  466. return
  467. }
  468. reply := replyOp{
  469. flags: uint32(getInt32(p, 16)),
  470. cursorId: getInt64(p, 20),
  471. firstDoc: getInt32(p, 28),
  472. replyDocs: getInt32(p, 32),
  473. }
  474. stats.receivedOps(+1)
  475. stats.receivedDocs(int(reply.replyDocs))
  476. socket.Lock()
  477. replyFunc, replyFuncFound := socket.replyFuncs[uint32(responseTo)]
  478. socket.Unlock()
  479. if replyFunc != nil && reply.replyDocs == 0 {
  480. replyFunc(nil, &reply, -1, nil)
  481. } else {
  482. for i := 0; i != int(reply.replyDocs); i++ {
  483. err := fill(conn, s)
  484. if err != nil {
  485. socket.kill(err, true)
  486. return
  487. }
  488. b := make([]byte, int(getInt32(s, 0)))
  489. // copy(b, s) in an efficient way.
  490. b[0] = s[0]
  491. b[1] = s[1]
  492. b[2] = s[2]
  493. b[3] = s[3]
  494. err = fill(conn, b[4:])
  495. if err != nil {
  496. socket.kill(err, true)
  497. return
  498. }
  499. if globalDebug && globalLogger != nil {
  500. m := bson.M{}
  501. if err := bson.Unmarshal(b, m); err == nil {
  502. debugf("Socket %p to %s: received document: %#v", socket, socket.addr, m)
  503. }
  504. }
  505. if replyFunc != nil {
  506. replyFunc(nil, &reply, i, b)
  507. }
  508. // XXX Do bound checking against totalLen.
  509. }
  510. }
  511. // Only remove replyFunc after iteration, so that kill() will see it.
  512. socket.Lock()
  513. if replyFuncFound {
  514. delete(socket.replyFuncs, uint32(responseTo))
  515. }
  516. if len(socket.replyFuncs) == 0 {
  517. // Nothing else to read for now. Disable deadline.
  518. socket.conn.SetReadDeadline(time.Time{})
  519. } else {
  520. socket.updateDeadline(readDeadline)
  521. }
  522. socket.Unlock()
  523. // XXX Do bound checking against totalLen.
  524. }
  525. }
  526. var emptyHeader = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  527. func addHeader(b []byte, opcode int) []byte {
  528. i := len(b)
  529. b = append(b, emptyHeader...)
  530. // Enough for current opcodes.
  531. b[i+12] = byte(opcode)
  532. b[i+13] = byte(opcode >> 8)
  533. return b
  534. }
  535. func addInt32(b []byte, i int32) []byte {
  536. return append(b, byte(i), byte(i>>8), byte(i>>16), byte(i>>24))
  537. }
  538. func addInt64(b []byte, i int64) []byte {
  539. return append(b, byte(i), byte(i>>8), byte(i>>16), byte(i>>24),
  540. byte(i>>32), byte(i>>40), byte(i>>48), byte(i>>56))
  541. }
  542. func addCString(b []byte, s string) []byte {
  543. b = append(b, []byte(s)...)
  544. b = append(b, 0)
  545. return b
  546. }
  547. func addBSON(b []byte, doc interface{}) ([]byte, error) {
  548. if doc == nil {
  549. return append(b, 5, 0, 0, 0, 0), nil
  550. }
  551. data, err := bson.Marshal(doc)
  552. if err != nil {
  553. return b, err
  554. }
  555. return append(b, data...), nil
  556. }
  557. func setInt32(b []byte, pos int, i int32) {
  558. b[pos] = byte(i)
  559. b[pos+1] = byte(i >> 8)
  560. b[pos+2] = byte(i >> 16)
  561. b[pos+3] = byte(i >> 24)
  562. }
  563. func getInt32(b []byte, pos int) int32 {
  564. return (int32(b[pos+0])) |
  565. (int32(b[pos+1]) << 8) |
  566. (int32(b[pos+2]) << 16) |
  567. (int32(b[pos+3]) << 24)
  568. }
  569. func getInt64(b []byte, pos int) int64 {
  570. return (int64(b[pos+0])) |
  571. (int64(b[pos+1]) << 8) |
  572. (int64(b[pos+2]) << 16) |
  573. (int64(b[pos+3]) << 24) |
  574. (int64(b[pos+4]) << 32) |
  575. (int64(b[pos+5]) << 40) |
  576. (int64(b[pos+6]) << 48) |
  577. (int64(b[pos+7]) << 56)
  578. }