seba-365 - implemented dep
Change-Id: Ia6226d50e7615935a0c8876809a687427ff88c22
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/session_pool.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/session_pool.go
new file mode 100644
index 0000000..af749da
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/session_pool.go
@@ -0,0 +1,175 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package session
+
+import (
+ "sync"
+
+ "github.com/mongodb/mongo-go-driver/x/bsonx"
+ "github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// Node represents a server session in a linked list
+type Node struct {
+ *Server
+ next *Node
+ prev *Node
+}
+
+// Pool is a pool of server sessions that can be reused.
+type Pool struct {
+ descChan <-chan description.Topology
+ head *Node
+ tail *Node
+ timeout uint32
+ mutex sync.Mutex // mutex to protect list and sessionTimeout
+
+ checkedOut int // number of sessions checked out of pool
+}
+
+func (p *Pool) createServerSession() (*Server, error) {
+ s, err := newServerSession()
+ if err != nil {
+ return nil, err
+ }
+
+ p.checkedOut++
+ return s, nil
+}
+
+// NewPool creates a new server session pool
+func NewPool(descChan <-chan description.Topology) *Pool {
+ p := &Pool{
+ descChan: descChan,
+ }
+
+ return p
+}
+
+// assumes caller has mutex to protect the pool
+func (p *Pool) updateTimeout() {
+ select {
+ case newDesc := <-p.descChan:
+ p.timeout = newDesc.SessionTimeoutMinutes
+ default:
+ // no new description waiting
+ }
+}
+
+// GetSession retrieves an unexpired session from the pool.
+func (p *Pool) GetSession() (*Server, error) {
+ p.mutex.Lock() // prevent changing the linked list while seeing if sessions have expired
+ defer p.mutex.Unlock()
+
+ // empty pool
+ if p.head == nil && p.tail == nil {
+ return p.createServerSession()
+ }
+
+ p.updateTimeout()
+ for p.head != nil {
+ // pull session from head of queue and return if it is valid for at least 1 more minute
+ if p.head.expired(p.timeout) {
+ p.head = p.head.next
+ continue
+ }
+
+ // found unexpired session
+ session := p.head.Server
+ if p.head.next != nil {
+ p.head.next.prev = nil
+ }
+ if p.tail == p.head {
+ p.tail = nil
+ p.head = nil
+ } else {
+ p.head = p.head.next
+ }
+
+ p.checkedOut++
+ return session, nil
+ }
+
+ // no valid session found
+ p.tail = nil // empty list
+ return p.createServerSession()
+}
+
+// ReturnSession returns a session to the pool if it has not expired.
+func (p *Pool) ReturnSession(ss *Server) {
+ if ss == nil {
+ return
+ }
+
+ p.mutex.Lock()
+ defer p.mutex.Unlock()
+
+ p.checkedOut--
+ p.updateTimeout()
+ // check sessions at end of queue for expired
+ // stop checking after hitting the first valid session
+ for p.tail != nil && p.tail.expired(p.timeout) {
+ if p.tail.prev != nil {
+ p.tail.prev.next = nil
+ }
+ p.tail = p.tail.prev
+ }
+
+ // session expired
+ if ss.expired(p.timeout) {
+ return
+ }
+
+ newNode := &Node{
+ Server: ss,
+ next: nil,
+ prev: nil,
+ }
+
+ // empty list
+ if p.tail == nil {
+ p.head = newNode
+ p.tail = newNode
+ return
+ }
+
+ // at least 1 valid session in list
+ newNode.next = p.head
+ p.head.prev = newNode
+ p.head = newNode
+}
+
+// IDSlice returns a slice of session IDs for each session in the pool
+func (p *Pool) IDSlice() []bsonx.Doc {
+ p.mutex.Lock()
+ defer p.mutex.Unlock()
+
+ ids := []bsonx.Doc{}
+ for node := p.head; node != nil; node = node.next {
+ ids = append(ids, node.SessionID)
+ }
+
+ return ids
+}
+
+// String implements the Stringer interface
+func (p *Pool) String() string {
+ p.mutex.Lock()
+ defer p.mutex.Unlock()
+
+ s := ""
+ for head := p.head; head != nil; head = head.next {
+ s += head.SessionID.String() + "\n"
+ }
+
+ return s
+}
+
+// CheckedOut returns number of sessions checked out from pool.
+func (p *Pool) CheckedOut() int {
+ return p.checkedOut
+}