github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/db/dbgateway.go (about) 1 package db 2 3 import ( 4 "crypto/tls" 5 "net" 6 "sync" 7 "time" 8 9 "github.com/evergreen-ci/evergreen" 10 "gopkg.in/mgo.v2" 11 ) 12 13 var ( 14 globalSessionProvider SessionProvider = nil 15 defaultDialTimeout = 5 * time.Second 16 defaultSocketTimeout = 90 * time.Second 17 ) 18 19 // SessionFactory contains information for connecting to Evergreen's 20 // MongoDB instance. Implements SessionProvider. 21 type SessionFactory struct { 22 url string 23 db string 24 ssl bool 25 dialTimeout time.Duration 26 socketTimeout time.Duration 27 safety mgo.Safe 28 dialLock sync.Mutex 29 masterSession *mgo.Session 30 } 31 32 // SessionProvider returns mgo Sessions for database interaction. 33 type SessionProvider interface { 34 GetSession() (*mgo.Session, *mgo.Database, error) 35 } 36 37 // SessionFactoryFromConfig creates a usable SessionFactory from 38 // the Evergreen settings. 39 func SessionFactoryFromConfig(settings *evergreen.Settings) *SessionFactory { 40 safety := mgo.Safe{} 41 safety.W = settings.Database.WriteConcernSettings.W 42 safety.WMode = settings.Database.WriteConcernSettings.WMode 43 safety.WTimeout = settings.Database.WriteConcernSettings.WTimeout 44 safety.FSync = settings.Database.WriteConcernSettings.FSync 45 safety.J = settings.Database.WriteConcernSettings.J 46 return NewSessionFactory(settings.Database.Url, settings.Database.DB, settings.Database.SSL, safety, defaultDialTimeout) 47 } 48 49 // NewSessionFactory returns a new session factory pointed at the given URL/DB combo, 50 // with the supplied timeout and writeconcern settings. 51 func NewSessionFactory(url, db string, ssl bool, safety mgo.Safe, dialTimeout time.Duration) *SessionFactory { 52 return &SessionFactory{ 53 url: url, 54 db: db, 55 ssl: ssl, 56 dialTimeout: dialTimeout, 57 socketTimeout: defaultSocketTimeout, 58 safety: safety, 59 } 60 } 61 62 func (sf *SessionFactory) GetSession() (*mgo.Session, *mgo.Database, error) { 63 // if the master session has not been initialized, do that for the first time 64 if sf.masterSession == nil { 65 sf.dialLock.Lock() 66 defer sf.dialLock.Unlock() 67 if sf.masterSession == nil { //check again in case someone else just set and unlocked it 68 dialInfo, err := mgo.ParseURL(sf.url) 69 if err != nil { 70 return nil, nil, err 71 } 72 dialInfo.Timeout = sf.dialTimeout 73 74 if sf.ssl { 75 tlsConfig := &tls.Config{} 76 // Note: this turns off certificate validation. TODO: load system certs and/or 77 // allow the user to specify their own CA certs file 78 tlsConfig.InsecureSkipVerify = true 79 dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) { 80 conn, err := tls.Dial("tcp", addr.String(), tlsConfig) 81 return conn, err 82 } 83 } 84 85 sf.masterSession, err = mgo.DialWithInfo(dialInfo) 86 if err != nil { 87 return nil, nil, err 88 } 89 sf.masterSession.SetSocketTimeout(sf.socketTimeout) 90 sf.masterSession.SetSafe(&sf.safety) 91 } 92 } 93 94 // copy the master session 95 sessionCopy := sf.masterSession.Copy() 96 return sessionCopy, sessionCopy.DB(sf.db), nil 97 } 98 99 // SetGlobalSessionProvider sets the global session provider. 100 func SetGlobalSessionProvider(sessionProvider SessionProvider) { 101 globalSessionProvider = sessionProvider 102 } 103 104 // GetGlobalSessionFactory returns the global session provider. 105 func GetGlobalSessionFactory() SessionProvider { 106 if globalSessionProvider == nil { 107 panic("No global session provider has been set.") 108 } 109 return globalSessionProvider 110 }