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  }