github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/gopkg.in/mgo.v2/session.go (about)

     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  
    27  package mgo
    28  
    29  import (
    30  	"crypto/md5"
    31  	"encoding/hex"
    32  	"errors"
    33  	"fmt"
    34  	"math"
    35  	"net"
    36  	"net/url"
    37  	"reflect"
    38  	"sort"
    39  	"strconv"
    40  	"strings"
    41  	"sync"
    42  	"time"
    43  
    44  	"gopkg.in/mgo.v2/bson"
    45  )
    46  
    47  type Mode int
    48  
    49  const (
    50  	// Relevant documentation on read preference modes:
    51  	//
    52  	//     http://docs.mongodb.org/manual/reference/read-preference/
    53  	//
    54  	Primary            Mode = 2 // Default mode. All operations read from the current replica set primary.
    55  	PrimaryPreferred   Mode = 3 // Read from the primary if available. Read from the secondary otherwise.
    56  	Secondary          Mode = 4 // Read from one of the nearest secondary members of the replica set.
    57  	SecondaryPreferred Mode = 5 // Read from one of the nearest secondaries if available. Read from primary otherwise.
    58  	Nearest            Mode = 6 // Read from one of the nearest members, irrespective of it being primary or secondary.
    59  
    60  	// Read preference modes are specific to mgo:
    61  	Eventual  Mode = 0 // Same as Nearest, but may change servers between reads.
    62  	Monotonic Mode = 1 // Same as SecondaryPreferred before first write. Same as Primary after first write.
    63  	Strong    Mode = 2 // Same as Primary.
    64  )
    65  
    66  // mgo.v3: Drop Strong mode, suffix all modes with "Mode".
    67  
    68  // When changing the Session type, check if newSession and copySession
    69  // need to be updated too.
    70  
    71  // Session represents a communication session with the database.
    72  //
    73  // All Session methods are concurrency-safe and may be called from multiple
    74  // goroutines. In all session modes but Eventual, using the session from
    75  // multiple goroutines will cause them to share the same underlying socket.
    76  // See the documentation on Session.SetMode for more details.
    77  type Session struct {
    78  	m                sync.RWMutex
    79  	cluster_         *mongoCluster
    80  	slaveSocket      *mongoSocket
    81  	masterSocket     *mongoSocket
    82  	slaveOk          bool
    83  	consistency      Mode
    84  	queryConfig      query
    85  	safeOp           *queryOp
    86  	syncTimeout      time.Duration
    87  	sockTimeout      time.Duration
    88  	defaultdb        string
    89  	sourcedb         string
    90  	dialCred         *Credential
    91  	creds            []Credential
    92  	poolLimit        int
    93  	bypassValidation bool
    94  }
    95  
    96  type Database struct {
    97  	Session *Session
    98  	Name    string
    99  }
   100  
   101  type Collection struct {
   102  	Database *Database
   103  	Name     string // "collection"
   104  	FullName string // "db.collection"
   105  }
   106  
   107  type Query struct {
   108  	m       sync.Mutex
   109  	session *Session
   110  	query   // Enables default settings in session.
   111  }
   112  
   113  type query struct {
   114  	op       queryOp
   115  	prefetch float64
   116  	limit    int32
   117  }
   118  
   119  type getLastError struct {
   120  	CmdName  int         "getLastError,omitempty"
   121  	W        interface{} "w,omitempty"
   122  	WTimeout int         "wtimeout,omitempty"
   123  	FSync    bool        "fsync,omitempty"
   124  	J        bool        "j,omitempty"
   125  }
   126  
   127  type Iter struct {
   128  	m              sync.Mutex
   129  	gotReply       sync.Cond
   130  	session        *Session
   131  	server         *mongoServer
   132  	docData        queue
   133  	err            error
   134  	op             getMoreOp
   135  	prefetch       float64
   136  	limit          int32
   137  	docsToReceive  int
   138  	docsBeforeMore int
   139  	timeout        time.Duration
   140  	timedout       bool
   141  	findCmd        bool
   142  }
   143  
   144  var (
   145  	ErrNotFound = errors.New("not found")
   146  	ErrCursor   = errors.New("invalid cursor")
   147  )
   148  
   149  const (
   150  	defaultPrefetch  = 0.25
   151  	maxUpsertRetries = 5
   152  )
   153  
   154  // Dial establishes a new session to the cluster identified by the given seed
   155  // server(s). The session will enable communication with all of the servers in
   156  // the cluster, so the seed servers are used only to find out about the cluster
   157  // topology.
   158  //
   159  // Dial will timeout after 10 seconds if a server isn't reached. The returned
   160  // session will timeout operations after one minute by default if servers
   161  // aren't available. To customize the timeout, see DialWithTimeout,
   162  // SetSyncTimeout, and SetSocketTimeout.
   163  //
   164  // This method is generally called just once for a given cluster.  Further
   165  // sessions to the same cluster are then established using the New or Copy
   166  // methods on the obtained session. This will make them share the underlying
   167  // cluster, and manage the pool of connections appropriately.
   168  //
   169  // Once the session is not useful anymore, Close must be called to release the
   170  // resources appropriately.
   171  //
   172  // The seed servers must be provided in the following format:
   173  //
   174  //     [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]
   175  //
   176  // For example, it may be as simple as:
   177  //
   178  //     localhost
   179  //
   180  // Or more involved like:
   181  //
   182  //     mongodb://myuser:mypass@localhost:40001,otherhost:40001/mydb
   183  //
   184  // If the port number is not provided for a server, it defaults to 27017.
   185  //
   186  // The username and password provided in the URL will be used to authenticate
   187  // into the database named after the slash at the end of the host names, or
   188  // into the "admin" database if none is provided.  The authentication information
   189  // will persist in sessions obtained through the New method as well.
   190  //
   191  // The following connection options are supported after the question mark:
   192  //
   193  //     connect=direct
   194  //
   195  //         Disables the automatic replica set server discovery logic, and
   196  //         forces the use of servers provided only (even if secondaries).
   197  //         Note that to talk to a secondary the consistency requirements
   198  //         must be relaxed to Monotonic or Eventual via SetMode.
   199  //
   200  //
   201  //     connect=replicaSet
   202  //
   203  //  	   Discover replica sets automatically. Default connection behavior.
   204  //
   205  //
   206  //     replicaSet=<setname>
   207  //
   208  //         If specified will prevent the obtained session from communicating
   209  //         with any server which is not part of a replica set with the given name.
   210  //         The default is to communicate with any server specified or discovered
   211  //         via the servers contacted.
   212  //
   213  //
   214  //     authSource=<db>
   215  //
   216  //         Informs the database used to establish credentials and privileges
   217  //         with a MongoDB server. Defaults to the database name provided via
   218  //         the URL path, and "admin" if that's unset.
   219  //
   220  //
   221  //     authMechanism=<mechanism>
   222  //
   223  //        Defines the protocol for credential negotiation. Defaults to "MONGODB-CR",
   224  //        which is the default username/password challenge-response mechanism.
   225  //
   226  //
   227  //     gssapiServiceName=<name>
   228  //
   229  //        Defines the service name to use when authenticating with the GSSAPI
   230  //        mechanism. Defaults to "mongodb".
   231  //
   232  //
   233  //     maxPoolSize=<limit>
   234  //
   235  //        Defines the per-server socket pool limit. Defaults to 4096.
   236  //        See Session.SetPoolLimit for details.
   237  //
   238  //
   239  // Relevant documentation:
   240  //
   241  //     http://docs.mongodb.org/manual/reference/connection-string/
   242  //
   243  func Dial(url string) (*Session, error) {
   244  	session, err := DialWithTimeout(url, 10*time.Second)
   245  	if err == nil {
   246  		session.SetSyncTimeout(1 * time.Minute)
   247  		session.SetSocketTimeout(1 * time.Minute)
   248  	}
   249  	return session, err
   250  }
   251  
   252  // DialWithTimeout works like Dial, but uses timeout as the amount of time to
   253  // wait for a server to respond when first connecting and also on follow up
   254  // operations in the session. If timeout is zero, the call may block
   255  // forever waiting for a connection to be made.
   256  //
   257  // See SetSyncTimeout for customizing the timeout for the session.
   258  func DialWithTimeout(url string, timeout time.Duration) (*Session, error) {
   259  	info, err := ParseURL(url)
   260  	if err != nil {
   261  		return nil, err
   262  	}
   263  	info.Timeout = timeout
   264  	return DialWithInfo(info)
   265  }
   266  
   267  // ParseURL parses a MongoDB URL as accepted by the Dial function and returns
   268  // a value suitable for providing into DialWithInfo.
   269  //
   270  // See Dial for more details on the format of url.
   271  func ParseURL(url string) (*DialInfo, error) {
   272  	uinfo, err := extractURL(url)
   273  	if err != nil {
   274  		return nil, err
   275  	}
   276  	direct := false
   277  	mechanism := ""
   278  	service := ""
   279  	source := ""
   280  	setName := ""
   281  	poolLimit := 0
   282  	for k, v := range uinfo.options {
   283  		switch k {
   284  		case "authSource":
   285  			source = v
   286  		case "authMechanism":
   287  			mechanism = v
   288  		case "gssapiServiceName":
   289  			service = v
   290  		case "replicaSet":
   291  			setName = v
   292  		case "maxPoolSize":
   293  			poolLimit, err = strconv.Atoi(v)
   294  			if err != nil {
   295  				return nil, errors.New("bad value for maxPoolSize: " + v)
   296  			}
   297  		case "connect":
   298  			if v == "direct" {
   299  				direct = true
   300  				break
   301  			}
   302  			if v == "replicaSet" {
   303  				break
   304  			}
   305  			fallthrough
   306  		default:
   307  			return nil, errors.New("unsupported connection URL option: " + k + "=" + v)
   308  		}
   309  	}
   310  	info := DialInfo{
   311  		Addrs:          uinfo.addrs,
   312  		Direct:         direct,
   313  		Database:       uinfo.db,
   314  		Username:       uinfo.user,
   315  		Password:       uinfo.pass,
   316  		Mechanism:      mechanism,
   317  		Service:        service,
   318  		Source:         source,
   319  		PoolLimit:      poolLimit,
   320  		ReplicaSetName: setName,
   321  	}
   322  	return &info, nil
   323  }
   324  
   325  // DialInfo holds options for establishing a session with a MongoDB cluster.
   326  // To use a URL, see the Dial function.
   327  type DialInfo struct {
   328  	// Addrs holds the addresses for the seed servers.
   329  	Addrs []string
   330  
   331  	// Direct informs whether to establish connections only with the
   332  	// specified seed servers, or to obtain information for the whole
   333  	// cluster and establish connections with further servers too.
   334  	Direct bool
   335  
   336  	// Timeout is the amount of time to wait for a server to respond when
   337  	// first connecting and on follow up operations in the session. If
   338  	// timeout is zero, the call may block forever waiting for a connection
   339  	// to be established. Timeout does not affect logic in DialServer.
   340  	Timeout time.Duration
   341  
   342  	// FailFast will cause connection and query attempts to fail faster when
   343  	// the server is unavailable, instead of retrying until the configured
   344  	// timeout period. Note that an unavailable server may silently drop
   345  	// packets instead of rejecting them, in which case it's impossible to
   346  	// distinguish it from a slow server, so the timeout stays relevant.
   347  	FailFast bool
   348  
   349  	// Database is the default database name used when the Session.DB method
   350  	// is called with an empty name, and is also used during the initial
   351  	// authentication if Source is unset.
   352  	Database string
   353  
   354  	// ReplicaSetName, if specified, will prevent the obtained session from
   355  	// communicating with any server which is not part of a replica set
   356  	// with the given name. The default is to communicate with any server
   357  	// specified or discovered via the servers contacted.
   358  	ReplicaSetName string
   359  
   360  	// Source is the database used to establish credentials and privileges
   361  	// with a MongoDB server. Defaults to the value of Database, if that is
   362  	// set, or "admin" otherwise.
   363  	Source string
   364  
   365  	// Service defines the service name to use when authenticating with the GSSAPI
   366  	// mechanism. Defaults to "mongodb".
   367  	Service string
   368  
   369  	// ServiceHost defines which hostname to use when authenticating
   370  	// with the GSSAPI mechanism. If not specified, defaults to the MongoDB
   371  	// server's address.
   372  	ServiceHost string
   373  
   374  	// Mechanism defines the protocol for credential negotiation.
   375  	// Defaults to "MONGODB-CR".
   376  	Mechanism string
   377  
   378  	// Username and Password inform the credentials for the initial authentication
   379  	// done on the database defined by the Source field. See Session.Login.
   380  	Username string
   381  	Password string
   382  
   383  	// PoolLimit defines the per-server socket pool limit. Defaults to 4096.
   384  	// See Session.SetPoolLimit for details.
   385  	PoolLimit int
   386  
   387  	// DialServer optionally specifies the dial function for establishing
   388  	// connections with the MongoDB servers.
   389  	DialServer func(addr *ServerAddr) (net.Conn, error)
   390  
   391  	// WARNING: This field is obsolete. See DialServer above.
   392  	Dial func(addr net.Addr) (net.Conn, error)
   393  }
   394  
   395  // mgo.v3: Drop DialInfo.Dial.
   396  
   397  // ServerAddr represents the address for establishing a connection to an
   398  // individual MongoDB server.
   399  type ServerAddr struct {
   400  	str string
   401  	tcp *net.TCPAddr
   402  }
   403  
   404  // String returns the address that was provided for the server before resolution.
   405  func (addr *ServerAddr) String() string {
   406  	return addr.str
   407  }
   408  
   409  // TCPAddr returns the resolved TCP address for the server.
   410  func (addr *ServerAddr) TCPAddr() *net.TCPAddr {
   411  	return addr.tcp
   412  }
   413  
   414  // DialWithInfo establishes a new session to the cluster identified by info.
   415  func DialWithInfo(info *DialInfo) (*Session, error) {
   416  	addrs := make([]string, len(info.Addrs))
   417  	for i, addr := range info.Addrs {
   418  		p := strings.LastIndexAny(addr, "]:")
   419  		if p == -1 || addr[p] != ':' {
   420  			// XXX This is untested. The test suite doesn't use the standard port.
   421  			addr += ":27017"
   422  		}
   423  		addrs[i] = addr
   424  	}
   425  	cluster := newCluster(addrs, info.Direct, info.FailFast, dialer{info.Dial, info.DialServer}, info.ReplicaSetName)
   426  	session := newSession(Eventual, cluster, info.Timeout)
   427  	session.defaultdb = info.Database
   428  	if session.defaultdb == "" {
   429  		session.defaultdb = "test"
   430  	}
   431  	session.sourcedb = info.Source
   432  	if session.sourcedb == "" {
   433  		session.sourcedb = info.Database
   434  		if session.sourcedb == "" {
   435  			session.sourcedb = "admin"
   436  		}
   437  	}
   438  	if info.Username != "" {
   439  		source := session.sourcedb
   440  		if info.Source == "" &&
   441  			(info.Mechanism == "GSSAPI" || info.Mechanism == "PLAIN" || info.Mechanism == "MONGODB-X509") {
   442  			source = "$external"
   443  		}
   444  		session.dialCred = &Credential{
   445  			Username:    info.Username,
   446  			Password:    info.Password,
   447  			Mechanism:   info.Mechanism,
   448  			Service:     info.Service,
   449  			ServiceHost: info.ServiceHost,
   450  			Source:      source,
   451  		}
   452  		session.creds = []Credential{*session.dialCred}
   453  	}
   454  	if info.PoolLimit > 0 {
   455  		session.poolLimit = info.PoolLimit
   456  	}
   457  	cluster.Release()
   458  
   459  	// People get confused when we return a session that is not actually
   460  	// established to any servers yet (e.g. what if url was wrong). So,
   461  	// ping the server to ensure there's someone there, and abort if it
   462  	// fails.
   463  	if err := session.Ping(); err != nil {
   464  		session.Close()
   465  		return nil, err
   466  	}
   467  	session.SetMode(Strong, true)
   468  	return session, nil
   469  }
   470  
   471  func isOptSep(c rune) bool {
   472  	return c == ';' || c == '&'
   473  }
   474  
   475  type urlInfo struct {
   476  	addrs   []string
   477  	user    string
   478  	pass    string
   479  	db      string
   480  	options map[string]string
   481  }
   482  
   483  func extractURL(s string) (*urlInfo, error) {
   484  	if strings.HasPrefix(s, "mongodb://") {
   485  		s = s[10:]
   486  	}
   487  	info := &urlInfo{options: make(map[string]string)}
   488  	if c := strings.Index(s, "?"); c != -1 {
   489  		for _, pair := range strings.FieldsFunc(s[c+1:], isOptSep) {
   490  			l := strings.SplitN(pair, "=", 2)
   491  			if len(l) != 2 || l[0] == "" || l[1] == "" {
   492  				return nil, errors.New("connection option must be key=value: " + pair)
   493  			}
   494  			info.options[l[0]] = l[1]
   495  		}
   496  		s = s[:c]
   497  	}
   498  	if c := strings.Index(s, "@"); c != -1 {
   499  		pair := strings.SplitN(s[:c], ":", 2)
   500  		if len(pair) > 2 || pair[0] == "" {
   501  			return nil, errors.New("credentials must be provided as user:pass@host")
   502  		}
   503  		var err error
   504  		info.user, err = url.QueryUnescape(pair[0])
   505  		if err != nil {
   506  			return nil, fmt.Errorf("cannot unescape username in URL: %q", pair[0])
   507  		}
   508  		if len(pair) > 1 {
   509  			info.pass, err = url.QueryUnescape(pair[1])
   510  			if err != nil {
   511  				return nil, fmt.Errorf("cannot unescape password in URL")
   512  			}
   513  		}
   514  		s = s[c+1:]
   515  	}
   516  	if c := strings.Index(s, "/"); c != -1 {
   517  		info.db = s[c+1:]
   518  		s = s[:c]
   519  	}
   520  	info.addrs = strings.Split(s, ",")
   521  	return info, nil
   522  }
   523  
   524  func newSession(consistency Mode, cluster *mongoCluster, timeout time.Duration) (session *Session) {
   525  	cluster.Acquire()
   526  	session = &Session{
   527  		cluster_:    cluster,
   528  		syncTimeout: timeout,
   529  		sockTimeout: timeout,
   530  		poolLimit:   4096,
   531  	}
   532  	debugf("New session %p on cluster %p", session, cluster)
   533  	session.SetMode(consistency, true)
   534  	session.SetSafe(&Safe{})
   535  	session.queryConfig.prefetch = defaultPrefetch
   536  	return session
   537  }
   538  
   539  func copySession(session *Session, keepCreds bool) (s *Session) {
   540  	cluster := session.cluster()
   541  	cluster.Acquire()
   542  	if session.masterSocket != nil {
   543  		session.masterSocket.Acquire()
   544  	}
   545  	if session.slaveSocket != nil {
   546  		session.slaveSocket.Acquire()
   547  	}
   548  	var creds []Credential
   549  	if keepCreds {
   550  		creds = make([]Credential, len(session.creds))
   551  		copy(creds, session.creds)
   552  	} else if session.dialCred != nil {
   553  		creds = []Credential{*session.dialCred}
   554  	}
   555  	scopy := *session
   556  	scopy.m = sync.RWMutex{}
   557  	scopy.creds = creds
   558  	s = &scopy
   559  	debugf("New session %p on cluster %p (copy from %p)", s, cluster, session)
   560  	return s
   561  }
   562  
   563  // LiveServers returns a list of server addresses which are
   564  // currently known to be alive.
   565  func (s *Session) LiveServers() (addrs []string) {
   566  	s.m.RLock()
   567  	addrs = s.cluster().LiveServers()
   568  	s.m.RUnlock()
   569  	return addrs
   570  }
   571  
   572  // DB returns a value representing the named database. If name
   573  // is empty, the database name provided in the dialed URL is
   574  // used instead. If that is also empty, "test" is used as a
   575  // fallback in a way equivalent to the mongo shell.
   576  //
   577  // Creating this value is a very lightweight operation, and
   578  // involves no network communication.
   579  func (s *Session) DB(name string) *Database {
   580  	if name == "" {
   581  		name = s.defaultdb
   582  	}
   583  	return &Database{s, name}
   584  }
   585  
   586  // C returns a value representing the named collection.
   587  //
   588  // Creating this value is a very lightweight operation, and
   589  // involves no network communication.
   590  func (db *Database) C(name string) *Collection {
   591  	return &Collection{db, name, db.Name + "." + name}
   592  }
   593  
   594  // With returns a copy of db that uses session s.
   595  func (db *Database) With(s *Session) *Database {
   596  	newdb := *db
   597  	newdb.Session = s
   598  	return &newdb
   599  }
   600  
   601  // With returns a copy of c that uses session s.
   602  func (c *Collection) With(s *Session) *Collection {
   603  	newdb := *c.Database
   604  	newdb.Session = s
   605  	newc := *c
   606  	newc.Database = &newdb
   607  	return &newc
   608  }
   609  
   610  // GridFS returns a GridFS value representing collections in db that
   611  // follow the standard GridFS specification.
   612  // The provided prefix (sometimes known as root) will determine which
   613  // collections to use, and is usually set to "fs" when there is a
   614  // single GridFS in the database.
   615  //
   616  // See the GridFS Create, Open, and OpenId methods for more details.
   617  //
   618  // Relevant documentation:
   619  //
   620  //     http://www.mongodb.org/display/DOCS/GridFS
   621  //     http://www.mongodb.org/display/DOCS/GridFS+Tools
   622  //     http://www.mongodb.org/display/DOCS/GridFS+Specification
   623  //
   624  func (db *Database) GridFS(prefix string) *GridFS {
   625  	return newGridFS(db, prefix)
   626  }
   627  
   628  // Run issues the provided command on the db database and unmarshals
   629  // its result in the respective argument. The cmd argument may be either
   630  // a string with the command name itself, in which case an empty document of
   631  // the form bson.M{cmd: 1} will be used, or it may be a full command document.
   632  //
   633  // Note that MongoDB considers the first marshalled key as the command
   634  // name, so when providing a command with options, it's important to
   635  // use an ordering-preserving document, such as a struct value or an
   636  // instance of bson.D.  For instance:
   637  //
   638  //     db.Run(bson.D{{"create", "mycollection"}, {"size", 1024}})
   639  //
   640  // For privilleged commands typically run on the "admin" database, see
   641  // the Run method in the Session type.
   642  //
   643  // Relevant documentation:
   644  //
   645  //     http://www.mongodb.org/display/DOCS/Commands
   646  //     http://www.mongodb.org/display/DOCS/List+of+Database+CommandSkips
   647  //
   648  func (db *Database) Run(cmd interface{}, result interface{}) error {
   649  	socket, err := db.Session.acquireSocket(true)
   650  	if err != nil {
   651  		return err
   652  	}
   653  	defer socket.Release()
   654  
   655  	// This is an optimized form of db.C("$cmd").Find(cmd).One(result).
   656  	return db.run(socket, cmd, result)
   657  }
   658  
   659  // Credential holds details to authenticate with a MongoDB server.
   660  type Credential struct {
   661  	// Username and Password hold the basic details for authentication.
   662  	// Password is optional with some authentication mechanisms.
   663  	Username string
   664  	Password string
   665  
   666  	// Source is the database used to establish credentials and privileges
   667  	// with a MongoDB server. Defaults to the default database provided
   668  	// during dial, or "admin" if that was unset.
   669  	Source string
   670  
   671  	// Service defines the service name to use when authenticating with the GSSAPI
   672  	// mechanism. Defaults to "mongodb".
   673  	Service string
   674  
   675  	// ServiceHost defines which hostname to use when authenticating
   676  	// with the GSSAPI mechanism. If not specified, defaults to the MongoDB
   677  	// server's address.
   678  	ServiceHost string
   679  
   680  	// Mechanism defines the protocol for credential negotiation.
   681  	// Defaults to "MONGODB-CR".
   682  	Mechanism string
   683  }
   684  
   685  // Login authenticates with MongoDB using the provided credential.  The
   686  // authentication is valid for the whole session and will stay valid until
   687  // Logout is explicitly called for the same database, or the session is
   688  // closed.
   689  func (db *Database) Login(user, pass string) error {
   690  	return db.Session.Login(&Credential{Username: user, Password: pass, Source: db.Name})
   691  }
   692  
   693  // Login authenticates with MongoDB using the provided credential.  The
   694  // authentication is valid for the whole session and will stay valid until
   695  // Logout is explicitly called for the same database, or the session is
   696  // closed.
   697  func (s *Session) Login(cred *Credential) error {
   698  	socket, err := s.acquireSocket(true)
   699  	if err != nil {
   700  		return err
   701  	}
   702  	defer socket.Release()
   703  
   704  	credCopy := *cred
   705  	if cred.Source == "" {
   706  		if cred.Mechanism == "GSSAPI" {
   707  			credCopy.Source = "$external"
   708  		} else {
   709  			credCopy.Source = s.sourcedb
   710  		}
   711  	}
   712  	err = socket.Login(credCopy)
   713  	if err != nil {
   714  		return err
   715  	}
   716  
   717  	s.m.Lock()
   718  	s.creds = append(s.creds, credCopy)
   719  	s.m.Unlock()
   720  	return nil
   721  }
   722  
   723  func (s *Session) socketLogin(socket *mongoSocket) error {
   724  	for _, cred := range s.creds {
   725  		if err := socket.Login(cred); err != nil {
   726  			return err
   727  		}
   728  	}
   729  	return nil
   730  }
   731  
   732  // Logout removes any established authentication credentials for the database.
   733  func (db *Database) Logout() {
   734  	session := db.Session
   735  	dbname := db.Name
   736  	session.m.Lock()
   737  	found := false
   738  	for i, cred := range session.creds {
   739  		if cred.Source == dbname {
   740  			copy(session.creds[i:], session.creds[i+1:])
   741  			session.creds = session.creds[:len(session.creds)-1]
   742  			found = true
   743  			break
   744  		}
   745  	}
   746  	if found {
   747  		if session.masterSocket != nil {
   748  			session.masterSocket.Logout(dbname)
   749  		}
   750  		if session.slaveSocket != nil {
   751  			session.slaveSocket.Logout(dbname)
   752  		}
   753  	}
   754  	session.m.Unlock()
   755  }
   756  
   757  // LogoutAll removes all established authentication credentials for the session.
   758  func (s *Session) LogoutAll() {
   759  	s.m.Lock()
   760  	for _, cred := range s.creds {
   761  		if s.masterSocket != nil {
   762  			s.masterSocket.Logout(cred.Source)
   763  		}
   764  		if s.slaveSocket != nil {
   765  			s.slaveSocket.Logout(cred.Source)
   766  		}
   767  	}
   768  	s.creds = s.creds[0:0]
   769  	s.m.Unlock()
   770  }
   771  
   772  // User represents a MongoDB user.
   773  //
   774  // Relevant documentation:
   775  //
   776  //     http://docs.mongodb.org/manual/reference/privilege-documents/
   777  //     http://docs.mongodb.org/manual/reference/user-privileges/
   778  //
   779  type User struct {
   780  	// Username is how the user identifies itself to the system.
   781  	Username string `bson:"user"`
   782  
   783  	// Password is the plaintext password for the user. If set,
   784  	// the UpsertUser method will hash it into PasswordHash and
   785  	// unset it before the user is added to the database.
   786  	Password string `bson:",omitempty"`
   787  
   788  	// PasswordHash is the MD5 hash of Username+":mongo:"+Password.
   789  	PasswordHash string `bson:"pwd,omitempty"`
   790  
   791  	// CustomData holds arbitrary data admins decide to associate
   792  	// with this user, such as the full name or employee id.
   793  	CustomData interface{} `bson:"customData,omitempty"`
   794  
   795  	// Roles indicates the set of roles the user will be provided.
   796  	// See the Role constants.
   797  	Roles []Role `bson:"roles"`
   798  
   799  	// OtherDBRoles allows assigning roles in other databases from
   800  	// user documents inserted in the admin database. This field
   801  	// only works in the admin database.
   802  	OtherDBRoles map[string][]Role `bson:"otherDBRoles,omitempty"`
   803  
   804  	// UserSource indicates where to look for this user's credentials.
   805  	// It may be set to a database name, or to "$external" for
   806  	// consulting an external resource such as Kerberos. UserSource
   807  	// must not be set if Password or PasswordHash are present.
   808  	//
   809  	// WARNING: This setting was only ever supported in MongoDB 2.4,
   810  	// and is now obsolete.
   811  	UserSource string `bson:"userSource,omitempty"`
   812  }
   813  
   814  type Role string
   815  
   816  const (
   817  	// Relevant documentation:
   818  	//
   819  	//     http://docs.mongodb.org/manual/reference/user-privileges/
   820  	//
   821  	RoleRoot         Role = "root"
   822  	RoleRead         Role = "read"
   823  	RoleReadAny      Role = "readAnyDatabase"
   824  	RoleReadWrite    Role = "readWrite"
   825  	RoleReadWriteAny Role = "readWriteAnyDatabase"
   826  	RoleDBAdmin      Role = "dbAdmin"
   827  	RoleDBAdminAny   Role = "dbAdminAnyDatabase"
   828  	RoleUserAdmin    Role = "userAdmin"
   829  	RoleUserAdminAny Role = "userAdminAnyDatabase"
   830  	RoleClusterAdmin Role = "clusterAdmin"
   831  )
   832  
   833  // UpsertUser updates the authentication credentials and the roles for
   834  // a MongoDB user within the db database. If the named user doesn't exist
   835  // it will be created.
   836  //
   837  // This method should only be used from MongoDB 2.4 and on. For older
   838  // MongoDB releases, use the obsolete AddUser method instead.
   839  //
   840  // Relevant documentation:
   841  //
   842  //     http://docs.mongodb.org/manual/reference/user-privileges/
   843  //     http://docs.mongodb.org/manual/reference/privilege-documents/
   844  //
   845  func (db *Database) UpsertUser(user *User) error {
   846  	if user.Username == "" {
   847  		return fmt.Errorf("user has no Username")
   848  	}
   849  	if (user.Password != "" || user.PasswordHash != "") && user.UserSource != "" {
   850  		return fmt.Errorf("user has both Password/PasswordHash and UserSource set")
   851  	}
   852  	if len(user.OtherDBRoles) > 0 && db.Name != "admin" && db.Name != "$external" {
   853  		return fmt.Errorf("user with OtherDBRoles is only supported in the admin or $external databases")
   854  	}
   855  
   856  	// Attempt to run this using 2.6+ commands.
   857  	rundb := db
   858  	if user.UserSource != "" {
   859  		// Compatibility logic for the userSource field of MongoDB <= 2.4.X
   860  		rundb = db.Session.DB(user.UserSource)
   861  	}
   862  	err := rundb.runUserCmd("updateUser", user)
   863  	// retry with createUser when isAuthError in order to enable the "localhost exception"
   864  	if isNotFound(err) || isAuthError(err) {
   865  		return rundb.runUserCmd("createUser", user)
   866  	}
   867  	if !isNoCmd(err) {
   868  		return err
   869  	}
   870  
   871  	// Command does not exist. Fallback to pre-2.6 behavior.
   872  	var set, unset bson.D
   873  	if user.Password != "" {
   874  		psum := md5.New()
   875  		psum.Write([]byte(user.Username + ":mongo:" + user.Password))
   876  		set = append(set, bson.DocElem{"pwd", hex.EncodeToString(psum.Sum(nil))})
   877  		unset = append(unset, bson.DocElem{"userSource", 1})
   878  	} else if user.PasswordHash != "" {
   879  		set = append(set, bson.DocElem{"pwd", user.PasswordHash})
   880  		unset = append(unset, bson.DocElem{"userSource", 1})
   881  	}
   882  	if user.UserSource != "" {
   883  		set = append(set, bson.DocElem{"userSource", user.UserSource})
   884  		unset = append(unset, bson.DocElem{"pwd", 1})
   885  	}
   886  	if user.Roles != nil || user.OtherDBRoles != nil {
   887  		set = append(set, bson.DocElem{"roles", user.Roles})
   888  		if len(user.OtherDBRoles) > 0 {
   889  			set = append(set, bson.DocElem{"otherDBRoles", user.OtherDBRoles})
   890  		} else {
   891  			unset = append(unset, bson.DocElem{"otherDBRoles", 1})
   892  		}
   893  	}
   894  	users := db.C("system.users")
   895  	err = users.Update(bson.D{{"user", user.Username}}, bson.D{{"$unset", unset}, {"$set", set}})
   896  	if err == ErrNotFound {
   897  		set = append(set, bson.DocElem{"user", user.Username})
   898  		if user.Roles == nil && user.OtherDBRoles == nil {
   899  			// Roles must be sent, as it's the way MongoDB distinguishes
   900  			// old-style documents from new-style documents in pre-2.6.
   901  			set = append(set, bson.DocElem{"roles", user.Roles})
   902  		}
   903  		err = users.Insert(set)
   904  	}
   905  	return err
   906  }
   907  
   908  func isNoCmd(err error) bool {
   909  	e, ok := err.(*QueryError)
   910  	return ok && (e.Code == 59 || e.Code == 13390 || strings.HasPrefix(e.Message, "no such cmd:"))
   911  }
   912  
   913  func isNotFound(err error) bool {
   914  	e, ok := err.(*QueryError)
   915  	return ok && e.Code == 11
   916  }
   917  
   918  func isAuthError(err error) bool {
   919  	e, ok := err.(*QueryError)
   920  	return ok && e.Code == 13
   921  }
   922  
   923  func (db *Database) runUserCmd(cmdName string, user *User) error {
   924  	cmd := make(bson.D, 0, 16)
   925  	cmd = append(cmd, bson.DocElem{cmdName, user.Username})
   926  	if user.Password != "" {
   927  		cmd = append(cmd, bson.DocElem{"pwd", user.Password})
   928  	}
   929  	var roles []interface{}
   930  	for _, role := range user.Roles {
   931  		roles = append(roles, role)
   932  	}
   933  	for db, dbroles := range user.OtherDBRoles {
   934  		for _, role := range dbroles {
   935  			roles = append(roles, bson.D{{"role", role}, {"db", db}})
   936  		}
   937  	}
   938  	if roles != nil || user.Roles != nil || cmdName == "createUser" {
   939  		cmd = append(cmd, bson.DocElem{"roles", roles})
   940  	}
   941  	err := db.Run(cmd, nil)
   942  	if !isNoCmd(err) && user.UserSource != "" && (user.UserSource != "$external" || db.Name != "$external") {
   943  		return fmt.Errorf("MongoDB 2.6+ does not support the UserSource setting")
   944  	}
   945  	return err
   946  }
   947  
   948  // AddUser creates or updates the authentication credentials of user within
   949  // the db database.
   950  //
   951  // WARNING: This method is obsolete and should only be used with MongoDB 2.2
   952  // or earlier. For MongoDB 2.4 and on, use UpsertUser instead.
   953  func (db *Database) AddUser(username, password string, readOnly bool) error {
   954  	// Try to emulate the old behavior on 2.6+
   955  	user := &User{Username: username, Password: password}
   956  	if db.Name == "admin" {
   957  		if readOnly {
   958  			user.Roles = []Role{RoleReadAny}
   959  		} else {
   960  			user.Roles = []Role{RoleReadWriteAny}
   961  		}
   962  	} else {
   963  		if readOnly {
   964  			user.Roles = []Role{RoleRead}
   965  		} else {
   966  			user.Roles = []Role{RoleReadWrite}
   967  		}
   968  	}
   969  	err := db.runUserCmd("updateUser", user)
   970  	if isNotFound(err) {
   971  		return db.runUserCmd("createUser", user)
   972  	}
   973  	if !isNoCmd(err) {
   974  		return err
   975  	}
   976  
   977  	// Command doesn't exist. Fallback to pre-2.6 behavior.
   978  	psum := md5.New()
   979  	psum.Write([]byte(username + ":mongo:" + password))
   980  	digest := hex.EncodeToString(psum.Sum(nil))
   981  	c := db.C("system.users")
   982  	_, err = c.Upsert(bson.M{"user": username}, bson.M{"$set": bson.M{"user": username, "pwd": digest, "readOnly": readOnly}})
   983  	return err
   984  }
   985  
   986  // RemoveUser removes the authentication credentials of user from the database.
   987  func (db *Database) RemoveUser(user string) error {
   988  	err := db.Run(bson.D{{"dropUser", user}}, nil)
   989  	if isNoCmd(err) {
   990  		users := db.C("system.users")
   991  		return users.Remove(bson.M{"user": user})
   992  	}
   993  	if isNotFound(err) {
   994  		return ErrNotFound
   995  	}
   996  	return err
   997  }
   998  
   999  type indexSpec struct {
  1000  	Name, NS         string
  1001  	Key              bson.D
  1002  	Unique           bool    ",omitempty"
  1003  	DropDups         bool    "dropDups,omitempty"
  1004  	Background       bool    ",omitempty"
  1005  	Sparse           bool    ",omitempty"
  1006  	Bits             int     ",omitempty"
  1007  	Min, Max         float64 ",omitempty"
  1008  	BucketSize       float64 "bucketSize,omitempty"
  1009  	ExpireAfter      int     "expireAfterSeconds,omitempty"
  1010  	Weights          bson.D  ",omitempty"
  1011  	DefaultLanguage  string  "default_language,omitempty"
  1012  	LanguageOverride string  "language_override,omitempty"
  1013  	TextIndexVersion int     "textIndexVersion,omitempty"
  1014  
  1015  	Collation *Collation "collation,omitempty"
  1016  }
  1017  
  1018  type Index struct {
  1019  	Key        []string // Index key fields; prefix name with dash (-) for descending order
  1020  	Unique     bool     // Prevent two documents from having the same index key
  1021  	DropDups   bool     // Drop documents with the same index key as a previously indexed one
  1022  	Background bool     // Build index in background and return immediately
  1023  	Sparse     bool     // Only index documents containing the Key fields
  1024  
  1025  	// If ExpireAfter is defined the server will periodically delete
  1026  	// documents with indexed time.Time older than the provided delta.
  1027  	ExpireAfter time.Duration
  1028  
  1029  	// Name holds the stored index name. On creation if this field is unset it is
  1030  	// computed by EnsureIndex based on the index key.
  1031  	Name string
  1032  
  1033  	// Properties for spatial indexes.
  1034  	//
  1035  	// Min and Max were improperly typed as int when they should have been
  1036  	// floats.  To preserve backwards compatibility they are still typed as
  1037  	// int and the following two fields enable reading and writing the same
  1038  	// fields as float numbers. In mgo.v3, these fields will be dropped and
  1039  	// Min/Max will become floats.
  1040  	Min, Max   int
  1041  	Minf, Maxf float64
  1042  	BucketSize float64
  1043  	Bits       int
  1044  
  1045  	// Properties for text indexes.
  1046  	DefaultLanguage  string
  1047  	LanguageOverride string
  1048  
  1049  	// Weights defines the significance of provided fields relative to other
  1050  	// fields in a text index. The score for a given word in a document is derived
  1051  	// from the weighted sum of the frequency for each of the indexed fields in
  1052  	// that document. The default field weight is 1.
  1053  	Weights map[string]int
  1054  
  1055  	// Collation defines the collation to use for the index.
  1056  	Collation *Collation
  1057  }
  1058  
  1059  type Collation struct {
  1060  
  1061  	// Locale defines the collation locale.
  1062  	Locale string `bson:"locale"`
  1063  
  1064  	// CaseLevel defines whether to turn case sensitivity on at strength 1 or 2.
  1065  	CaseLevel bool `bson:"caseLevel,omitempty"`
  1066  
  1067  	// CaseFirst may be set to "upper" or "lower" to define whether
  1068  	// to have uppercase or lowercase items first. Default is "off".
  1069  	CaseFirst string `bson:"caseFirst,omitempty"`
  1070  
  1071  	// Strength defines the priority of comparison properties, as follows:
  1072  	//
  1073  	//   1 (primary)    - Strongest level, denote difference between base characters
  1074  	//   2 (secondary)  - Accents in characters are considered secondary differences
  1075  	//   3 (tertiary)   - Upper and lower case differences in characters are
  1076  	//                    distinguished at the tertiary level
  1077  	//   4 (quaternary) - When punctuation is ignored at level 1-3, an additional
  1078  	//                    level can be used to distinguish words with and without
  1079  	//                    punctuation. Should only be used if ignoring punctuation
  1080  	//                    is required or when processing Japanese text.
  1081  	//   5 (identical)  - When all other levels are equal, the identical level is
  1082  	//                    used as a tiebreaker. The Unicode code point values of
  1083  	//                    the NFD form of each string are compared at this level,
  1084  	//                    just in case there is no difference at levels 1-4
  1085  	//
  1086  	// Strength defaults to 3.
  1087  	Strength int `bson:"strength,omitempty"`
  1088  
  1089  	// NumericOrdering defines whether to order numbers based on numerical
  1090  	// order and not collation order.
  1091  	NumericOrdering bool `bson:"numericOrdering,omitempty"`
  1092  
  1093  	// Alternate controls whether spaces and punctuation are considered base characters.
  1094  	// May be set to "non-ignorable" (spaces and punctuation considered base characters)
  1095  	// or "shifted" (spaces and punctuation not considered base characters, and only
  1096  	// distinguished at strength > 3). Defaults to "non-ignorable".
  1097  	Alternate string `bson:"alternate,omitempty"`
  1098  
  1099  	// Backwards defines whether to have secondary differences considered in reverse order,
  1100  	// as done in the French language.
  1101  	Backwards bool `bson:"backwards,omitempty"`
  1102  }
  1103  
  1104  // mgo.v3: Drop Minf and Maxf and transform Min and Max to floats.
  1105  // mgo.v3: Drop DropDups as it's unsupported past 2.8.
  1106  
  1107  type indexKeyInfo struct {
  1108  	name    string
  1109  	key     bson.D
  1110  	weights bson.D
  1111  }
  1112  
  1113  func parseIndexKey(key []string) (*indexKeyInfo, error) {
  1114  	var keyInfo indexKeyInfo
  1115  	isText := false
  1116  	var order interface{}
  1117  	for _, field := range key {
  1118  		raw := field
  1119  		if keyInfo.name != "" {
  1120  			keyInfo.name += "_"
  1121  		}
  1122  		var kind string
  1123  		if field != "" {
  1124  			if field[0] == '$' {
  1125  				if c := strings.Index(field, ":"); c > 1 && c < len(field)-1 {
  1126  					kind = field[1:c]
  1127  					field = field[c+1:]
  1128  					keyInfo.name += field + "_" + kind
  1129  				} else {
  1130  					field = "\x00"
  1131  				}
  1132  			}
  1133  			switch field[0] {
  1134  			case 0:
  1135  				// Logic above failed. Reset and error.
  1136  				field = ""
  1137  			case '@':
  1138  				order = "2d"
  1139  				field = field[1:]
  1140  				// The shell used to render this field as key_ instead of key_2d,
  1141  				// and mgo followed suit. This has been fixed in recent server
  1142  				// releases, and mgo followed as well.
  1143  				keyInfo.name += field + "_2d"
  1144  			case '-':
  1145  				order = -1
  1146  				field = field[1:]
  1147  				keyInfo.name += field + "_-1"
  1148  			case '+':
  1149  				field = field[1:]
  1150  				fallthrough
  1151  			default:
  1152  				if kind == "" {
  1153  					order = 1
  1154  					keyInfo.name += field + "_1"
  1155  				} else {
  1156  					order = kind
  1157  				}
  1158  			}
  1159  		}
  1160  		if field == "" || kind != "" && order != kind {
  1161  			return nil, fmt.Errorf(`invalid index key: want "[$<kind>:][-]<field name>", got %q`, raw)
  1162  		}
  1163  		if kind == "text" {
  1164  			if !isText {
  1165  				keyInfo.key = append(keyInfo.key, bson.DocElem{"_fts", "text"}, bson.DocElem{"_ftsx", 1})
  1166  				isText = true
  1167  			}
  1168  			keyInfo.weights = append(keyInfo.weights, bson.DocElem{field, 1})
  1169  		} else {
  1170  			keyInfo.key = append(keyInfo.key, bson.DocElem{field, order})
  1171  		}
  1172  	}
  1173  	if keyInfo.name == "" {
  1174  		return nil, errors.New("invalid index key: no fields provided")
  1175  	}
  1176  	return &keyInfo, nil
  1177  }
  1178  
  1179  // EnsureIndexKey ensures an index with the given key exists, creating it
  1180  // if necessary.
  1181  //
  1182  // This example:
  1183  //
  1184  //     err := collection.EnsureIndexKey("a", "b")
  1185  //
  1186  // Is equivalent to:
  1187  //
  1188  //     err := collection.EnsureIndex(mgo.Index{Key: []string{"a", "b"}})
  1189  //
  1190  // See the EnsureIndex method for more details.
  1191  func (c *Collection) EnsureIndexKey(key ...string) error {
  1192  	return c.EnsureIndex(Index{Key: key})
  1193  }
  1194  
  1195  // EnsureIndex ensures an index with the given key exists, creating it with
  1196  // the provided parameters if necessary. EnsureIndex does not modify a previously
  1197  // existent index with a matching key. The old index must be dropped first instead.
  1198  //
  1199  // Once EnsureIndex returns successfully, following requests for the same index
  1200  // will not contact the server unless Collection.DropIndex is used to drop the
  1201  // same index, or Session.ResetIndexCache is called.
  1202  //
  1203  // For example:
  1204  //
  1205  //     index := Index{
  1206  //         Key: []string{"lastname", "firstname"},
  1207  //         Unique: true,
  1208  //         DropDups: true,
  1209  //         Background: true, // See notes.
  1210  //         Sparse: true,
  1211  //     }
  1212  //     err := collection.EnsureIndex(index)
  1213  //
  1214  // The Key value determines which fields compose the index. The index ordering
  1215  // will be ascending by default.  To obtain an index with a descending order,
  1216  // the field name should be prefixed by a dash (e.g. []string{"-time"}). It can
  1217  // also be optionally prefixed by an index kind, as in "$text:summary" or
  1218  // "$2d:-point". The key string format is:
  1219  //
  1220  //     [$<kind>:][-]<field name>
  1221  //
  1222  // If the Unique field is true, the index must necessarily contain only a single
  1223  // document per Key.  With DropDups set to true, documents with the same key
  1224  // as a previously indexed one will be dropped rather than an error returned.
  1225  //
  1226  // If Background is true, other connections will be allowed to proceed using
  1227  // the collection without the index while it's being built. Note that the
  1228  // session executing EnsureIndex will be blocked for as long as it takes for
  1229  // the index to be built.
  1230  //
  1231  // If Sparse is true, only documents containing the provided Key fields will be
  1232  // included in the index.  When using a sparse index for sorting, only indexed
  1233  // documents will be returned.
  1234  //
  1235  // If ExpireAfter is non-zero, the server will periodically scan the collection
  1236  // and remove documents containing an indexed time.Time field with a value
  1237  // older than ExpireAfter. See the documentation for details:
  1238  //
  1239  //     http://docs.mongodb.org/manual/tutorial/expire-data
  1240  //
  1241  // Other kinds of indexes are also supported through that API. Here is an example:
  1242  //
  1243  //     index := Index{
  1244  //         Key: []string{"$2d:loc"},
  1245  //         Bits: 26,
  1246  //     }
  1247  //     err := collection.EnsureIndex(index)
  1248  //
  1249  // The example above requests the creation of a "2d" index for the "loc" field.
  1250  //
  1251  // The 2D index bounds may be changed using the Min and Max attributes of the
  1252  // Index value.  The default bound setting of (-180, 180) is suitable for
  1253  // latitude/longitude pairs.
  1254  //
  1255  // The Bits parameter sets the precision of the 2D geohash values.  If not
  1256  // provided, 26 bits are used, which is roughly equivalent to 1 foot of
  1257  // precision for the default (-180, 180) index bounds.
  1258  //
  1259  // Relevant documentation:
  1260  //
  1261  //     http://www.mongodb.org/display/DOCS/Indexes
  1262  //     http://www.mongodb.org/display/DOCS/Indexing+Advice+and+FAQ
  1263  //     http://www.mongodb.org/display/DOCS/Indexing+as+a+Background+Operation
  1264  //     http://www.mongodb.org/display/DOCS/Geospatial+Indexing
  1265  //     http://www.mongodb.org/display/DOCS/Multikeys
  1266  //
  1267  func (c *Collection) EnsureIndex(index Index) error {
  1268  	keyInfo, err := parseIndexKey(index.Key)
  1269  	if err != nil {
  1270  		return err
  1271  	}
  1272  
  1273  	session := c.Database.Session
  1274  	cacheKey := c.FullName + "\x00" + keyInfo.name
  1275  	if session.cluster().HasCachedIndex(cacheKey) {
  1276  		return nil
  1277  	}
  1278  
  1279  	spec := indexSpec{
  1280  		Name:             keyInfo.name,
  1281  		NS:               c.FullName,
  1282  		Key:              keyInfo.key,
  1283  		Unique:           index.Unique,
  1284  		DropDups:         index.DropDups,
  1285  		Background:       index.Background,
  1286  		Sparse:           index.Sparse,
  1287  		Bits:             index.Bits,
  1288  		Min:              index.Minf,
  1289  		Max:              index.Maxf,
  1290  		BucketSize:       index.BucketSize,
  1291  		ExpireAfter:      int(index.ExpireAfter / time.Second),
  1292  		Weights:          keyInfo.weights,
  1293  		DefaultLanguage:  index.DefaultLanguage,
  1294  		LanguageOverride: index.LanguageOverride,
  1295  		Collation:        index.Collation,
  1296  	}
  1297  
  1298  	if spec.Min == 0 && spec.Max == 0 {
  1299  		spec.Min = float64(index.Min)
  1300  		spec.Max = float64(index.Max)
  1301  	}
  1302  
  1303  	if index.Name != "" {
  1304  		spec.Name = index.Name
  1305  	}
  1306  
  1307  NextField:
  1308  	for name, weight := range index.Weights {
  1309  		for i, elem := range spec.Weights {
  1310  			if elem.Name == name {
  1311  				spec.Weights[i].Value = weight
  1312  				continue NextField
  1313  			}
  1314  		}
  1315  		panic("weight provided for field that is not part of index key: " + name)
  1316  	}
  1317  
  1318  	cloned := session.Clone()
  1319  	defer cloned.Close()
  1320  	cloned.SetMode(Strong, false)
  1321  	cloned.EnsureSafe(&Safe{})
  1322  	db := c.Database.With(cloned)
  1323  
  1324  	// Try with a command first.
  1325  	err = db.Run(bson.D{{"createIndexes", c.Name}, {"indexes", []indexSpec{spec}}}, nil)
  1326  	if isNoCmd(err) {
  1327  		// Command not yet supported. Insert into the indexes collection instead.
  1328  		err = db.C("system.indexes").Insert(&spec)
  1329  	}
  1330  	if err == nil {
  1331  		session.cluster().CacheIndex(cacheKey, true)
  1332  	}
  1333  	return err
  1334  }
  1335  
  1336  // DropIndex drops the index with the provided key from the c collection.
  1337  //
  1338  // See EnsureIndex for details on the accepted key variants.
  1339  //
  1340  // For example:
  1341  //
  1342  //     err1 := collection.DropIndex("firstField", "-secondField")
  1343  //     err2 := collection.DropIndex("customIndexName")
  1344  //
  1345  func (c *Collection) DropIndex(key ...string) error {
  1346  	keyInfo, err := parseIndexKey(key)
  1347  	if err != nil {
  1348  		return err
  1349  	}
  1350  
  1351  	session := c.Database.Session
  1352  	cacheKey := c.FullName + "\x00" + keyInfo.name
  1353  	session.cluster().CacheIndex(cacheKey, false)
  1354  
  1355  	session = session.Clone()
  1356  	defer session.Close()
  1357  	session.SetMode(Strong, false)
  1358  
  1359  	db := c.Database.With(session)
  1360  	result := struct {
  1361  		ErrMsg string
  1362  		Ok     bool
  1363  	}{}
  1364  	err = db.Run(bson.D{{"dropIndexes", c.Name}, {"index", keyInfo.name}}, &result)
  1365  	if err != nil {
  1366  		return err
  1367  	}
  1368  	if !result.Ok {
  1369  		return errors.New(result.ErrMsg)
  1370  	}
  1371  	return nil
  1372  }
  1373  
  1374  // DropIndexName removes the index with the provided index name.
  1375  //
  1376  // For example:
  1377  //
  1378  //     err := collection.DropIndex("customIndexName")
  1379  //
  1380  func (c *Collection) DropIndexName(name string) error {
  1381  	session := c.Database.Session
  1382  
  1383  	session = session.Clone()
  1384  	defer session.Close()
  1385  	session.SetMode(Strong, false)
  1386  
  1387  	c = c.With(session)
  1388  
  1389  	indexes, err := c.Indexes()
  1390  	if err != nil {
  1391  		return err
  1392  	}
  1393  
  1394  	var index Index
  1395  	for _, idx := range indexes {
  1396  		if idx.Name == name {
  1397  			index = idx
  1398  			break
  1399  		}
  1400  	}
  1401  
  1402  	if index.Name != "" {
  1403  		keyInfo, err := parseIndexKey(index.Key)
  1404  		if err != nil {
  1405  			return err
  1406  		}
  1407  
  1408  		cacheKey := c.FullName + "\x00" + keyInfo.name
  1409  		session.cluster().CacheIndex(cacheKey, false)
  1410  	}
  1411  
  1412  	result := struct {
  1413  		ErrMsg string
  1414  		Ok     bool
  1415  	}{}
  1416  	err = c.Database.Run(bson.D{{"dropIndexes", c.Name}, {"index", name}}, &result)
  1417  	if err != nil {
  1418  		return err
  1419  	}
  1420  	if !result.Ok {
  1421  		return errors.New(result.ErrMsg)
  1422  	}
  1423  	return nil
  1424  }
  1425  
  1426  // nonEventual returns a clone of session and ensures it is not Eventual.
  1427  // This guarantees that the server that is used for queries may be reused
  1428  // afterwards when a cursor is received.
  1429  func (session *Session) nonEventual() *Session {
  1430  	cloned := session.Clone()
  1431  	if cloned.consistency == Eventual {
  1432  		cloned.SetMode(Monotonic, false)
  1433  	}
  1434  	return cloned
  1435  }
  1436  
  1437  // Indexes returns a list of all indexes for the collection.
  1438  //
  1439  // For example, this snippet would drop all available indexes:
  1440  //
  1441  //   indexes, err := collection.Indexes()
  1442  //   if err != nil {
  1443  //       return err
  1444  //   }
  1445  //   for _, index := range indexes {
  1446  //       err = collection.DropIndex(index.Key...)
  1447  //       if err != nil {
  1448  //           return err
  1449  //       }
  1450  //   }
  1451  //
  1452  // See the EnsureIndex method for more details on indexes.
  1453  func (c *Collection) Indexes() (indexes []Index, err error) {
  1454  	cloned := c.Database.Session.nonEventual()
  1455  	defer cloned.Close()
  1456  
  1457  	batchSize := int(cloned.queryConfig.op.limit)
  1458  
  1459  	// Try with a command.
  1460  	var result struct {
  1461  		Indexes []bson.Raw
  1462  		Cursor  cursorData
  1463  	}
  1464  	var iter *Iter
  1465  	err = c.Database.With(cloned).Run(bson.D{{"listIndexes", c.Name}, {"cursor", bson.D{{"batchSize", batchSize}}}}, &result)
  1466  	if err == nil {
  1467  		firstBatch := result.Indexes
  1468  		if firstBatch == nil {
  1469  			firstBatch = result.Cursor.FirstBatch
  1470  		}
  1471  		ns := strings.SplitN(result.Cursor.NS, ".", 2)
  1472  		if len(ns) < 2 {
  1473  			iter = c.With(cloned).NewIter(nil, firstBatch, result.Cursor.Id, nil)
  1474  		} else {
  1475  			iter = cloned.DB(ns[0]).C(ns[1]).NewIter(nil, firstBatch, result.Cursor.Id, nil)
  1476  		}
  1477  	} else if isNoCmd(err) {
  1478  		// Command not yet supported. Query the database instead.
  1479  		iter = c.Database.C("system.indexes").Find(bson.M{"ns": c.FullName}).Iter()
  1480  	} else {
  1481  		return nil, err
  1482  	}
  1483  
  1484  	var spec indexSpec
  1485  	for iter.Next(&spec) {
  1486  		indexes = append(indexes, indexFromSpec(spec))
  1487  	}
  1488  	if err = iter.Close(); err != nil {
  1489  		return nil, err
  1490  	}
  1491  	sort.Sort(indexSlice(indexes))
  1492  	return indexes, nil
  1493  }
  1494  
  1495  func indexFromSpec(spec indexSpec) Index {
  1496  	index := Index{
  1497  		Name:             spec.Name,
  1498  		Key:              simpleIndexKey(spec.Key),
  1499  		Unique:           spec.Unique,
  1500  		DropDups:         spec.DropDups,
  1501  		Background:       spec.Background,
  1502  		Sparse:           spec.Sparse,
  1503  		Minf:             spec.Min,
  1504  		Maxf:             spec.Max,
  1505  		Bits:             spec.Bits,
  1506  		BucketSize:       spec.BucketSize,
  1507  		DefaultLanguage:  spec.DefaultLanguage,
  1508  		LanguageOverride: spec.LanguageOverride,
  1509  		ExpireAfter:      time.Duration(spec.ExpireAfter) * time.Second,
  1510  		Collation:        spec.Collation,
  1511  	}
  1512  	if float64(int(spec.Min)) == spec.Min && float64(int(spec.Max)) == spec.Max {
  1513  		index.Min = int(spec.Min)
  1514  		index.Max = int(spec.Max)
  1515  	}
  1516  	if spec.TextIndexVersion > 0 {
  1517  		index.Key = make([]string, len(spec.Weights))
  1518  		index.Weights = make(map[string]int)
  1519  		for i, elem := range spec.Weights {
  1520  			index.Key[i] = "$text:" + elem.Name
  1521  			if w, ok := elem.Value.(int); ok {
  1522  				index.Weights[elem.Name] = w
  1523  			}
  1524  		}
  1525  	}
  1526  	return index
  1527  }
  1528  
  1529  type indexSlice []Index
  1530  
  1531  func (idxs indexSlice) Len() int           { return len(idxs) }
  1532  func (idxs indexSlice) Less(i, j int) bool { return idxs[i].Name < idxs[j].Name }
  1533  func (idxs indexSlice) Swap(i, j int)      { idxs[i], idxs[j] = idxs[j], idxs[i] }
  1534  
  1535  func simpleIndexKey(realKey bson.D) (key []string) {
  1536  	for i := range realKey {
  1537  		field := realKey[i].Name
  1538  		vi, ok := realKey[i].Value.(int)
  1539  		if !ok {
  1540  			vf, _ := realKey[i].Value.(float64)
  1541  			vi = int(vf)
  1542  		}
  1543  		if vi == 1 {
  1544  			key = append(key, field)
  1545  			continue
  1546  		}
  1547  		if vi == -1 {
  1548  			key = append(key, "-"+field)
  1549  			continue
  1550  		}
  1551  		if vs, ok := realKey[i].Value.(string); ok {
  1552  			key = append(key, "$"+vs+":"+field)
  1553  			continue
  1554  		}
  1555  		panic("Got unknown index key type for field " + field)
  1556  	}
  1557  	return
  1558  }
  1559  
  1560  // ResetIndexCache() clears the cache of previously ensured indexes.
  1561  // Following requests to EnsureIndex will contact the server.
  1562  func (s *Session) ResetIndexCache() {
  1563  	s.cluster().ResetIndexCache()
  1564  }
  1565  
  1566  // New creates a new session with the same parameters as the original
  1567  // session, including consistency, batch size, prefetching, safety mode,
  1568  // etc. The returned session will use sockets from the pool, so there's
  1569  // a chance that writes just performed in another session may not yet
  1570  // be visible.
  1571  //
  1572  // Login information from the original session will not be copied over
  1573  // into the new session unless it was provided through the initial URL
  1574  // for the Dial function.
  1575  //
  1576  // See the Copy and Clone methods.
  1577  //
  1578  func (s *Session) New() *Session {
  1579  	s.m.Lock()
  1580  	scopy := copySession(s, false)
  1581  	s.m.Unlock()
  1582  	scopy.Refresh()
  1583  	return scopy
  1584  }
  1585  
  1586  // Copy works just like New, but preserves the exact authentication
  1587  // information from the original session.
  1588  func (s *Session) Copy() *Session {
  1589  	s.m.Lock()
  1590  	scopy := copySession(s, true)
  1591  	s.m.Unlock()
  1592  	scopy.Refresh()
  1593  	return scopy
  1594  }
  1595  
  1596  // Clone works just like Copy, but also reuses the same socket as the original
  1597  // session, in case it had already reserved one due to its consistency
  1598  // guarantees.  This behavior ensures that writes performed in the old session
  1599  // are necessarily observed when using the new session, as long as it was a
  1600  // strong or monotonic session.  That said, it also means that long operations
  1601  // may cause other goroutines using the original session to wait.
  1602  func (s *Session) Clone() *Session {
  1603  	s.m.Lock()
  1604  	scopy := copySession(s, true)
  1605  	s.m.Unlock()
  1606  	return scopy
  1607  }
  1608  
  1609  // Close terminates the session.  It's a runtime error to use a session
  1610  // after it has been closed.
  1611  func (s *Session) Close() {
  1612  	s.m.Lock()
  1613  	if s.cluster_ != nil {
  1614  		debugf("Closing session %p", s)
  1615  		s.unsetSocket()
  1616  		s.cluster_.Release()
  1617  		s.cluster_ = nil
  1618  	}
  1619  	s.m.Unlock()
  1620  }
  1621  
  1622  func (s *Session) cluster() *mongoCluster {
  1623  	if s.cluster_ == nil {
  1624  		panic("Session already closed")
  1625  	}
  1626  	return s.cluster_
  1627  }
  1628  
  1629  // Refresh puts back any reserved sockets in use and restarts the consistency
  1630  // guarantees according to the current consistency setting for the session.
  1631  func (s *Session) Refresh() {
  1632  	s.m.Lock()
  1633  	s.slaveOk = s.consistency != Strong
  1634  	s.unsetSocket()
  1635  	s.m.Unlock()
  1636  }
  1637  
  1638  // SetMode changes the consistency mode for the session.
  1639  //
  1640  // The default mode is Strong.
  1641  //
  1642  // In the Strong consistency mode reads and writes will always be made to
  1643  // the primary server using a unique connection so that reads and writes are
  1644  // fully consistent, ordered, and observing the most up-to-date data.
  1645  // This offers the least benefits in terms of distributing load, but the
  1646  // most guarantees.  See also Monotonic and Eventual.
  1647  //
  1648  // In the Monotonic consistency mode reads may not be entirely up-to-date,
  1649  // but they will always see the history of changes moving forward, the data
  1650  // read will be consistent across sequential queries in the same session,
  1651  // and modifications made within the session will be observed in following
  1652  // queries (read-your-writes).
  1653  //
  1654  // In practice, the Monotonic mode is obtained by performing initial reads
  1655  // on a unique connection to an arbitrary secondary, if one is available,
  1656  // and once the first write happens, the session connection is switched over
  1657  // to the primary server.  This manages to distribute some of the reading
  1658  // load with secondaries, while maintaining some useful guarantees.
  1659  //
  1660  // In the Eventual consistency mode reads will be made to any secondary in the
  1661  // cluster, if one is available, and sequential reads will not necessarily
  1662  // be made with the same connection.  This means that data may be observed
  1663  // out of order.  Writes will of course be issued to the primary, but
  1664  // independent writes in the same Eventual session may also be made with
  1665  // independent connections, so there are also no guarantees in terms of
  1666  // write ordering (no read-your-writes guarantees either).
  1667  //
  1668  // The Eventual mode is the fastest and most resource-friendly, but is
  1669  // also the one offering the least guarantees about ordering of the data
  1670  // read and written.
  1671  //
  1672  // If refresh is true, in addition to ensuring the session is in the given
  1673  // consistency mode, the consistency guarantees will also be reset (e.g.
  1674  // a Monotonic session will be allowed to read from secondaries again).
  1675  // This is equivalent to calling the Refresh function.
  1676  //
  1677  // Shifting between Monotonic and Strong modes will keep a previously
  1678  // reserved connection for the session unless refresh is true or the
  1679  // connection is unsuitable (to a secondary server in a Strong session).
  1680  func (s *Session) SetMode(consistency Mode, refresh bool) {
  1681  	s.m.Lock()
  1682  	debugf("Session %p: setting mode %d with refresh=%v (master=%p, slave=%p)", s, consistency, refresh, s.masterSocket, s.slaveSocket)
  1683  	s.consistency = consistency
  1684  	if refresh {
  1685  		s.slaveOk = s.consistency != Strong
  1686  		s.unsetSocket()
  1687  	} else if s.consistency == Strong {
  1688  		s.slaveOk = false
  1689  	} else if s.masterSocket == nil {
  1690  		s.slaveOk = true
  1691  	}
  1692  	s.m.Unlock()
  1693  }
  1694  
  1695  // Mode returns the current consistency mode for the session.
  1696  func (s *Session) Mode() Mode {
  1697  	s.m.RLock()
  1698  	mode := s.consistency
  1699  	s.m.RUnlock()
  1700  	return mode
  1701  }
  1702  
  1703  // SetSyncTimeout sets the amount of time an operation with this session
  1704  // will wait before returning an error in case a connection to a usable
  1705  // server can't be established. Set it to zero to wait forever. The
  1706  // default value is 7 seconds.
  1707  func (s *Session) SetSyncTimeout(d time.Duration) {
  1708  	s.m.Lock()
  1709  	s.syncTimeout = d
  1710  	s.m.Unlock()
  1711  }
  1712  
  1713  // SetSocketTimeout sets the amount of time to wait for a non-responding
  1714  // socket to the database before it is forcefully closed.
  1715  //
  1716  // The default timeout is 1 minute.
  1717  func (s *Session) SetSocketTimeout(d time.Duration) {
  1718  	s.m.Lock()
  1719  	s.sockTimeout = d
  1720  	if s.masterSocket != nil {
  1721  		s.masterSocket.SetTimeout(d)
  1722  	}
  1723  	if s.slaveSocket != nil {
  1724  		s.slaveSocket.SetTimeout(d)
  1725  	}
  1726  	s.m.Unlock()
  1727  }
  1728  
  1729  // SetCursorTimeout changes the standard timeout period that the server
  1730  // enforces on created cursors. The only supported value right now is
  1731  // 0, which disables the timeout. The standard server timeout is 10 minutes.
  1732  func (s *Session) SetCursorTimeout(d time.Duration) {
  1733  	s.m.Lock()
  1734  	if d == 0 {
  1735  		s.queryConfig.op.flags |= flagNoCursorTimeout
  1736  	} else {
  1737  		panic("SetCursorTimeout: only 0 (disable timeout) supported for now")
  1738  	}
  1739  	s.m.Unlock()
  1740  }
  1741  
  1742  // SetPoolLimit sets the maximum number of sockets in use in a single server
  1743  // before this session will block waiting for a socket to be available.
  1744  // The default limit is 4096.
  1745  //
  1746  // This limit must be set to cover more than any expected workload of the
  1747  // application. It is a bad practice and an unsupported use case to use the
  1748  // database driver to define the concurrency limit of an application. Prevent
  1749  // such concurrency "at the door" instead, by properly restricting the amount
  1750  // of used resources and number of goroutines before they are created.
  1751  func (s *Session) SetPoolLimit(limit int) {
  1752  	s.m.Lock()
  1753  	s.poolLimit = limit
  1754  	s.m.Unlock()
  1755  }
  1756  
  1757  // SetBypassValidation sets whether the server should bypass the registered
  1758  // validation expressions executed when documents are inserted or modified,
  1759  // in the interest of preserving invariants in the collection being modified.
  1760  // The default is to not bypass, and thus to perform the validation
  1761  // expressions registered for modified collections.
  1762  //
  1763  // Document validation was introuced in MongoDB 3.2.
  1764  //
  1765  // Relevant documentation:
  1766  //
  1767  //   https://docs.mongodb.org/manual/release-notes/3.2/#bypass-validation
  1768  //
  1769  func (s *Session) SetBypassValidation(bypass bool) {
  1770  	s.m.Lock()
  1771  	s.bypassValidation = bypass
  1772  	s.m.Unlock()
  1773  }
  1774  
  1775  // SetBatch sets the default batch size used when fetching documents from the
  1776  // database. It's possible to change this setting on a per-query basis as
  1777  // well, using the Query.Batch method.
  1778  //
  1779  // The default batch size is defined by the database itself.  As of this
  1780  // writing, MongoDB will use an initial size of min(100 docs, 4MB) on the
  1781  // first batch, and 4MB on remaining ones.
  1782  func (s *Session) SetBatch(n int) {
  1783  	if n == 1 {
  1784  		// Server interprets 1 as -1 and closes the cursor (!?)
  1785  		n = 2
  1786  	}
  1787  	s.m.Lock()
  1788  	s.queryConfig.op.limit = int32(n)
  1789  	s.m.Unlock()
  1790  }
  1791  
  1792  // SetPrefetch sets the default point at which the next batch of results will be
  1793  // requested.  When there are p*batch_size remaining documents cached in an
  1794  // Iter, the next batch will be requested in background. For instance, when
  1795  // using this:
  1796  //
  1797  //     session.SetBatch(200)
  1798  //     session.SetPrefetch(0.25)
  1799  //
  1800  // and there are only 50 documents cached in the Iter to be processed, the
  1801  // next batch of 200 will be requested. It's possible to change this setting on
  1802  // a per-query basis as well, using the Prefetch method of Query.
  1803  //
  1804  // The default prefetch value is 0.25.
  1805  func (s *Session) SetPrefetch(p float64) {
  1806  	s.m.Lock()
  1807  	s.queryConfig.prefetch = p
  1808  	s.m.Unlock()
  1809  }
  1810  
  1811  // See SetSafe for details on the Safe type.
  1812  type Safe struct {
  1813  	W        int    // Min # of servers to ack before success
  1814  	WMode    string // Write mode for MongoDB 2.0+ (e.g. "majority")
  1815  	WTimeout int    // Milliseconds to wait for W before timing out
  1816  	FSync    bool   // Sync via the journal if present, or via data files sync otherwise
  1817  	J        bool   // Sync via the journal if present
  1818  }
  1819  
  1820  // Safe returns the current safety mode for the session.
  1821  func (s *Session) Safe() (safe *Safe) {
  1822  	s.m.Lock()
  1823  	defer s.m.Unlock()
  1824  	if s.safeOp != nil {
  1825  		cmd := s.safeOp.query.(*getLastError)
  1826  		safe = &Safe{WTimeout: cmd.WTimeout, FSync: cmd.FSync, J: cmd.J}
  1827  		switch w := cmd.W.(type) {
  1828  		case string:
  1829  			safe.WMode = w
  1830  		case int:
  1831  			safe.W = w
  1832  		}
  1833  	}
  1834  	return
  1835  }
  1836  
  1837  // SetSafe changes the session safety mode.
  1838  //
  1839  // If the safe parameter is nil, the session is put in unsafe mode, and writes
  1840  // become fire-and-forget, without error checking.  The unsafe mode is faster
  1841  // since operations won't hold on waiting for a confirmation.
  1842  //
  1843  // If the safe parameter is not nil, any changing query (insert, update, ...)
  1844  // will be followed by a getLastError command with the specified parameters,
  1845  // to ensure the request was correctly processed.
  1846  //
  1847  // The default is &Safe{}, meaning check for errors and use the default
  1848  // behavior for all fields.
  1849  //
  1850  // The safe.W parameter determines how many servers should confirm a write
  1851  // before the operation is considered successful.  If set to 0 or 1, the
  1852  // command will return as soon as the primary is done with the request.
  1853  // If safe.WTimeout is greater than zero, it determines how many milliseconds
  1854  // to wait for the safe.W servers to respond before returning an error.
  1855  //
  1856  // Starting with MongoDB 2.0.0 the safe.WMode parameter can be used instead
  1857  // of W to request for richer semantics. If set to "majority" the server will
  1858  // wait for a majority of members from the replica set to respond before
  1859  // returning. Custom modes may also be defined within the server to create
  1860  // very detailed placement schemas. See the data awareness documentation in
  1861  // the links below for more details (note that MongoDB internally reuses the
  1862  // "w" field name for WMode).
  1863  //
  1864  // If safe.J is true, servers will block until write operations have been
  1865  // committed to the journal. Cannot be used in combination with FSync. Prior
  1866  // to MongoDB 2.6 this option was ignored if the server was running without
  1867  // journaling. Starting with MongoDB 2.6 write operations will fail with an
  1868  // exception if this option is used when the server is running without
  1869  // journaling.
  1870  //
  1871  // If safe.FSync is true and the server is running without journaling, blocks
  1872  // until the server has synced all data files to disk. If the server is running
  1873  // with journaling, this acts the same as the J option, blocking until write
  1874  // operations have been committed to the journal. Cannot be used in
  1875  // combination with J.
  1876  //
  1877  // Since MongoDB 2.0.0, the safe.J option can also be used instead of FSync
  1878  // to force the server to wait for a group commit in case journaling is
  1879  // enabled. The option has no effect if the server has journaling disabled.
  1880  //
  1881  // For example, the following statement will make the session check for
  1882  // errors, without imposing further constraints:
  1883  //
  1884  //     session.SetSafe(&mgo.Safe{})
  1885  //
  1886  // The following statement will force the server to wait for a majority of
  1887  // members of a replica set to return (MongoDB 2.0+ only):
  1888  //
  1889  //     session.SetSafe(&mgo.Safe{WMode: "majority"})
  1890  //
  1891  // The following statement, on the other hand, ensures that at least two
  1892  // servers have flushed the change to disk before confirming the success
  1893  // of operations:
  1894  //
  1895  //     session.EnsureSafe(&mgo.Safe{W: 2, FSync: true})
  1896  //
  1897  // The following statement, on the other hand, disables the verification
  1898  // of errors entirely:
  1899  //
  1900  //     session.SetSafe(nil)
  1901  //
  1902  // See also the EnsureSafe method.
  1903  //
  1904  // Relevant documentation:
  1905  //
  1906  //     http://www.mongodb.org/display/DOCS/getLastError+Command
  1907  //     http://www.mongodb.org/display/DOCS/Verifying+Propagation+of+Writes+with+getLastError
  1908  //     http://www.mongodb.org/display/DOCS/Data+Center+Awareness
  1909  //
  1910  func (s *Session) SetSafe(safe *Safe) {
  1911  	s.m.Lock()
  1912  	s.safeOp = nil
  1913  	s.ensureSafe(safe)
  1914  	s.m.Unlock()
  1915  }
  1916  
  1917  // EnsureSafe compares the provided safety parameters with the ones
  1918  // currently in use by the session and picks the most conservative
  1919  // choice for each setting.
  1920  //
  1921  // That is:
  1922  //
  1923  //     - safe.WMode is always used if set.
  1924  //     - safe.W is used if larger than the current W and WMode is empty.
  1925  //     - safe.FSync is always used if true.
  1926  //     - safe.J is used if FSync is false.
  1927  //     - safe.WTimeout is used if set and smaller than the current WTimeout.
  1928  //
  1929  // For example, the following statement will ensure the session is
  1930  // at least checking for errors, without enforcing further constraints.
  1931  // If a more conservative SetSafe or EnsureSafe call was previously done,
  1932  // the following call will be ignored.
  1933  //
  1934  //     session.EnsureSafe(&mgo.Safe{})
  1935  //
  1936  // See also the SetSafe method for details on what each option means.
  1937  //
  1938  // Relevant documentation:
  1939  //
  1940  //     http://www.mongodb.org/display/DOCS/getLastError+Command
  1941  //     http://www.mongodb.org/display/DOCS/Verifying+Propagation+of+Writes+with+getLastError
  1942  //     http://www.mongodb.org/display/DOCS/Data+Center+Awareness
  1943  //
  1944  func (s *Session) EnsureSafe(safe *Safe) {
  1945  	s.m.Lock()
  1946  	s.ensureSafe(safe)
  1947  	s.m.Unlock()
  1948  }
  1949  
  1950  func (s *Session) ensureSafe(safe *Safe) {
  1951  	if safe == nil {
  1952  		return
  1953  	}
  1954  
  1955  	var w interface{}
  1956  	if safe.WMode != "" {
  1957  		w = safe.WMode
  1958  	} else if safe.W > 0 {
  1959  		w = safe.W
  1960  	}
  1961  
  1962  	var cmd getLastError
  1963  	if s.safeOp == nil {
  1964  		cmd = getLastError{1, w, safe.WTimeout, safe.FSync, safe.J}
  1965  	} else {
  1966  		// Copy.  We don't want to mutate the existing query.
  1967  		cmd = *(s.safeOp.query.(*getLastError))
  1968  		if cmd.W == nil {
  1969  			cmd.W = w
  1970  		} else if safe.WMode != "" {
  1971  			cmd.W = safe.WMode
  1972  		} else if i, ok := cmd.W.(int); ok && safe.W > i {
  1973  			cmd.W = safe.W
  1974  		}
  1975  		if safe.WTimeout > 0 && safe.WTimeout < cmd.WTimeout {
  1976  			cmd.WTimeout = safe.WTimeout
  1977  		}
  1978  		if safe.FSync {
  1979  			cmd.FSync = true
  1980  			cmd.J = false
  1981  		} else if safe.J && !cmd.FSync {
  1982  			cmd.J = true
  1983  		}
  1984  	}
  1985  	s.safeOp = &queryOp{
  1986  		query:      &cmd,
  1987  		collection: "admin.$cmd",
  1988  		limit:      -1,
  1989  	}
  1990  }
  1991  
  1992  // Run issues the provided command on the "admin" database and
  1993  // and unmarshals its result in the respective argument. The cmd
  1994  // argument may be either a string with the command name itself, in
  1995  // which case an empty document of the form bson.M{cmd: 1} will be used,
  1996  // or it may be a full command document.
  1997  //
  1998  // Note that MongoDB considers the first marshalled key as the command
  1999  // name, so when providing a command with options, it's important to
  2000  // use an ordering-preserving document, such as a struct value or an
  2001  // instance of bson.D.  For instance:
  2002  //
  2003  //     db.Run(bson.D{{"create", "mycollection"}, {"size", 1024}})
  2004  //
  2005  // For commands on arbitrary databases, see the Run method in
  2006  // the Database type.
  2007  //
  2008  // Relevant documentation:
  2009  //
  2010  //     http://www.mongodb.org/display/DOCS/Commands
  2011  //     http://www.mongodb.org/display/DOCS/List+of+Database+CommandSkips
  2012  //
  2013  func (s *Session) Run(cmd interface{}, result interface{}) error {
  2014  	return s.DB("admin").Run(cmd, result)
  2015  }
  2016  
  2017  // SelectServers restricts communication to servers configured with the
  2018  // given tags. For example, the following statement restricts servers
  2019  // used for reading operations to those with both tag "disk" set to
  2020  // "ssd" and tag "rack" set to 1:
  2021  //
  2022  //     session.SelectServers(bson.D{{"disk", "ssd"}, {"rack", 1}})
  2023  //
  2024  // Multiple sets of tags may be provided, in which case the used server
  2025  // must match all tags within any one set.
  2026  //
  2027  // If a connection was previously assigned to the session due to the
  2028  // current session mode (see Session.SetMode), the tag selection will
  2029  // only be enforced after the session is refreshed.
  2030  //
  2031  // Relevant documentation:
  2032  //
  2033  //     http://docs.mongodb.org/manual/tutorial/configure-replica-set-tag-sets
  2034  //
  2035  func (s *Session) SelectServers(tags ...bson.D) {
  2036  	s.m.Lock()
  2037  	s.queryConfig.op.serverTags = tags
  2038  	s.m.Unlock()
  2039  }
  2040  
  2041  // Ping runs a trivial ping command just to get in touch with the server.
  2042  func (s *Session) Ping() error {
  2043  	return s.Run("ping", nil)
  2044  }
  2045  
  2046  // Fsync flushes in-memory writes to disk on the server the session
  2047  // is established with. If async is true, the call returns immediately,
  2048  // otherwise it returns after the flush has been made.
  2049  func (s *Session) Fsync(async bool) error {
  2050  	return s.Run(bson.D{{"fsync", 1}, {"async", async}}, nil)
  2051  }
  2052  
  2053  // FsyncLock locks all writes in the specific server the session is
  2054  // established with and returns. Any writes attempted to the server
  2055  // after it is successfully locked will block until FsyncUnlock is
  2056  // called for the same server.
  2057  //
  2058  // This method works on secondaries as well, preventing the oplog from
  2059  // being flushed while the server is locked, but since only the server
  2060  // connected to is locked, for locking specific secondaries it may be
  2061  // necessary to establish a connection directly to the secondary (see
  2062  // Dial's connect=direct option).
  2063  //
  2064  // As an important caveat, note that once a write is attempted and
  2065  // blocks, follow up reads will block as well due to the way the
  2066  // lock is internally implemented in the server. More details at:
  2067  //
  2068  //     https://jira.mongodb.org/browse/SERVER-4243
  2069  //
  2070  // FsyncLock is often used for performing consistent backups of
  2071  // the database files on disk.
  2072  //
  2073  // Relevant documentation:
  2074  //
  2075  //     http://www.mongodb.org/display/DOCS/fsync+Command
  2076  //     http://www.mongodb.org/display/DOCS/Backups
  2077  //
  2078  func (s *Session) FsyncLock() error {
  2079  	return s.Run(bson.D{{"fsync", 1}, {"lock", true}}, nil)
  2080  }
  2081  
  2082  // FsyncUnlock releases the server for writes. See FsyncLock for details.
  2083  func (s *Session) FsyncUnlock() error {
  2084  	err := s.Run(bson.D{{"fsyncUnlock", 1}}, nil)
  2085  	if isNoCmd(err) {
  2086  		err = s.DB("admin").C("$cmd.sys.unlock").Find(nil).One(nil) // WTF?
  2087  	}
  2088  	return err
  2089  }
  2090  
  2091  // Find prepares a query using the provided document.  The document may be a
  2092  // map or a struct value capable of being marshalled with bson.  The map
  2093  // may be a generic one using interface{} for its key and/or values, such as
  2094  // bson.M, or it may be a properly typed map.  Providing nil as the document
  2095  // is equivalent to providing an empty document such as bson.M{}.
  2096  //
  2097  // Further details of the query may be tweaked using the resulting Query value,
  2098  // and then executed to retrieve results using methods such as One, For,
  2099  // Iter, or Tail.
  2100  //
  2101  // In case the resulting document includes a field named $err or errmsg, which
  2102  // are standard ways for MongoDB to return query errors, the returned err will
  2103  // be set to a *QueryError value including the Err message and the Code.  In
  2104  // those cases, the result argument is still unmarshalled into with the
  2105  // received document so that any other custom values may be obtained if
  2106  // desired.
  2107  //
  2108  // Relevant documentation:
  2109  //
  2110  //     http://www.mongodb.org/display/DOCS/Querying
  2111  //     http://www.mongodb.org/display/DOCS/Advanced+Queries
  2112  //
  2113  func (c *Collection) Find(query interface{}) *Query {
  2114  	session := c.Database.Session
  2115  	session.m.RLock()
  2116  	q := &Query{session: session, query: session.queryConfig}
  2117  	session.m.RUnlock()
  2118  	q.op.query = query
  2119  	q.op.collection = c.FullName
  2120  	return q
  2121  }
  2122  
  2123  type repairCmd struct {
  2124  	RepairCursor string           `bson:"repairCursor"`
  2125  	Cursor       *repairCmdCursor ",omitempty"
  2126  }
  2127  
  2128  type repairCmdCursor struct {
  2129  	BatchSize int `bson:"batchSize,omitempty"`
  2130  }
  2131  
  2132  // Repair returns an iterator that goes over all recovered documents in the
  2133  // collection, in a best-effort manner. This is most useful when there are
  2134  // damaged data files. Multiple copies of the same document may be returned
  2135  // by the iterator.
  2136  //
  2137  // Repair is supported in MongoDB 2.7.8 and later.
  2138  func (c *Collection) Repair() *Iter {
  2139  	// Clone session and set it to Monotonic mode so that the server
  2140  	// used for the query may be safely obtained afterwards, if
  2141  	// necessary for iteration when a cursor is received.
  2142  	session := c.Database.Session
  2143  	cloned := session.nonEventual()
  2144  	defer cloned.Close()
  2145  
  2146  	batchSize := int(cloned.queryConfig.op.limit)
  2147  
  2148  	var result struct{ Cursor cursorData }
  2149  
  2150  	cmd := repairCmd{
  2151  		RepairCursor: c.Name,
  2152  		Cursor:       &repairCmdCursor{batchSize},
  2153  	}
  2154  
  2155  	clonedc := c.With(cloned)
  2156  	err := clonedc.Database.Run(cmd, &result)
  2157  	return clonedc.NewIter(session, result.Cursor.FirstBatch, result.Cursor.Id, err)
  2158  }
  2159  
  2160  // FindId is a convenience helper equivalent to:
  2161  //
  2162  //     query := collection.Find(bson.M{"_id": id})
  2163  //
  2164  // See the Find method for more details.
  2165  func (c *Collection) FindId(id interface{}) *Query {
  2166  	return c.Find(bson.D{{"_id", id}})
  2167  }
  2168  
  2169  type Pipe struct {
  2170  	session    *Session
  2171  	collection *Collection
  2172  	pipeline   interface{}
  2173  	allowDisk  bool
  2174  	batchSize  int
  2175  }
  2176  
  2177  type pipeCmd struct {
  2178  	Aggregate string
  2179  	Pipeline  interface{}
  2180  	Cursor    *pipeCmdCursor ",omitempty"
  2181  	Explain   bool           ",omitempty"
  2182  	AllowDisk bool           "allowDiskUse,omitempty"
  2183  }
  2184  
  2185  type pipeCmdCursor struct {
  2186  	BatchSize int `bson:"batchSize,omitempty"`
  2187  }
  2188  
  2189  // Pipe prepares a pipeline to aggregate. The pipeline document
  2190  // must be a slice built in terms of the aggregation framework language.
  2191  //
  2192  // For example:
  2193  //
  2194  //     pipe := collection.Pipe([]bson.M{{"$match": bson.M{"name": "Otavio"}}})
  2195  //     iter := pipe.Iter()
  2196  //
  2197  // Relevant documentation:
  2198  //
  2199  //     http://docs.mongodb.org/manual/reference/aggregation
  2200  //     http://docs.mongodb.org/manual/applications/aggregation
  2201  //     http://docs.mongodb.org/manual/tutorial/aggregation-examples
  2202  //
  2203  func (c *Collection) Pipe(pipeline interface{}) *Pipe {
  2204  	session := c.Database.Session
  2205  	session.m.RLock()
  2206  	batchSize := int(session.queryConfig.op.limit)
  2207  	session.m.RUnlock()
  2208  	return &Pipe{
  2209  		session:    session,
  2210  		collection: c,
  2211  		pipeline:   pipeline,
  2212  		batchSize:  batchSize,
  2213  	}
  2214  }
  2215  
  2216  // Iter executes the pipeline and returns an iterator capable of going
  2217  // over all the generated results.
  2218  func (p *Pipe) Iter() *Iter {
  2219  	// Clone session and set it to Monotonic mode so that the server
  2220  	// used for the query may be safely obtained afterwards, if
  2221  	// necessary for iteration when a cursor is received.
  2222  	cloned := p.session.nonEventual()
  2223  	defer cloned.Close()
  2224  	c := p.collection.With(cloned)
  2225  
  2226  	var result struct {
  2227  		Result []bson.Raw // 2.4, no cursors.
  2228  		Cursor cursorData // 2.6+, with cursors.
  2229  	}
  2230  
  2231  	cmd := pipeCmd{
  2232  		Aggregate: c.Name,
  2233  		Pipeline:  p.pipeline,
  2234  		AllowDisk: p.allowDisk,
  2235  		Cursor:    &pipeCmdCursor{p.batchSize},
  2236  	}
  2237  	err := c.Database.Run(cmd, &result)
  2238  	if e, ok := err.(*QueryError); ok && e.Message == `unrecognized field "cursor` {
  2239  		cmd.Cursor = nil
  2240  		cmd.AllowDisk = false
  2241  		err = c.Database.Run(cmd, &result)
  2242  	}
  2243  	firstBatch := result.Result
  2244  	if firstBatch == nil {
  2245  		firstBatch = result.Cursor.FirstBatch
  2246  	}
  2247  	return c.NewIter(p.session, firstBatch, result.Cursor.Id, err)
  2248  }
  2249  
  2250  // NewIter returns a newly created iterator with the provided parameters.
  2251  // Using this method is not recommended unless the desired functionality
  2252  // is not yet exposed via a more convenient interface (Find, Pipe, etc).
  2253  //
  2254  // The optional session parameter associates the lifetime of the returned
  2255  // iterator to an arbitrary session. If nil, the iterator will be bound to
  2256  // c's session.
  2257  //
  2258  // Documents in firstBatch will be individually provided by the returned
  2259  // iterator before documents from cursorId are made available. If cursorId
  2260  // is zero, only the documents in firstBatch are provided.
  2261  //
  2262  // If err is not nil, the iterator's Err method will report it after
  2263  // exhausting documents in firstBatch.
  2264  //
  2265  // NewIter must be called right after the cursor id is obtained, and must not
  2266  // be called on a collection in Eventual mode, because the cursor id is
  2267  // associated with the specific server that returned it. The provided session
  2268  // parameter may be in any mode or state, though.
  2269  //
  2270  func (c *Collection) NewIter(session *Session, firstBatch []bson.Raw, cursorId int64, err error) *Iter {
  2271  	var server *mongoServer
  2272  	csession := c.Database.Session
  2273  	csession.m.RLock()
  2274  	socket := csession.masterSocket
  2275  	if socket == nil {
  2276  		socket = csession.slaveSocket
  2277  	}
  2278  	if socket != nil {
  2279  		server = socket.Server()
  2280  	}
  2281  	csession.m.RUnlock()
  2282  
  2283  	if server == nil {
  2284  		if csession.Mode() == Eventual {
  2285  			panic("Collection.NewIter called in Eventual mode")
  2286  		}
  2287  		if err == nil {
  2288  			err = errors.New("server not available")
  2289  		}
  2290  	}
  2291  
  2292  	if session == nil {
  2293  		session = csession
  2294  	}
  2295  
  2296  	iter := &Iter{
  2297  		session: session,
  2298  		server:  server,
  2299  		timeout: -1,
  2300  		err:     err,
  2301  	}
  2302  	iter.gotReply.L = &iter.m
  2303  	for _, doc := range firstBatch {
  2304  		iter.docData.Push(doc.Data)
  2305  	}
  2306  	if cursorId != 0 {
  2307  		iter.op.cursorId = cursorId
  2308  		iter.op.collection = c.FullName
  2309  		iter.op.replyFunc = iter.replyFunc()
  2310  	}
  2311  	return iter
  2312  }
  2313  
  2314  // All works like Iter.All.
  2315  func (p *Pipe) All(result interface{}) error {
  2316  	return p.Iter().All(result)
  2317  }
  2318  
  2319  // One executes the pipeline and unmarshals the first item from the
  2320  // result set into the result parameter.
  2321  // It returns ErrNotFound if no items are generated by the pipeline.
  2322  func (p *Pipe) One(result interface{}) error {
  2323  	iter := p.Iter()
  2324  	if iter.Next(result) {
  2325  		return nil
  2326  	}
  2327  	if err := iter.Err(); err != nil {
  2328  		return err
  2329  	}
  2330  	return ErrNotFound
  2331  }
  2332  
  2333  // Explain returns a number of details about how the MongoDB server would
  2334  // execute the requested pipeline, such as the number of objects examined,
  2335  // the number of times the read lock was yielded to allow writes to go in,
  2336  // and so on.
  2337  //
  2338  // For example:
  2339  //
  2340  //     var m bson.M
  2341  //     err := collection.Pipe(pipeline).Explain(&m)
  2342  //     if err == nil {
  2343  //         fmt.Printf("Explain: %#v\n", m)
  2344  //     }
  2345  //
  2346  func (p *Pipe) Explain(result interface{}) error {
  2347  	c := p.collection
  2348  	cmd := pipeCmd{
  2349  		Aggregate: c.Name,
  2350  		Pipeline:  p.pipeline,
  2351  		AllowDisk: p.allowDisk,
  2352  		Explain:   true,
  2353  	}
  2354  	return c.Database.Run(cmd, result)
  2355  }
  2356  
  2357  // AllowDiskUse enables writing to the "<dbpath>/_tmp" server directory so
  2358  // that aggregation pipelines do not have to be held entirely in memory.
  2359  func (p *Pipe) AllowDiskUse() *Pipe {
  2360  	p.allowDisk = true
  2361  	return p
  2362  }
  2363  
  2364  // Batch sets the batch size used when fetching documents from the database.
  2365  // It's possible to change this setting on a per-session basis as well, using
  2366  // the Batch method of Session.
  2367  //
  2368  // The default batch size is defined by the database server.
  2369  func (p *Pipe) Batch(n int) *Pipe {
  2370  	p.batchSize = n
  2371  	return p
  2372  }
  2373  
  2374  // mgo.v3: Use a single user-visible error type.
  2375  
  2376  type LastError struct {
  2377  	Err             string
  2378  	Code, N, Waited int
  2379  	FSyncFiles      int `bson:"fsyncFiles"`
  2380  	WTimeout        bool
  2381  	UpdatedExisting bool        `bson:"updatedExisting"`
  2382  	UpsertedId      interface{} `bson:"upserted"`
  2383  
  2384  	modified int
  2385  	ecases   []BulkErrorCase
  2386  }
  2387  
  2388  func (err *LastError) Error() string {
  2389  	return err.Err
  2390  }
  2391  
  2392  type queryError struct {
  2393  	Err           string "$err"
  2394  	ErrMsg        string
  2395  	Assertion     string
  2396  	Code          int
  2397  	AssertionCode int "assertionCode"
  2398  }
  2399  
  2400  type QueryError struct {
  2401  	Code      int
  2402  	Message   string
  2403  	Assertion bool
  2404  }
  2405  
  2406  func (err *QueryError) Error() string {
  2407  	return err.Message
  2408  }
  2409  
  2410  // IsDup returns whether err informs of a duplicate key error because
  2411  // a primary key index or a secondary unique index already has an entry
  2412  // with the given value.
  2413  func IsDup(err error) bool {
  2414  	// Besides being handy, helps with MongoDB bugs SERVER-7164 and SERVER-11493.
  2415  	// What follows makes me sad. Hopefully conventions will be more clear over time.
  2416  	switch e := err.(type) {
  2417  	case *LastError:
  2418  		return e.Code == 11000 || e.Code == 11001 || e.Code == 12582 || e.Code == 16460 && strings.Contains(e.Err, " E11000 ")
  2419  	case *QueryError:
  2420  		return e.Code == 11000 || e.Code == 11001 || e.Code == 12582
  2421  	case *BulkError:
  2422  		for _, ecase := range e.ecases {
  2423  			if !IsDup(ecase.Err) {
  2424  				return false
  2425  			}
  2426  		}
  2427  		return true
  2428  	}
  2429  	return false
  2430  }
  2431  
  2432  // Insert inserts one or more documents in the respective collection.  In
  2433  // case the session is in safe mode (see the SetSafe method) and an error
  2434  // happens while inserting the provided documents, the returned error will
  2435  // be of type *LastError.
  2436  func (c *Collection) Insert(docs ...interface{}) error {
  2437  	_, err := c.writeOp(&insertOp{c.FullName, docs, 0}, true)
  2438  	return err
  2439  }
  2440  
  2441  // Update finds a single document matching the provided selector document
  2442  // and modifies it according to the update document.
  2443  // If the session is in safe mode (see SetSafe) a ErrNotFound error is
  2444  // returned if a document isn't found, or a value of type *LastError
  2445  // when some other error is detected.
  2446  //
  2447  // Relevant documentation:
  2448  //
  2449  //     http://www.mongodb.org/display/DOCS/Updating
  2450  //     http://www.mongodb.org/display/DOCS/Atomic+Operations
  2451  //
  2452  func (c *Collection) Update(selector interface{}, update interface{}) error {
  2453  	if selector == nil {
  2454  		selector = bson.D{}
  2455  	}
  2456  	op := updateOp{
  2457  		Collection: c.FullName,
  2458  		Selector:   selector,
  2459  		Update:     update,
  2460  	}
  2461  	lerr, err := c.writeOp(&op, true)
  2462  	if err == nil && lerr != nil && !lerr.UpdatedExisting {
  2463  		return ErrNotFound
  2464  	}
  2465  	return err
  2466  }
  2467  
  2468  // UpdateId is a convenience helper equivalent to:
  2469  //
  2470  //     err := collection.Update(bson.M{"_id": id}, update)
  2471  //
  2472  // See the Update method for more details.
  2473  func (c *Collection) UpdateId(id interface{}, update interface{}) error {
  2474  	return c.Update(bson.D{{"_id", id}}, update)
  2475  }
  2476  
  2477  // ChangeInfo holds details about the outcome of an update operation.
  2478  type ChangeInfo struct {
  2479  	// Updated reports the number of existing documents modified.
  2480  	// Due to server limitations, this reports the same value as the Matched field when
  2481  	// talking to MongoDB <= 2.4 and on Upsert and Apply (findAndModify) operations.
  2482  	Updated    int
  2483  	Removed    int         // Number of documents removed
  2484  	Matched    int         // Number of documents matched but not necessarily changed
  2485  	UpsertedId interface{} // Upserted _id field, when not explicitly provided
  2486  }
  2487  
  2488  // UpdateAll finds all documents matching the provided selector document
  2489  // and modifies them according to the update document.
  2490  // If the session is in safe mode (see SetSafe) details of the executed
  2491  // operation are returned in info or an error of type *LastError when
  2492  // some problem is detected. It is not an error for the update to not be
  2493  // applied on any documents because the selector doesn't match.
  2494  //
  2495  // Relevant documentation:
  2496  //
  2497  //     http://www.mongodb.org/display/DOCS/Updating
  2498  //     http://www.mongodb.org/display/DOCS/Atomic+Operations
  2499  //
  2500  func (c *Collection) UpdateAll(selector interface{}, update interface{}) (info *ChangeInfo, err error) {
  2501  	if selector == nil {
  2502  		selector = bson.D{}
  2503  	}
  2504  	op := updateOp{
  2505  		Collection: c.FullName,
  2506  		Selector:   selector,
  2507  		Update:     update,
  2508  		Flags:      2,
  2509  		Multi:      true,
  2510  	}
  2511  	lerr, err := c.writeOp(&op, true)
  2512  	if err == nil && lerr != nil {
  2513  		info = &ChangeInfo{Updated: lerr.modified, Matched: lerr.N}
  2514  	}
  2515  	return info, err
  2516  }
  2517  
  2518  // Upsert finds a single document matching the provided selector document
  2519  // and modifies it according to the update document.  If no document matching
  2520  // the selector is found, the update document is applied to the selector
  2521  // document and the result is inserted in the collection.
  2522  // If the session is in safe mode (see SetSafe) details of the executed
  2523  // operation are returned in info, or an error of type *LastError when
  2524  // some problem is detected.
  2525  //
  2526  // Relevant documentation:
  2527  //
  2528  //     http://www.mongodb.org/display/DOCS/Updating
  2529  //     http://www.mongodb.org/display/DOCS/Atomic+Operations
  2530  //
  2531  func (c *Collection) Upsert(selector interface{}, update interface{}) (info *ChangeInfo, err error) {
  2532  	if selector == nil {
  2533  		selector = bson.D{}
  2534  	}
  2535  	op := updateOp{
  2536  		Collection: c.FullName,
  2537  		Selector:   selector,
  2538  		Update:     update,
  2539  		Flags:      1,
  2540  		Upsert:     true,
  2541  	}
  2542  	var lerr *LastError
  2543  	for i := 0; i < maxUpsertRetries; i++ {
  2544  		lerr, err = c.writeOp(&op, true)
  2545  		// Retry duplicate key errors on upserts.
  2546  		// https://docs.mongodb.com/v3.2/reference/method/db.collection.update/#use-unique-indexes
  2547  		if !IsDup(err) {
  2548  			break
  2549  		}
  2550  	}
  2551  	if err == nil && lerr != nil {
  2552  		info = &ChangeInfo{}
  2553  		if lerr.UpdatedExisting {
  2554  			info.Matched = lerr.N
  2555  			info.Updated = lerr.modified
  2556  		} else {
  2557  			info.UpsertedId = lerr.UpsertedId
  2558  		}
  2559  	}
  2560  	return info, err
  2561  }
  2562  
  2563  // UpsertId is a convenience helper equivalent to:
  2564  //
  2565  //     info, err := collection.Upsert(bson.M{"_id": id}, update)
  2566  //
  2567  // See the Upsert method for more details.
  2568  func (c *Collection) UpsertId(id interface{}, update interface{}) (info *ChangeInfo, err error) {
  2569  	return c.Upsert(bson.D{{"_id", id}}, update)
  2570  }
  2571  
  2572  // Remove finds a single document matching the provided selector document
  2573  // and removes it from the database.
  2574  // If the session is in safe mode (see SetSafe) a ErrNotFound error is
  2575  // returned if a document isn't found, or a value of type *LastError
  2576  // when some other error is detected.
  2577  //
  2578  // Relevant documentation:
  2579  //
  2580  //     http://www.mongodb.org/display/DOCS/Removing
  2581  //
  2582  func (c *Collection) Remove(selector interface{}) error {
  2583  	if selector == nil {
  2584  		selector = bson.D{}
  2585  	}
  2586  	lerr, err := c.writeOp(&deleteOp{c.FullName, selector, 1, 1}, true)
  2587  	if err == nil && lerr != nil && lerr.N == 0 {
  2588  		return ErrNotFound
  2589  	}
  2590  	return err
  2591  }
  2592  
  2593  // RemoveId is a convenience helper equivalent to:
  2594  //
  2595  //     err := collection.Remove(bson.M{"_id": id})
  2596  //
  2597  // See the Remove method for more details.
  2598  func (c *Collection) RemoveId(id interface{}) error {
  2599  	return c.Remove(bson.D{{"_id", id}})
  2600  }
  2601  
  2602  // RemoveAll finds all documents matching the provided selector document
  2603  // and removes them from the database.  In case the session is in safe mode
  2604  // (see the SetSafe method) and an error happens when attempting the change,
  2605  // the returned error will be of type *LastError.
  2606  //
  2607  // Relevant documentation:
  2608  //
  2609  //     http://www.mongodb.org/display/DOCS/Removing
  2610  //
  2611  func (c *Collection) RemoveAll(selector interface{}) (info *ChangeInfo, err error) {
  2612  	if selector == nil {
  2613  		selector = bson.D{}
  2614  	}
  2615  	lerr, err := c.writeOp(&deleteOp{c.FullName, selector, 0, 0}, true)
  2616  	if err == nil && lerr != nil {
  2617  		info = &ChangeInfo{Removed: lerr.N, Matched: lerr.N}
  2618  	}
  2619  	return info, err
  2620  }
  2621  
  2622  // DropDatabase removes the entire database including all of its collections.
  2623  func (db *Database) DropDatabase() error {
  2624  	return db.Run(bson.D{{"dropDatabase", 1}}, nil)
  2625  }
  2626  
  2627  // DropCollection removes the entire collection including all of its documents.
  2628  func (c *Collection) DropCollection() error {
  2629  	return c.Database.Run(bson.D{{"drop", c.Name}}, nil)
  2630  }
  2631  
  2632  // The CollectionInfo type holds metadata about a collection.
  2633  //
  2634  // Relevant documentation:
  2635  //
  2636  //     http://www.mongodb.org/display/DOCS/createCollection+Command
  2637  //     http://www.mongodb.org/display/DOCS/Capped+Collections
  2638  //
  2639  type CollectionInfo struct {
  2640  	// DisableIdIndex prevents the automatic creation of the index
  2641  	// on the _id field for the collection.
  2642  	DisableIdIndex bool
  2643  
  2644  	// ForceIdIndex enforces the automatic creation of the index
  2645  	// on the _id field for the collection. Capped collections,
  2646  	// for example, do not have such an index by default.
  2647  	ForceIdIndex bool
  2648  
  2649  	// If Capped is true new documents will replace old ones when
  2650  	// the collection is full. MaxBytes must necessarily be set
  2651  	// to define the size when the collection wraps around.
  2652  	// MaxDocs optionally defines the number of documents when it
  2653  	// wraps, but MaxBytes still needs to be set.
  2654  	Capped   bool
  2655  	MaxBytes int
  2656  	MaxDocs  int
  2657  
  2658  	// Validator contains a validation expression that defines which
  2659  	// documents should be considered valid for this collection.
  2660  	Validator interface{}
  2661  
  2662  	// ValidationLevel may be set to "strict" (the default) to force
  2663  	// MongoDB to validate all documents on inserts and updates, to
  2664  	// "moderate" to apply the validation rules only to documents
  2665  	// that already fulfill the validation criteria, or to "off" for
  2666  	// disabling validation entirely.
  2667  	ValidationLevel string
  2668  
  2669  	// ValidationAction determines how MongoDB handles documents that
  2670  	// violate the validation rules. It may be set to "error" (the default)
  2671  	// to reject inserts or updates that violate the rules, or to "warn"
  2672  	// to log invalid operations but allow them to proceed.
  2673  	ValidationAction string
  2674  
  2675  	// StorageEngine allows specifying collection options for the
  2676  	// storage engine in use. The map keys must hold the storage engine
  2677  	// name for which options are being specified.
  2678  	StorageEngine interface{}
  2679  }
  2680  
  2681  // Create explicitly creates the c collection with details of info.
  2682  // MongoDB creates collections automatically on use, so this method
  2683  // is only necessary when creating collection with non-default
  2684  // characteristics, such as capped collections.
  2685  //
  2686  // Relevant documentation:
  2687  //
  2688  //     http://www.mongodb.org/display/DOCS/createCollection+Command
  2689  //     http://www.mongodb.org/display/DOCS/Capped+Collections
  2690  //
  2691  func (c *Collection) Create(info *CollectionInfo) error {
  2692  	cmd := make(bson.D, 0, 4)
  2693  	cmd = append(cmd, bson.DocElem{"create", c.Name})
  2694  	if info.Capped {
  2695  		if info.MaxBytes < 1 {
  2696  			return fmt.Errorf("Collection.Create: with Capped, MaxBytes must also be set")
  2697  		}
  2698  		cmd = append(cmd, bson.DocElem{"capped", true})
  2699  		cmd = append(cmd, bson.DocElem{"size", info.MaxBytes})
  2700  		if info.MaxDocs > 0 {
  2701  			cmd = append(cmd, bson.DocElem{"max", info.MaxDocs})
  2702  		}
  2703  	}
  2704  	if info.DisableIdIndex {
  2705  		cmd = append(cmd, bson.DocElem{"autoIndexId", false})
  2706  	}
  2707  	if info.ForceIdIndex {
  2708  		cmd = append(cmd, bson.DocElem{"autoIndexId", true})
  2709  	}
  2710  	if info.Validator != nil {
  2711  		cmd = append(cmd, bson.DocElem{"validator", info.Validator})
  2712  	}
  2713  	if info.ValidationLevel != "" {
  2714  		cmd = append(cmd, bson.DocElem{"validationLevel", info.ValidationLevel})
  2715  	}
  2716  	if info.ValidationAction != "" {
  2717  		cmd = append(cmd, bson.DocElem{"validationAction", info.ValidationAction})
  2718  	}
  2719  	if info.StorageEngine != nil {
  2720  		cmd = append(cmd, bson.DocElem{"storageEngine", info.StorageEngine})
  2721  	}
  2722  	return c.Database.Run(cmd, nil)
  2723  }
  2724  
  2725  // Batch sets the batch size used when fetching documents from the database.
  2726  // It's possible to change this setting on a per-session basis as well, using
  2727  // the Batch method of Session.
  2728  
  2729  // The default batch size is defined by the database itself.  As of this
  2730  // writing, MongoDB will use an initial size of min(100 docs, 4MB) on the
  2731  // first batch, and 4MB on remaining ones.
  2732  func (q *Query) Batch(n int) *Query {
  2733  	if n == 1 {
  2734  		// Server interprets 1 as -1 and closes the cursor (!?)
  2735  		n = 2
  2736  	}
  2737  	q.m.Lock()
  2738  	q.op.limit = int32(n)
  2739  	q.m.Unlock()
  2740  	return q
  2741  }
  2742  
  2743  // Prefetch sets the point at which the next batch of results will be requested.
  2744  // When there are p*batch_size remaining documents cached in an Iter, the next
  2745  // batch will be requested in background. For instance, when using this:
  2746  //
  2747  //     query.Batch(200).Prefetch(0.25)
  2748  //
  2749  // and there are only 50 documents cached in the Iter to be processed, the
  2750  // next batch of 200 will be requested. It's possible to change this setting on
  2751  // a per-session basis as well, using the SetPrefetch method of Session.
  2752  //
  2753  // The default prefetch value is 0.25.
  2754  func (q *Query) Prefetch(p float64) *Query {
  2755  	q.m.Lock()
  2756  	q.prefetch = p
  2757  	q.m.Unlock()
  2758  	return q
  2759  }
  2760  
  2761  // Skip skips over the n initial documents from the query results.  Note that
  2762  // this only makes sense with capped collections where documents are naturally
  2763  // ordered by insertion time, or with sorted results.
  2764  func (q *Query) Skip(n int) *Query {
  2765  	q.m.Lock()
  2766  	q.op.skip = int32(n)
  2767  	q.m.Unlock()
  2768  	return q
  2769  }
  2770  
  2771  // Limit restricts the maximum number of documents retrieved to n, and also
  2772  // changes the batch size to the same value.  Once n documents have been
  2773  // returned by Next, the following call will return ErrNotFound.
  2774  func (q *Query) Limit(n int) *Query {
  2775  	q.m.Lock()
  2776  	switch {
  2777  	case n == 1:
  2778  		q.limit = 1
  2779  		q.op.limit = -1
  2780  	case n == math.MinInt32: // -MinInt32 == -MinInt32
  2781  		q.limit = math.MaxInt32
  2782  		q.op.limit = math.MinInt32 + 1
  2783  	case n < 0:
  2784  		q.limit = int32(-n)
  2785  		q.op.limit = int32(n)
  2786  	default:
  2787  		q.limit = int32(n)
  2788  		q.op.limit = int32(n)
  2789  	}
  2790  	q.m.Unlock()
  2791  	return q
  2792  }
  2793  
  2794  // Select enables selecting which fields should be retrieved for the results
  2795  // found. For example, the following query would only retrieve the name field:
  2796  //
  2797  //     err := collection.Find(nil).Select(bson.M{"name": 1}).One(&result)
  2798  //
  2799  // Relevant documentation:
  2800  //
  2801  //     http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields
  2802  //
  2803  func (q *Query) Select(selector interface{}) *Query {
  2804  	q.m.Lock()
  2805  	q.op.selector = selector
  2806  	q.m.Unlock()
  2807  	return q
  2808  }
  2809  
  2810  // Sort asks the database to order returned documents according to the
  2811  // provided field names. A field name may be prefixed by - (minus) for
  2812  // it to be sorted in reverse order.
  2813  //
  2814  // For example:
  2815  //
  2816  //     query1 := collection.Find(nil).Sort("firstname", "lastname")
  2817  //     query2 := collection.Find(nil).Sort("-age")
  2818  //     query3 := collection.Find(nil).Sort("$natural")
  2819  //     query4 := collection.Find(nil).Select(bson.M{"score": bson.M{"$meta": "textScore"}}).Sort("$textScore:score")
  2820  //
  2821  // Relevant documentation:
  2822  //
  2823  //     http://www.mongodb.org/display/DOCS/Sorting+and+Natural+Order
  2824  //
  2825  func (q *Query) Sort(fields ...string) *Query {
  2826  	q.m.Lock()
  2827  	var order bson.D
  2828  	for _, field := range fields {
  2829  		n := 1
  2830  		var kind string
  2831  		if field != "" {
  2832  			if field[0] == '$' {
  2833  				if c := strings.Index(field, ":"); c > 1 && c < len(field)-1 {
  2834  					kind = field[1:c]
  2835  					field = field[c+1:]
  2836  				}
  2837  			}
  2838  			switch field[0] {
  2839  			case '+':
  2840  				field = field[1:]
  2841  			case '-':
  2842  				n = -1
  2843  				field = field[1:]
  2844  			}
  2845  		}
  2846  		if field == "" {
  2847  			panic("Sort: empty field name")
  2848  		}
  2849  		if kind == "textScore" {
  2850  			order = append(order, bson.DocElem{field, bson.M{"$meta": kind}})
  2851  		} else {
  2852  			order = append(order, bson.DocElem{field, n})
  2853  		}
  2854  	}
  2855  	q.op.options.OrderBy = order
  2856  	q.op.hasOptions = true
  2857  	q.m.Unlock()
  2858  	return q
  2859  }
  2860  
  2861  // Explain returns a number of details about how the MongoDB server would
  2862  // execute the requested query, such as the number of objects examined,
  2863  // the number of times the read lock was yielded to allow writes to go in,
  2864  // and so on.
  2865  //
  2866  // For example:
  2867  //
  2868  //     m := bson.M{}
  2869  //     err := collection.Find(bson.M{"filename": name}).Explain(m)
  2870  //     if err == nil {
  2871  //         fmt.Printf("Explain: %#v\n", m)
  2872  //     }
  2873  //
  2874  // Relevant documentation:
  2875  //
  2876  //     http://www.mongodb.org/display/DOCS/Optimization
  2877  //     http://www.mongodb.org/display/DOCS/Query+Optimizer
  2878  //
  2879  func (q *Query) Explain(result interface{}) error {
  2880  	q.m.Lock()
  2881  	clone := &Query{session: q.session, query: q.query}
  2882  	q.m.Unlock()
  2883  	clone.op.options.Explain = true
  2884  	clone.op.hasOptions = true
  2885  	if clone.op.limit > 0 {
  2886  		clone.op.limit = -q.op.limit
  2887  	}
  2888  	iter := clone.Iter()
  2889  	if iter.Next(result) {
  2890  		return nil
  2891  	}
  2892  	return iter.Close()
  2893  }
  2894  
  2895  // TODO: Add Collection.Explain. See https://goo.gl/1MDlvz.
  2896  
  2897  // Hint will include an explicit "hint" in the query to force the server
  2898  // to use a specified index, potentially improving performance in some
  2899  // situations.  The provided parameters are the fields that compose the
  2900  // key of the index to be used.  For details on how the indexKey may be
  2901  // built, see the EnsureIndex method.
  2902  //
  2903  // For example:
  2904  //
  2905  //     query := collection.Find(bson.M{"firstname": "Joe", "lastname": "Winter"})
  2906  //     query.Hint("lastname", "firstname")
  2907  //
  2908  // Relevant documentation:
  2909  //
  2910  //     http://www.mongodb.org/display/DOCS/Optimization
  2911  //     http://www.mongodb.org/display/DOCS/Query+Optimizer
  2912  //
  2913  func (q *Query) Hint(indexKey ...string) *Query {
  2914  	q.m.Lock()
  2915  	keyInfo, err := parseIndexKey(indexKey)
  2916  	q.op.options.Hint = keyInfo.key
  2917  	q.op.hasOptions = true
  2918  	q.m.Unlock()
  2919  	if err != nil {
  2920  		panic(err)
  2921  	}
  2922  	return q
  2923  }
  2924  
  2925  // SetMaxScan constrains the query to stop after scanning the specified
  2926  // number of documents.
  2927  //
  2928  // This modifier is generally used to prevent potentially long running
  2929  // queries from disrupting performance by scanning through too much data.
  2930  func (q *Query) SetMaxScan(n int) *Query {
  2931  	q.m.Lock()
  2932  	q.op.options.MaxScan = n
  2933  	q.op.hasOptions = true
  2934  	q.m.Unlock()
  2935  	return q
  2936  }
  2937  
  2938  // SetMaxTime constrains the query to stop after running for the specified time.
  2939  //
  2940  // When the time limit is reached MongoDB automatically cancels the query.
  2941  // This can be used to efficiently prevent and identify unexpectedly slow queries.
  2942  //
  2943  // A few important notes about the mechanism enforcing this limit:
  2944  //
  2945  //  - Requests can block behind locking operations on the server, and that blocking
  2946  //    time is not accounted for. In other words, the timer starts ticking only after
  2947  //    the actual start of the query when it initially acquires the appropriate lock;
  2948  //
  2949  //  - Operations are interrupted only at interrupt points where an operation can be
  2950  //    safely aborted – the total execution time may exceed the specified value;
  2951  //
  2952  //  - The limit can be applied to both CRUD operations and commands, but not all
  2953  //    commands are interruptible;
  2954  //
  2955  //  - While iterating over results, computing follow up batches is included in the
  2956  //    total time and the iteration continues until the alloted time is over, but
  2957  //    network roundtrips are not taken into account for the limit.
  2958  //
  2959  //  - This limit does not override the inactive cursor timeout for idle cursors
  2960  //    (default is 10 min).
  2961  //
  2962  // This mechanism was introduced in MongoDB 2.6.
  2963  //
  2964  // Relevant documentation:
  2965  //
  2966  //   http://blog.mongodb.org/post/83621787773/maxtimems-and-query-optimizer-introspection-in
  2967  //
  2968  func (q *Query) SetMaxTime(d time.Duration) *Query {
  2969  	q.m.Lock()
  2970  	q.op.options.MaxTimeMS = int(d / time.Millisecond)
  2971  	q.op.hasOptions = true
  2972  	q.m.Unlock()
  2973  	return q
  2974  }
  2975  
  2976  // Snapshot will force the performed query to make use of an available
  2977  // index on the _id field to prevent the same document from being returned
  2978  // more than once in a single iteration. This might happen without this
  2979  // setting in situations when the document changes in size and thus has to
  2980  // be moved while the iteration is running.
  2981  //
  2982  // Because snapshot mode traverses the _id index, it may not be used with
  2983  // sorting or explicit hints. It also cannot use any other index for the
  2984  // query.
  2985  //
  2986  // Even with snapshot mode, items inserted or deleted during the query may
  2987  // or may not be returned; that is, this mode is not a true point-in-time
  2988  // snapshot.
  2989  //
  2990  // The same effect of Snapshot may be obtained by using any unique index on
  2991  // field(s) that will not be modified (best to use Hint explicitly too).
  2992  // A non-unique index (such as creation time) may be made unique by
  2993  // appending _id to the index when creating it.
  2994  //
  2995  // Relevant documentation:
  2996  //
  2997  //     http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database
  2998  //
  2999  func (q *Query) Snapshot() *Query {
  3000  	q.m.Lock()
  3001  	q.op.options.Snapshot = true
  3002  	q.op.hasOptions = true
  3003  	q.m.Unlock()
  3004  	return q
  3005  }
  3006  
  3007  // Comment adds a comment to the query to identify it in the database profiler output.
  3008  //
  3009  // Relevant documentation:
  3010  //
  3011  //     http://docs.mongodb.org/manual/reference/operator/meta/comment
  3012  //     http://docs.mongodb.org/manual/reference/command/profile
  3013  //     http://docs.mongodb.org/manual/administration/analyzing-mongodb-performance/#database-profiling
  3014  //
  3015  func (q *Query) Comment(comment string) *Query {
  3016  	q.m.Lock()
  3017  	q.op.options.Comment = comment
  3018  	q.op.hasOptions = true
  3019  	q.m.Unlock()
  3020  	return q
  3021  }
  3022  
  3023  // LogReplay enables an option that optimizes queries that are typically
  3024  // made on the MongoDB oplog for replaying it. This is an internal
  3025  // implementation aspect and most likely uninteresting for other uses.
  3026  // It has seen at least one use case, though, so it's exposed via the API.
  3027  func (q *Query) LogReplay() *Query {
  3028  	q.m.Lock()
  3029  	q.op.flags |= flagLogReplay
  3030  	q.m.Unlock()
  3031  	return q
  3032  }
  3033  
  3034  func checkQueryError(fullname string, d []byte) error {
  3035  	l := len(d)
  3036  	if l < 16 {
  3037  		return nil
  3038  	}
  3039  	if d[5] == '$' && d[6] == 'e' && d[7] == 'r' && d[8] == 'r' && d[9] == '\x00' && d[4] == '\x02' {
  3040  		goto Error
  3041  	}
  3042  	if len(fullname) < 5 || fullname[len(fullname)-5:] != ".$cmd" {
  3043  		return nil
  3044  	}
  3045  	for i := 0; i+8 < l; i++ {
  3046  		if d[i] == '\x02' && d[i+1] == 'e' && d[i+2] == 'r' && d[i+3] == 'r' && d[i+4] == 'm' && d[i+5] == 's' && d[i+6] == 'g' && d[i+7] == '\x00' {
  3047  			goto Error
  3048  		}
  3049  	}
  3050  	return nil
  3051  
  3052  Error:
  3053  	result := &queryError{}
  3054  	bson.Unmarshal(d, result)
  3055  	if result.Err == "" && result.ErrMsg == "" {
  3056  		return nil
  3057  	}
  3058  	if result.AssertionCode != 0 && result.Assertion != "" {
  3059  		return &QueryError{Code: result.AssertionCode, Message: result.Assertion, Assertion: true}
  3060  	}
  3061  	if result.Err != "" {
  3062  		return &QueryError{Code: result.Code, Message: result.Err}
  3063  	}
  3064  	return &QueryError{Code: result.Code, Message: result.ErrMsg}
  3065  }
  3066  
  3067  // One executes the query and unmarshals the first obtained document into the
  3068  // result argument.  The result must be a struct or map value capable of being
  3069  // unmarshalled into by gobson.  This function blocks until either a result
  3070  // is available or an error happens.  For example:
  3071  //
  3072  //     err := collection.Find(bson.M{"a": 1}).One(&result)
  3073  //
  3074  // In case the resulting document includes a field named $err or errmsg, which
  3075  // are standard ways for MongoDB to return query errors, the returned err will
  3076  // be set to a *QueryError value including the Err message and the Code.  In
  3077  // those cases, the result argument is still unmarshalled into with the
  3078  // received document so that any other custom values may be obtained if
  3079  // desired.
  3080  //
  3081  func (q *Query) One(result interface{}) (err error) {
  3082  	q.m.Lock()
  3083  	session := q.session
  3084  	op := q.op // Copy.
  3085  	q.m.Unlock()
  3086  
  3087  	socket, err := session.acquireSocket(true)
  3088  	if err != nil {
  3089  		return err
  3090  	}
  3091  	defer socket.Release()
  3092  
  3093  	op.limit = -1
  3094  
  3095  	session.prepareQuery(&op)
  3096  
  3097  	expectFindReply := prepareFindOp(socket, &op, 1)
  3098  
  3099  	data, err := socket.SimpleQuery(&op)
  3100  	if err != nil {
  3101  		return err
  3102  	}
  3103  	if data == nil {
  3104  		return ErrNotFound
  3105  	}
  3106  	if expectFindReply {
  3107  		var findReply struct {
  3108  			Ok     bool
  3109  			Code   int
  3110  			Errmsg string
  3111  			Cursor cursorData
  3112  		}
  3113  		err = bson.Unmarshal(data, &findReply)
  3114  		if err != nil {
  3115  			return err
  3116  		}
  3117  		if !findReply.Ok && findReply.Errmsg != "" {
  3118  			return &QueryError{Code: findReply.Code, Message: findReply.Errmsg}
  3119  		}
  3120  		if len(findReply.Cursor.FirstBatch) == 0 {
  3121  			return ErrNotFound
  3122  		}
  3123  		data = findReply.Cursor.FirstBatch[0].Data
  3124  	}
  3125  	if result != nil {
  3126  		err = bson.Unmarshal(data, result)
  3127  		if err == nil {
  3128  			debugf("Query %p document unmarshaled: %#v", q, result)
  3129  		} else {
  3130  			debugf("Query %p document unmarshaling failed: %#v", q, err)
  3131  			return err
  3132  		}
  3133  	}
  3134  	return checkQueryError(op.collection, data)
  3135  }
  3136  
  3137  // prepareFindOp translates op from being an old-style wire protocol query into
  3138  // a new-style find command if that's supported by the MongoDB server (3.2+).
  3139  // It returns whether to expect a find command result or not. Note op may be
  3140  // translated into an explain command, in which case the function returns false.
  3141  func prepareFindOp(socket *mongoSocket, op *queryOp, limit int32) bool {
  3142  	if socket.ServerInfo().MaxWireVersion < 4 || op.collection == "admin.$cmd" {
  3143  		return false
  3144  	}
  3145  
  3146  	nameDot := strings.Index(op.collection, ".")
  3147  	if nameDot < 0 {
  3148  		panic("invalid query collection name: " + op.collection)
  3149  	}
  3150  
  3151  	find := findCmd{
  3152  		Collection:  op.collection[nameDot+1:],
  3153  		Filter:      op.query,
  3154  		Projection:  op.selector,
  3155  		Sort:        op.options.OrderBy,
  3156  		Skip:        op.skip,
  3157  		Limit:       limit,
  3158  		MaxTimeMS:   op.options.MaxTimeMS,
  3159  		MaxScan:     op.options.MaxScan,
  3160  		Hint:        op.options.Hint,
  3161  		Comment:     op.options.Comment,
  3162  		Snapshot:    op.options.Snapshot,
  3163  		OplogReplay: op.flags&flagLogReplay != 0,
  3164  	}
  3165  	if op.limit < 0 {
  3166  		find.BatchSize = -op.limit
  3167  		find.SingleBatch = true
  3168  	} else {
  3169  		find.BatchSize = op.limit
  3170  	}
  3171  
  3172  	explain := op.options.Explain
  3173  
  3174  	op.collection = op.collection[:nameDot] + ".$cmd"
  3175  	op.query = &find
  3176  	op.skip = 0
  3177  	op.limit = -1
  3178  	op.options = queryWrapper{}
  3179  	op.hasOptions = false
  3180  
  3181  	if explain {
  3182  		op.query = bson.D{{"explain", op.query}}
  3183  		return false
  3184  	}
  3185  	return true
  3186  }
  3187  
  3188  type cursorData struct {
  3189  	FirstBatch []bson.Raw "firstBatch"
  3190  	NextBatch  []bson.Raw "nextBatch"
  3191  	NS         string
  3192  	Id         int64
  3193  }
  3194  
  3195  // findCmd holds the command used for performing queries on MongoDB 3.2+.
  3196  //
  3197  // Relevant documentation:
  3198  //
  3199  //     https://docs.mongodb.org/master/reference/command/find/#dbcmd.find
  3200  //
  3201  type findCmd struct {
  3202  	Collection          string      `bson:"find"`
  3203  	Filter              interface{} `bson:"filter,omitempty"`
  3204  	Sort                interface{} `bson:"sort,omitempty"`
  3205  	Projection          interface{} `bson:"projection,omitempty"`
  3206  	Hint                interface{} `bson:"hint,omitempty"`
  3207  	Skip                interface{} `bson:"skip,omitempty"`
  3208  	Limit               int32       `bson:"limit,omitempty"`
  3209  	BatchSize           int32       `bson:"batchSize,omitempty"`
  3210  	SingleBatch         bool        `bson:"singleBatch,omitempty"`
  3211  	Comment             string      `bson:"comment,omitempty"`
  3212  	MaxScan             int         `bson:"maxScan,omitempty"`
  3213  	MaxTimeMS           int         `bson:"maxTimeMS,omitempty"`
  3214  	ReadConcern         interface{} `bson:"readConcern,omitempty"`
  3215  	Max                 interface{} `bson:"max,omitempty"`
  3216  	Min                 interface{} `bson:"min,omitempty"`
  3217  	ReturnKey           bool        `bson:"returnKey,omitempty"`
  3218  	ShowRecordId        bool        `bson:"showRecordId,omitempty"`
  3219  	Snapshot            bool        `bson:"snapshot,omitempty"`
  3220  	Tailable            bool        `bson:"tailable,omitempty"`
  3221  	AwaitData           bool        `bson:"awaitData,omitempty"`
  3222  	OplogReplay         bool        `bson:"oplogReplay,omitempty"`
  3223  	NoCursorTimeout     bool        `bson:"noCursorTimeout,omitempty"`
  3224  	AllowPartialResults bool        `bson:"allowPartialResults,omitempty"`
  3225  }
  3226  
  3227  // getMoreCmd holds the command used for requesting more query results on MongoDB 3.2+.
  3228  //
  3229  // Relevant documentation:
  3230  //
  3231  //     https://docs.mongodb.org/master/reference/command/getMore/#dbcmd.getMore
  3232  //
  3233  type getMoreCmd struct {
  3234  	CursorId   int64  `bson:"getMore"`
  3235  	Collection string `bson:"collection"`
  3236  	BatchSize  int32  `bson:"batchSize,omitempty"`
  3237  	MaxTimeMS  int64  `bson:"maxTimeMS,omitempty"`
  3238  }
  3239  
  3240  // run duplicates the behavior of collection.Find(query).One(&result)
  3241  // as performed by Database.Run, specializing the logic for running
  3242  // database commands on a given socket.
  3243  func (db *Database) run(socket *mongoSocket, cmd, result interface{}) (err error) {
  3244  	// Database.Run:
  3245  	if name, ok := cmd.(string); ok {
  3246  		cmd = bson.D{{name, 1}}
  3247  	}
  3248  
  3249  	// Collection.Find:
  3250  	session := db.Session
  3251  	session.m.RLock()
  3252  	op := session.queryConfig.op // Copy.
  3253  	session.m.RUnlock()
  3254  	op.query = cmd
  3255  	op.collection = db.Name + ".$cmd"
  3256  
  3257  	// Query.One:
  3258  	session.prepareQuery(&op)
  3259  	op.limit = -1
  3260  
  3261  	data, err := socket.SimpleQuery(&op)
  3262  	if err != nil {
  3263  		return err
  3264  	}
  3265  	if data == nil {
  3266  		return ErrNotFound
  3267  	}
  3268  	if result != nil {
  3269  		err = bson.Unmarshal(data, result)
  3270  		if err != nil {
  3271  			debugf("Run command unmarshaling failed: %#v", op, err)
  3272  			return err
  3273  		}
  3274  		if globalDebug && globalLogger != nil {
  3275  			var res bson.M
  3276  			bson.Unmarshal(data, &res)
  3277  			debugf("Run command unmarshaled: %#v, result: %#v", op, res)
  3278  		}
  3279  	}
  3280  	return checkQueryError(op.collection, data)
  3281  }
  3282  
  3283  // The DBRef type implements support for the database reference MongoDB
  3284  // convention as supported by multiple drivers.  This convention enables
  3285  // cross-referencing documents between collections and databases using
  3286  // a structure which includes a collection name, a document id, and
  3287  // optionally a database name.
  3288  //
  3289  // See the FindRef methods on Session and on Database.
  3290  //
  3291  // Relevant documentation:
  3292  //
  3293  //     http://www.mongodb.org/display/DOCS/Database+References
  3294  //
  3295  type DBRef struct {
  3296  	Collection string      `bson:"$ref"`
  3297  	Id         interface{} `bson:"$id"`
  3298  	Database   string      `bson:"$db,omitempty"`
  3299  }
  3300  
  3301  // NOTE: Order of fields for DBRef above does matter, per documentation.
  3302  
  3303  // FindRef returns a query that looks for the document in the provided
  3304  // reference. If the reference includes the DB field, the document will
  3305  // be retrieved from the respective database.
  3306  //
  3307  // See also the DBRef type and the FindRef method on Session.
  3308  //
  3309  // Relevant documentation:
  3310  //
  3311  //     http://www.mongodb.org/display/DOCS/Database+References
  3312  //
  3313  func (db *Database) FindRef(ref *DBRef) *Query {
  3314  	var c *Collection
  3315  	if ref.Database == "" {
  3316  		c = db.C(ref.Collection)
  3317  	} else {
  3318  		c = db.Session.DB(ref.Database).C(ref.Collection)
  3319  	}
  3320  	return c.FindId(ref.Id)
  3321  }
  3322  
  3323  // FindRef returns a query that looks for the document in the provided
  3324  // reference. For a DBRef to be resolved correctly at the session level
  3325  // it must necessarily have the optional DB field defined.
  3326  //
  3327  // See also the DBRef type and the FindRef method on Database.
  3328  //
  3329  // Relevant documentation:
  3330  //
  3331  //     http://www.mongodb.org/display/DOCS/Database+References
  3332  //
  3333  func (s *Session) FindRef(ref *DBRef) *Query {
  3334  	if ref.Database == "" {
  3335  		panic(errors.New(fmt.Sprintf("Can't resolve database for %#v", ref)))
  3336  	}
  3337  	c := s.DB(ref.Database).C(ref.Collection)
  3338  	return c.FindId(ref.Id)
  3339  }
  3340  
  3341  // CollectionNames returns the collection names present in the db database.
  3342  func (db *Database) CollectionNames() (names []string, err error) {
  3343  	// Clone session and set it to Monotonic mode so that the server
  3344  	// used for the query may be safely obtained afterwards, if
  3345  	// necessary for iteration when a cursor is received.
  3346  	cloned := db.Session.nonEventual()
  3347  	defer cloned.Close()
  3348  
  3349  	batchSize := int(cloned.queryConfig.op.limit)
  3350  
  3351  	// Try with a command.
  3352  	var result struct {
  3353  		Collections []bson.Raw
  3354  		Cursor      cursorData
  3355  	}
  3356  	err = db.With(cloned).Run(bson.D{{"listCollections", 1}, {"cursor", bson.D{{"batchSize", batchSize}}}}, &result)
  3357  	if err == nil {
  3358  		firstBatch := result.Collections
  3359  		if firstBatch == nil {
  3360  			firstBatch = result.Cursor.FirstBatch
  3361  		}
  3362  		var iter *Iter
  3363  		ns := strings.SplitN(result.Cursor.NS, ".", 2)
  3364  		if len(ns) < 2 {
  3365  			iter = db.With(cloned).C("").NewIter(nil, firstBatch, result.Cursor.Id, nil)
  3366  		} else {
  3367  			iter = cloned.DB(ns[0]).C(ns[1]).NewIter(nil, firstBatch, result.Cursor.Id, nil)
  3368  		}
  3369  		var coll struct{ Name string }
  3370  		for iter.Next(&coll) {
  3371  			names = append(names, coll.Name)
  3372  		}
  3373  		if err := iter.Close(); err != nil {
  3374  			return nil, err
  3375  		}
  3376  		sort.Strings(names)
  3377  		return names, err
  3378  	}
  3379  	if err != nil && !isNoCmd(err) {
  3380  		return nil, err
  3381  	}
  3382  
  3383  	// Command not yet supported. Query the database instead.
  3384  	nameIndex := len(db.Name) + 1
  3385  	iter := db.C("system.namespaces").Find(nil).Iter()
  3386  	var coll struct{ Name string }
  3387  	for iter.Next(&coll) {
  3388  		if strings.Index(coll.Name, "$") < 0 || strings.Index(coll.Name, ".oplog.$") >= 0 {
  3389  			names = append(names, coll.Name[nameIndex:])
  3390  		}
  3391  	}
  3392  	if err := iter.Close(); err != nil {
  3393  		return nil, err
  3394  	}
  3395  	sort.Strings(names)
  3396  	return names, nil
  3397  }
  3398  
  3399  type dbNames struct {
  3400  	Databases []struct {
  3401  		Name  string
  3402  		Empty bool
  3403  	}
  3404  }
  3405  
  3406  // DatabaseNames returns the names of non-empty databases present in the cluster.
  3407  func (s *Session) DatabaseNames() (names []string, err error) {
  3408  	var result dbNames
  3409  	err = s.Run("listDatabases", &result)
  3410  	if err != nil {
  3411  		return nil, err
  3412  	}
  3413  	for _, db := range result.Databases {
  3414  		if !db.Empty {
  3415  			names = append(names, db.Name)
  3416  		}
  3417  	}
  3418  	sort.Strings(names)
  3419  	return names, nil
  3420  }
  3421  
  3422  // Iter executes the query and returns an iterator capable of going over all
  3423  // the results. Results will be returned in batches of configurable
  3424  // size (see the Batch method) and more documents will be requested when a
  3425  // configurable number of documents is iterated over (see the Prefetch method).
  3426  func (q *Query) Iter() *Iter {
  3427  	q.m.Lock()
  3428  	session := q.session
  3429  	op := q.op
  3430  	prefetch := q.prefetch
  3431  	limit := q.limit
  3432  	q.m.Unlock()
  3433  
  3434  	iter := &Iter{
  3435  		session:  session,
  3436  		prefetch: prefetch,
  3437  		limit:    limit,
  3438  		timeout:  -1,
  3439  	}
  3440  	iter.gotReply.L = &iter.m
  3441  	iter.op.collection = op.collection
  3442  	iter.op.limit = op.limit
  3443  	iter.op.replyFunc = iter.replyFunc()
  3444  	iter.docsToReceive++
  3445  
  3446  	socket, err := session.acquireSocket(true)
  3447  	if err != nil {
  3448  		iter.err = err
  3449  		return iter
  3450  	}
  3451  	defer socket.Release()
  3452  
  3453  	session.prepareQuery(&op)
  3454  	op.replyFunc = iter.op.replyFunc
  3455  
  3456  	if prepareFindOp(socket, &op, limit) {
  3457  		iter.findCmd = true
  3458  	}
  3459  
  3460  	iter.server = socket.Server()
  3461  	err = socket.Query(&op)
  3462  	if err != nil {
  3463  		// Must lock as the query is already out and it may call replyFunc.
  3464  		iter.m.Lock()
  3465  		iter.err = err
  3466  		iter.m.Unlock()
  3467  	}
  3468  
  3469  	return iter
  3470  }
  3471  
  3472  // Tail returns a tailable iterator. Unlike a normal iterator, a
  3473  // tailable iterator may wait for new values to be inserted in the
  3474  // collection once the end of the current result set is reached,
  3475  // A tailable iterator may only be used with capped collections.
  3476  //
  3477  // The timeout parameter indicates how long Next will block waiting
  3478  // for a result before timing out.  If set to -1, Next will not
  3479  // timeout, and will continue waiting for a result for as long as
  3480  // the cursor is valid and the session is not closed. If set to 0,
  3481  // Next times out as soon as it reaches the end of the result set.
  3482  // Otherwise, Next will wait for at least the given number of
  3483  // seconds for a new document to be available before timing out.
  3484  //
  3485  // On timeouts, Next will unblock and return false, and the Timeout
  3486  // method will return true if called. In these cases, Next may still
  3487  // be called again on the same iterator to check if a new value is
  3488  // available at the current cursor position, and again it will block
  3489  // according to the specified timeoutSecs. If the cursor becomes
  3490  // invalid, though, both Next and Timeout will return false and
  3491  // the query must be restarted.
  3492  //
  3493  // The following example demonstrates timeout handling and query
  3494  // restarting:
  3495  //
  3496  //    iter := collection.Find(nil).Sort("$natural").Tail(5 * time.Second)
  3497  //    for {
  3498  //         for iter.Next(&result) {
  3499  //             fmt.Println(result.Id)
  3500  //             lastId = result.Id
  3501  //         }
  3502  //         if iter.Err() != nil {
  3503  //             return iter.Close()
  3504  //         }
  3505  //         if iter.Timeout() {
  3506  //             continue
  3507  //         }
  3508  //         query := collection.Find(bson.M{"_id": bson.M{"$gt": lastId}})
  3509  //         iter = query.Sort("$natural").Tail(5 * time.Second)
  3510  //    }
  3511  //    iter.Close()
  3512  //
  3513  // Relevant documentation:
  3514  //
  3515  //     http://www.mongodb.org/display/DOCS/Tailable+Cursors
  3516  //     http://www.mongodb.org/display/DOCS/Capped+Collections
  3517  //     http://www.mongodb.org/display/DOCS/Sorting+and+Natural+Order
  3518  //
  3519  func (q *Query) Tail(timeout time.Duration) *Iter {
  3520  	q.m.Lock()
  3521  	session := q.session
  3522  	op := q.op
  3523  	prefetch := q.prefetch
  3524  	q.m.Unlock()
  3525  
  3526  	iter := &Iter{session: session, prefetch: prefetch}
  3527  	iter.gotReply.L = &iter.m
  3528  	iter.timeout = timeout
  3529  	iter.op.collection = op.collection
  3530  	iter.op.limit = op.limit
  3531  	iter.op.replyFunc = iter.replyFunc()
  3532  	iter.docsToReceive++
  3533  	session.prepareQuery(&op)
  3534  	op.replyFunc = iter.op.replyFunc
  3535  	op.flags |= flagTailable | flagAwaitData
  3536  
  3537  	socket, err := session.acquireSocket(true)
  3538  	if err != nil {
  3539  		iter.err = err
  3540  	} else {
  3541  		iter.server = socket.Server()
  3542  		err = socket.Query(&op)
  3543  		if err != nil {
  3544  			// Must lock as the query is already out and it may call replyFunc.
  3545  			iter.m.Lock()
  3546  			iter.err = err
  3547  			iter.m.Unlock()
  3548  		}
  3549  		socket.Release()
  3550  	}
  3551  	return iter
  3552  }
  3553  
  3554  func (s *Session) prepareQuery(op *queryOp) {
  3555  	s.m.RLock()
  3556  	op.mode = s.consistency
  3557  	if s.slaveOk {
  3558  		op.flags |= flagSlaveOk
  3559  	}
  3560  	s.m.RUnlock()
  3561  	return
  3562  }
  3563  
  3564  // Err returns nil if no errors happened during iteration, or the actual
  3565  // error otherwise.
  3566  //
  3567  // In case a resulting document included a field named $err or errmsg, which are
  3568  // standard ways for MongoDB to report an improper query, the returned value has
  3569  // a *QueryError type, and includes the Err message and the Code.
  3570  func (iter *Iter) Err() error {
  3571  	iter.m.Lock()
  3572  	err := iter.err
  3573  	iter.m.Unlock()
  3574  	if err == ErrNotFound {
  3575  		return nil
  3576  	}
  3577  	return err
  3578  }
  3579  
  3580  // Close kills the server cursor used by the iterator, if any, and returns
  3581  // nil if no errors happened during iteration, or the actual error otherwise.
  3582  //
  3583  // Server cursors are automatically closed at the end of an iteration, which
  3584  // means close will do nothing unless the iteration was interrupted before
  3585  // the server finished sending results to the driver. If Close is not called
  3586  // in such a situation, the cursor will remain available at the server until
  3587  // the default cursor timeout period is reached. No further problems arise.
  3588  //
  3589  // Close is idempotent. That means it can be called repeatedly and will
  3590  // return the same result every time.
  3591  //
  3592  // In case a resulting document included a field named $err or errmsg, which are
  3593  // standard ways for MongoDB to report an improper query, the returned value has
  3594  // a *QueryError type.
  3595  func (iter *Iter) Close() error {
  3596  	iter.m.Lock()
  3597  	cursorId := iter.op.cursorId
  3598  	iter.op.cursorId = 0
  3599  	err := iter.err
  3600  	iter.m.Unlock()
  3601  	if cursorId == 0 {
  3602  		if err == ErrNotFound {
  3603  			return nil
  3604  		}
  3605  		return err
  3606  	}
  3607  	socket, err := iter.acquireSocket()
  3608  	if err == nil {
  3609  		// TODO Batch kills.
  3610  		err = socket.Query(&killCursorsOp{[]int64{cursorId}})
  3611  		socket.Release()
  3612  	}
  3613  
  3614  	iter.m.Lock()
  3615  	if err != nil && (iter.err == nil || iter.err == ErrNotFound) {
  3616  		iter.err = err
  3617  	} else if iter.err != ErrNotFound {
  3618  		err = iter.err
  3619  	}
  3620  	iter.m.Unlock()
  3621  	return err
  3622  }
  3623  
  3624  // Done returns true only if a follow up Next call is guaranteed
  3625  // to return false.
  3626  //
  3627  // For an iterator created with Tail, Done may return false for
  3628  // an iterator that has no more data. Otherwise it's guaranteed
  3629  // to return false only if there is data or an error happened.
  3630  //
  3631  // Done may block waiting for a pending query to verify whether
  3632  // more data is actually available or not.
  3633  func (iter *Iter) Done() bool {
  3634  	iter.m.Lock()
  3635  	defer iter.m.Unlock()
  3636  
  3637  	for {
  3638  		if iter.docData.Len() > 0 {
  3639  			return false
  3640  		}
  3641  		if iter.docsToReceive > 1 {
  3642  			return true
  3643  		}
  3644  		if iter.docsToReceive > 0 {
  3645  			iter.gotReply.Wait()
  3646  			continue
  3647  		}
  3648  		return iter.op.cursorId == 0
  3649  	}
  3650  }
  3651  
  3652  // Timeout returns true if Next returned false due to a timeout of
  3653  // a tailable cursor. In those cases, Next may be called again to continue
  3654  // the iteration at the previous cursor position.
  3655  func (iter *Iter) Timeout() bool {
  3656  	iter.m.Lock()
  3657  	result := iter.timedout
  3658  	iter.m.Unlock()
  3659  	return result
  3660  }
  3661  
  3662  // Next retrieves the next document from the result set, blocking if necessary.
  3663  // This method will also automatically retrieve another batch of documents from
  3664  // the server when the current one is exhausted, or before that in background
  3665  // if pre-fetching is enabled (see the Query.Prefetch and Session.SetPrefetch
  3666  // methods).
  3667  //
  3668  // Next returns true if a document was successfully unmarshalled onto result,
  3669  // and false at the end of the result set or if an error happened.
  3670  // When Next returns false, the Err method should be called to verify if
  3671  // there was an error during iteration.
  3672  //
  3673  // For example:
  3674  //
  3675  //    iter := collection.Find(nil).Iter()
  3676  //    for iter.Next(&result) {
  3677  //        fmt.Printf("Result: %v\n", result.Id)
  3678  //    }
  3679  //    if err := iter.Close(); err != nil {
  3680  //        return err
  3681  //    }
  3682  //
  3683  func (iter *Iter) Next(result interface{}) bool {
  3684  	iter.m.Lock()
  3685  	iter.timedout = false
  3686  	timeout := time.Time{}
  3687  	for iter.err == nil && iter.docData.Len() == 0 && (iter.docsToReceive > 0 || iter.op.cursorId != 0) {
  3688  		if iter.docsToReceive == 0 {
  3689  			if iter.timeout >= 0 {
  3690  				if timeout.IsZero() {
  3691  					timeout = time.Now().Add(iter.timeout)
  3692  				}
  3693  				if time.Now().After(timeout) {
  3694  					iter.timedout = true
  3695  					iter.m.Unlock()
  3696  					return false
  3697  				}
  3698  			}
  3699  			iter.getMore()
  3700  			if iter.err != nil {
  3701  				break
  3702  			}
  3703  		}
  3704  		iter.gotReply.Wait()
  3705  	}
  3706  
  3707  	// Exhaust available data before reporting any errors.
  3708  	if docData, ok := iter.docData.Pop().([]byte); ok {
  3709  		close := false
  3710  		if iter.limit > 0 {
  3711  			iter.limit--
  3712  			if iter.limit == 0 {
  3713  				if iter.docData.Len() > 0 {
  3714  					iter.m.Unlock()
  3715  					panic(fmt.Errorf("data remains after limit exhausted: %d", iter.docData.Len()))
  3716  				}
  3717  				iter.err = ErrNotFound
  3718  				close = true
  3719  			}
  3720  		}
  3721  		if iter.op.cursorId != 0 && iter.err == nil {
  3722  			iter.docsBeforeMore--
  3723  			if iter.docsBeforeMore == -1 {
  3724  				iter.getMore()
  3725  			}
  3726  		}
  3727  		iter.m.Unlock()
  3728  
  3729  		if close {
  3730  			iter.Close()
  3731  		}
  3732  		err := bson.Unmarshal(docData, result)
  3733  		if err != nil {
  3734  			debugf("Iter %p document unmarshaling failed: %#v", iter, err)
  3735  			iter.m.Lock()
  3736  			if iter.err == nil {
  3737  				iter.err = err
  3738  			}
  3739  			iter.m.Unlock()
  3740  			return false
  3741  		}
  3742  		debugf("Iter %p document unmarshaled: %#v", iter, result)
  3743  		// XXX Only have to check first document for a query error?
  3744  		err = checkQueryError(iter.op.collection, docData)
  3745  		if err != nil {
  3746  			iter.m.Lock()
  3747  			if iter.err == nil {
  3748  				iter.err = err
  3749  			}
  3750  			iter.m.Unlock()
  3751  			return false
  3752  		}
  3753  		return true
  3754  	} else if iter.err != nil {
  3755  		debugf("Iter %p returning false: %s", iter, iter.err)
  3756  		iter.m.Unlock()
  3757  		return false
  3758  	} else if iter.op.cursorId == 0 {
  3759  		iter.err = ErrNotFound
  3760  		debugf("Iter %p exhausted with cursor=0", iter)
  3761  		iter.m.Unlock()
  3762  		return false
  3763  	}
  3764  
  3765  	panic("unreachable")
  3766  }
  3767  
  3768  // All retrieves all documents from the result set into the provided slice
  3769  // and closes the iterator.
  3770  //
  3771  // The result argument must necessarily be the address for a slice. The slice
  3772  // may be nil or previously allocated.
  3773  //
  3774  // WARNING: Obviously, All must not be used with result sets that may be
  3775  // potentially large, since it may consume all memory until the system
  3776  // crashes. Consider building the query with a Limit clause to ensure the
  3777  // result size is bounded.
  3778  //
  3779  // For instance:
  3780  //
  3781  //    var result []struct{ Value int }
  3782  //    iter := collection.Find(nil).Limit(100).Iter()
  3783  //    err := iter.All(&result)
  3784  //    if err != nil {
  3785  //        return err
  3786  //    }
  3787  //
  3788  func (iter *Iter) All(result interface{}) error {
  3789  	resultv := reflect.ValueOf(result)
  3790  	if resultv.Kind() != reflect.Ptr || resultv.Elem().Kind() != reflect.Slice {
  3791  		panic("result argument must be a slice address")
  3792  	}
  3793  	slicev := resultv.Elem()
  3794  	slicev = slicev.Slice(0, slicev.Cap())
  3795  	elemt := slicev.Type().Elem()
  3796  	i := 0
  3797  	for {
  3798  		if slicev.Len() == i {
  3799  			elemp := reflect.New(elemt)
  3800  			if !iter.Next(elemp.Interface()) {
  3801  				break
  3802  			}
  3803  			slicev = reflect.Append(slicev, elemp.Elem())
  3804  			slicev = slicev.Slice(0, slicev.Cap())
  3805  		} else {
  3806  			if !iter.Next(slicev.Index(i).Addr().Interface()) {
  3807  				break
  3808  			}
  3809  		}
  3810  		i++
  3811  	}
  3812  	resultv.Elem().Set(slicev.Slice(0, i))
  3813  	return iter.Close()
  3814  }
  3815  
  3816  // All works like Iter.All.
  3817  func (q *Query) All(result interface{}) error {
  3818  	return q.Iter().All(result)
  3819  }
  3820  
  3821  // The For method is obsolete and will be removed in a future release.
  3822  // See Iter as an elegant replacement.
  3823  func (q *Query) For(result interface{}, f func() error) error {
  3824  	return q.Iter().For(result, f)
  3825  }
  3826  
  3827  // The For method is obsolete and will be removed in a future release.
  3828  // See Iter as an elegant replacement.
  3829  func (iter *Iter) For(result interface{}, f func() error) (err error) {
  3830  	valid := false
  3831  	v := reflect.ValueOf(result)
  3832  	if v.Kind() == reflect.Ptr {
  3833  		v = v.Elem()
  3834  		switch v.Kind() {
  3835  		case reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
  3836  			valid = v.IsNil()
  3837  		}
  3838  	}
  3839  	if !valid {
  3840  		panic("For needs a pointer to nil reference value.  See the documentation.")
  3841  	}
  3842  	zero := reflect.Zero(v.Type())
  3843  	for {
  3844  		v.Set(zero)
  3845  		if !iter.Next(result) {
  3846  			break
  3847  		}
  3848  		err = f()
  3849  		if err != nil {
  3850  			return err
  3851  		}
  3852  	}
  3853  	return iter.Err()
  3854  }
  3855  
  3856  // acquireSocket acquires a socket from the same server that the iterator
  3857  // cursor was obtained from.
  3858  //
  3859  // WARNING: This method must not be called with iter.m locked. Acquiring the
  3860  // socket depends on the cluster sync loop, and the cluster sync loop might
  3861  // attempt actions which cause replyFunc to be called, inducing a deadlock.
  3862  func (iter *Iter) acquireSocket() (*mongoSocket, error) {
  3863  	socket, err := iter.session.acquireSocket(true)
  3864  	if err != nil {
  3865  		return nil, err
  3866  	}
  3867  	if socket.Server() != iter.server {
  3868  		// Socket server changed during iteration. This may happen
  3869  		// with Eventual sessions, if a Refresh is done, or if a
  3870  		// monotonic session gets a write and shifts from secondary
  3871  		// to primary. Our cursor is in a specific server, though.
  3872  		iter.session.m.Lock()
  3873  		sockTimeout := iter.session.sockTimeout
  3874  		iter.session.m.Unlock()
  3875  		socket.Release()
  3876  		socket, _, err = iter.server.AcquireSocket(0, sockTimeout)
  3877  		if err != nil {
  3878  			return nil, err
  3879  		}
  3880  		err := iter.session.socketLogin(socket)
  3881  		if err != nil {
  3882  			socket.Release()
  3883  			return nil, err
  3884  		}
  3885  	}
  3886  	return socket, nil
  3887  }
  3888  
  3889  func (iter *Iter) getMore() {
  3890  	// Increment now so that unlocking the iterator won't cause a
  3891  	// different goroutine to get here as well.
  3892  	iter.docsToReceive++
  3893  	iter.m.Unlock()
  3894  	socket, err := iter.acquireSocket()
  3895  	iter.m.Lock()
  3896  	if err != nil {
  3897  		iter.err = err
  3898  		return
  3899  	}
  3900  	defer socket.Release()
  3901  
  3902  	debugf("Iter %p requesting more documents", iter)
  3903  	if iter.limit > 0 {
  3904  		// The -1 below accounts for the fact docsToReceive was incremented above.
  3905  		limit := iter.limit - int32(iter.docsToReceive-1) - int32(iter.docData.Len())
  3906  		if limit < iter.op.limit {
  3907  			iter.op.limit = limit
  3908  		}
  3909  	}
  3910  	var op interface{}
  3911  	if iter.findCmd {
  3912  		op = iter.getMoreCmd()
  3913  	} else {
  3914  		op = &iter.op
  3915  	}
  3916  	if err := socket.Query(op); err != nil {
  3917  		iter.docsToReceive--
  3918  		iter.err = err
  3919  	}
  3920  }
  3921  
  3922  func (iter *Iter) getMoreCmd() *queryOp {
  3923  	// TODO: Define the query statically in the Iter type, next to getMoreOp.
  3924  	nameDot := strings.Index(iter.op.collection, ".")
  3925  	if nameDot < 0 {
  3926  		panic("invalid query collection name: " + iter.op.collection)
  3927  	}
  3928  
  3929  	getMore := getMoreCmd{
  3930  		CursorId:   iter.op.cursorId,
  3931  		Collection: iter.op.collection[nameDot+1:],
  3932  		BatchSize:  iter.op.limit,
  3933  	}
  3934  
  3935  	var op queryOp
  3936  	op.collection = iter.op.collection[:nameDot] + ".$cmd"
  3937  	op.query = &getMore
  3938  	op.limit = -1
  3939  	op.replyFunc = iter.op.replyFunc
  3940  	return &op
  3941  }
  3942  
  3943  type countCmd struct {
  3944  	Count string
  3945  	Query interface{}
  3946  	Limit int32 ",omitempty"
  3947  	Skip  int32 ",omitempty"
  3948  }
  3949  
  3950  // Count returns the total number of documents in the result set.
  3951  func (q *Query) Count() (n int, err error) {
  3952  	q.m.Lock()
  3953  	session := q.session
  3954  	op := q.op
  3955  	limit := q.limit
  3956  	q.m.Unlock()
  3957  
  3958  	c := strings.Index(op.collection, ".")
  3959  	if c < 0 {
  3960  		return 0, errors.New("Bad collection name: " + op.collection)
  3961  	}
  3962  
  3963  	dbname := op.collection[:c]
  3964  	cname := op.collection[c+1:]
  3965  	query := op.query
  3966  	if query == nil {
  3967  		query = bson.D{}
  3968  	}
  3969  	result := struct{ N int }{}
  3970  	err = session.DB(dbname).Run(countCmd{cname, query, limit, op.skip}, &result)
  3971  	return result.N, err
  3972  }
  3973  
  3974  // Count returns the total number of documents in the collection.
  3975  func (c *Collection) Count() (n int, err error) {
  3976  	return c.Find(nil).Count()
  3977  }
  3978  
  3979  type distinctCmd struct {
  3980  	Collection string "distinct"
  3981  	Key        string
  3982  	Query      interface{} ",omitempty"
  3983  }
  3984  
  3985  // Distinct unmarshals into result the list of distinct values for the given key.
  3986  //
  3987  // For example:
  3988  //
  3989  //     var result []int
  3990  //     err := collection.Find(bson.M{"gender": "F"}).Distinct("age", &result)
  3991  //
  3992  // Relevant documentation:
  3993  //
  3994  //     http://www.mongodb.org/display/DOCS/Aggregation
  3995  //
  3996  func (q *Query) Distinct(key string, result interface{}) error {
  3997  	q.m.Lock()
  3998  	session := q.session
  3999  	op := q.op // Copy.
  4000  	q.m.Unlock()
  4001  
  4002  	c := strings.Index(op.collection, ".")
  4003  	if c < 0 {
  4004  		return errors.New("Bad collection name: " + op.collection)
  4005  	}
  4006  
  4007  	dbname := op.collection[:c]
  4008  	cname := op.collection[c+1:]
  4009  
  4010  	var doc struct{ Values bson.Raw }
  4011  	err := session.DB(dbname).Run(distinctCmd{cname, key, op.query}, &doc)
  4012  	if err != nil {
  4013  		return err
  4014  	}
  4015  	return doc.Values.Unmarshal(result)
  4016  }
  4017  
  4018  type mapReduceCmd struct {
  4019  	Collection string "mapreduce"
  4020  	Map        string ",omitempty"
  4021  	Reduce     string ",omitempty"
  4022  	Finalize   string ",omitempty"
  4023  	Limit      int32  ",omitempty"
  4024  	Out        interface{}
  4025  	Query      interface{} ",omitempty"
  4026  	Sort       interface{} ",omitempty"
  4027  	Scope      interface{} ",omitempty"
  4028  	Verbose    bool        ",omitempty"
  4029  }
  4030  
  4031  type mapReduceResult struct {
  4032  	Results    bson.Raw
  4033  	Result     bson.Raw
  4034  	TimeMillis int64 "timeMillis"
  4035  	Counts     struct{ Input, Emit, Output int }
  4036  	Ok         bool
  4037  	Err        string
  4038  	Timing     *MapReduceTime
  4039  }
  4040  
  4041  type MapReduce struct {
  4042  	Map      string      // Map Javascript function code (required)
  4043  	Reduce   string      // Reduce Javascript function code (required)
  4044  	Finalize string      // Finalize Javascript function code (optional)
  4045  	Out      interface{} // Output collection name or document. If nil, results are inlined into the result parameter.
  4046  	Scope    interface{} // Optional global scope for Javascript functions
  4047  	Verbose  bool
  4048  }
  4049  
  4050  type MapReduceInfo struct {
  4051  	InputCount  int            // Number of documents mapped
  4052  	EmitCount   int            // Number of times reduce called emit
  4053  	OutputCount int            // Number of documents in resulting collection
  4054  	Database    string         // Output database, if results are not inlined
  4055  	Collection  string         // Output collection, if results are not inlined
  4056  	Time        int64          // Time to run the job, in nanoseconds
  4057  	VerboseTime *MapReduceTime // Only defined if Verbose was true
  4058  }
  4059  
  4060  type MapReduceTime struct {
  4061  	Total    int64 // Total time, in nanoseconds
  4062  	Map      int64 "mapTime"  // Time within map function, in nanoseconds
  4063  	EmitLoop int64 "emitLoop" // Time within the emit/map loop, in nanoseconds
  4064  }
  4065  
  4066  // MapReduce executes a map/reduce job for documents covered by the query.
  4067  // That kind of job is suitable for very flexible bulk aggregation of data
  4068  // performed at the server side via Javascript functions.
  4069  //
  4070  // Results from the job may be returned as a result of the query itself
  4071  // through the result parameter in case they'll certainly fit in memory
  4072  // and in a single document.  If there's the possibility that the amount
  4073  // of data might be too large, results must be stored back in an alternative
  4074  // collection or even a separate database, by setting the Out field of the
  4075  // provided MapReduce job.  In that case, provide nil as the result parameter.
  4076  //
  4077  // These are some of the ways to set Out:
  4078  //
  4079  //     nil
  4080  //         Inline results into the result parameter.
  4081  //
  4082  //     bson.M{"replace": "mycollection"}
  4083  //         The output will be inserted into a collection which replaces any
  4084  //         existing collection with the same name.
  4085  //
  4086  //     bson.M{"merge": "mycollection"}
  4087  //         This option will merge new data into the old output collection. In
  4088  //         other words, if the same key exists in both the result set and the
  4089  //         old collection, the new key will overwrite the old one.
  4090  //
  4091  //     bson.M{"reduce": "mycollection"}
  4092  //         If documents exist for a given key in the result set and in the old
  4093  //         collection, then a reduce operation (using the specified reduce
  4094  //         function) will be performed on the two values and the result will be
  4095  //         written to the output collection. If a finalize function was
  4096  //         provided, this will be run after the reduce as well.
  4097  //
  4098  //     bson.M{...., "db": "mydb"}
  4099  //         Any of the above options can have the "db" key included for doing
  4100  //         the respective action in a separate database.
  4101  //
  4102  // The following is a trivial example which will count the number of
  4103  // occurrences of a field named n on each document in a collection, and
  4104  // will return results inline:
  4105  //
  4106  //     job := &mgo.MapReduce{
  4107  //             Map:      "function() { emit(this.n, 1) }",
  4108  //             Reduce:   "function(key, values) { return Array.sum(values) }",
  4109  //     }
  4110  //     var result []struct { Id int "_id"; Value int }
  4111  //     _, err := collection.Find(nil).MapReduce(job, &result)
  4112  //     if err != nil {
  4113  //         return err
  4114  //     }
  4115  //     for _, item := range result {
  4116  //         fmt.Println(item.Value)
  4117  //     }
  4118  //
  4119  // This function is compatible with MongoDB 1.7.4+.
  4120  //
  4121  // Relevant documentation:
  4122  //
  4123  //     http://www.mongodb.org/display/DOCS/MapReduce
  4124  //
  4125  func (q *Query) MapReduce(job *MapReduce, result interface{}) (info *MapReduceInfo, err error) {
  4126  	q.m.Lock()
  4127  	session := q.session
  4128  	op := q.op // Copy.
  4129  	limit := q.limit
  4130  	q.m.Unlock()
  4131  
  4132  	c := strings.Index(op.collection, ".")
  4133  	if c < 0 {
  4134  		return nil, errors.New("Bad collection name: " + op.collection)
  4135  	}
  4136  
  4137  	dbname := op.collection[:c]
  4138  	cname := op.collection[c+1:]
  4139  
  4140  	cmd := mapReduceCmd{
  4141  		Collection: cname,
  4142  		Map:        job.Map,
  4143  		Reduce:     job.Reduce,
  4144  		Finalize:   job.Finalize,
  4145  		Out:        fixMROut(job.Out),
  4146  		Scope:      job.Scope,
  4147  		Verbose:    job.Verbose,
  4148  		Query:      op.query,
  4149  		Sort:       op.options.OrderBy,
  4150  		Limit:      limit,
  4151  	}
  4152  
  4153  	if cmd.Out == nil {
  4154  		cmd.Out = bson.D{{"inline", 1}}
  4155  	}
  4156  
  4157  	var doc mapReduceResult
  4158  	err = session.DB(dbname).Run(&cmd, &doc)
  4159  	if err != nil {
  4160  		return nil, err
  4161  	}
  4162  	if doc.Err != "" {
  4163  		return nil, errors.New(doc.Err)
  4164  	}
  4165  
  4166  	info = &MapReduceInfo{
  4167  		InputCount:  doc.Counts.Input,
  4168  		EmitCount:   doc.Counts.Emit,
  4169  		OutputCount: doc.Counts.Output,
  4170  		Time:        doc.TimeMillis * 1e6,
  4171  	}
  4172  
  4173  	if doc.Result.Kind == 0x02 {
  4174  		err = doc.Result.Unmarshal(&info.Collection)
  4175  		info.Database = dbname
  4176  	} else if doc.Result.Kind == 0x03 {
  4177  		var v struct{ Collection, Db string }
  4178  		err = doc.Result.Unmarshal(&v)
  4179  		info.Collection = v.Collection
  4180  		info.Database = v.Db
  4181  	}
  4182  
  4183  	if doc.Timing != nil {
  4184  		info.VerboseTime = doc.Timing
  4185  		info.VerboseTime.Total *= 1e6
  4186  		info.VerboseTime.Map *= 1e6
  4187  		info.VerboseTime.EmitLoop *= 1e6
  4188  	}
  4189  
  4190  	if err != nil {
  4191  		return nil, err
  4192  	}
  4193  	if result != nil {
  4194  		return info, doc.Results.Unmarshal(result)
  4195  	}
  4196  	return info, nil
  4197  }
  4198  
  4199  // The "out" option in the MapReduce command must be ordered. This was
  4200  // found after the implementation was accepting maps for a long time,
  4201  // so rather than breaking the API, we'll fix the order if necessary.
  4202  // Details about the order requirement may be seen in MongoDB's code:
  4203  //
  4204  //     http://goo.gl/L8jwJX
  4205  //
  4206  func fixMROut(out interface{}) interface{} {
  4207  	outv := reflect.ValueOf(out)
  4208  	if outv.Kind() != reflect.Map || outv.Type().Key() != reflect.TypeOf("") {
  4209  		return out
  4210  	}
  4211  	outs := make(bson.D, outv.Len())
  4212  
  4213  	outTypeIndex := -1
  4214  	for i, k := range outv.MapKeys() {
  4215  		ks := k.String()
  4216  		outs[i].Name = ks
  4217  		outs[i].Value = outv.MapIndex(k).Interface()
  4218  		switch ks {
  4219  		case "normal", "replace", "merge", "reduce", "inline":
  4220  			outTypeIndex = i
  4221  		}
  4222  	}
  4223  	if outTypeIndex > 0 {
  4224  		outs[0], outs[outTypeIndex] = outs[outTypeIndex], outs[0]
  4225  	}
  4226  	return outs
  4227  }
  4228  
  4229  // Change holds fields for running a findAndModify MongoDB command via
  4230  // the Query.Apply method.
  4231  type Change struct {
  4232  	Update    interface{} // The update document
  4233  	Upsert    bool        // Whether to insert in case the document isn't found
  4234  	Remove    bool        // Whether to remove the document found rather than updating
  4235  	ReturnNew bool        // Should the modified document be returned rather than the old one
  4236  }
  4237  
  4238  type findModifyCmd struct {
  4239  	Collection                  string      "findAndModify"
  4240  	Query, Update, Sort, Fields interface{} ",omitempty"
  4241  	Upsert, Remove, New         bool        ",omitempty"
  4242  }
  4243  
  4244  type valueResult struct {
  4245  	Value     bson.Raw
  4246  	LastError LastError "lastErrorObject"
  4247  }
  4248  
  4249  // Apply runs the findAndModify MongoDB command, which allows updating, upserting
  4250  // or removing a document matching a query and atomically returning either the old
  4251  // version (the default) or the new version of the document (when ReturnNew is true).
  4252  // If no objects are found Apply returns ErrNotFound.
  4253  //
  4254  // The Sort and Select query methods affect the result of Apply.  In case
  4255  // multiple documents match the query, Sort enables selecting which document to
  4256  // act upon by ordering it first.  Select enables retrieving only a selection
  4257  // of fields of the new or old document.
  4258  //
  4259  // This simple example increments a counter and prints its new value:
  4260  //
  4261  //     change := mgo.Change{
  4262  //             Update: bson.M{"$inc": bson.M{"n": 1}},
  4263  //             ReturnNew: true,
  4264  //     }
  4265  //     info, err = col.Find(M{"_id": id}).Apply(change, &doc)
  4266  //     fmt.Println(doc.N)
  4267  //
  4268  // This method depends on MongoDB >= 2.0 to work properly.
  4269  //
  4270  // Relevant documentation:
  4271  //
  4272  //     http://www.mongodb.org/display/DOCS/findAndModify+Command
  4273  //     http://www.mongodb.org/display/DOCS/Updating
  4274  //     http://www.mongodb.org/display/DOCS/Atomic+Operations
  4275  //
  4276  func (q *Query) Apply(change Change, result interface{}) (info *ChangeInfo, err error) {
  4277  	q.m.Lock()
  4278  	session := q.session
  4279  	op := q.op // Copy.
  4280  	q.m.Unlock()
  4281  
  4282  	c := strings.Index(op.collection, ".")
  4283  	if c < 0 {
  4284  		return nil, errors.New("bad collection name: " + op.collection)
  4285  	}
  4286  
  4287  	dbname := op.collection[:c]
  4288  	cname := op.collection[c+1:]
  4289  
  4290  	cmd := findModifyCmd{
  4291  		Collection: cname,
  4292  		Update:     change.Update,
  4293  		Upsert:     change.Upsert,
  4294  		Remove:     change.Remove,
  4295  		New:        change.ReturnNew,
  4296  		Query:      op.query,
  4297  		Sort:       op.options.OrderBy,
  4298  		Fields:     op.selector,
  4299  	}
  4300  
  4301  	session = session.Clone()
  4302  	defer session.Close()
  4303  	session.SetMode(Strong, false)
  4304  
  4305  	var doc valueResult
  4306  	for i := 0; i < maxUpsertRetries; i++ {
  4307  		err = session.DB(dbname).Run(&cmd, &doc)
  4308  		if err == nil {
  4309  			break
  4310  		}
  4311  		if change.Upsert && IsDup(err) && i+1 < maxUpsertRetries {
  4312  			// Retry duplicate key errors on upserts.
  4313  			// https://docs.mongodb.com/v3.2/reference/method/db.collection.update/#use-unique-indexes
  4314  			continue
  4315  		}
  4316  		if qerr, ok := err.(*QueryError); ok && qerr.Message == "No matching object found" {
  4317  			return nil, ErrNotFound
  4318  		}
  4319  		return nil, err
  4320  	}
  4321  	if doc.LastError.N == 0 {
  4322  		return nil, ErrNotFound
  4323  	}
  4324  	if doc.Value.Kind != 0x0A && result != nil {
  4325  		err = doc.Value.Unmarshal(result)
  4326  		if err != nil {
  4327  			return nil, err
  4328  		}
  4329  	}
  4330  	info = &ChangeInfo{}
  4331  	lerr := &doc.LastError
  4332  	if lerr.UpdatedExisting {
  4333  		info.Updated = lerr.N
  4334  		info.Matched = lerr.N
  4335  	} else if change.Remove {
  4336  		info.Removed = lerr.N
  4337  		info.Matched = lerr.N
  4338  	} else if change.Upsert {
  4339  		info.UpsertedId = lerr.UpsertedId
  4340  	}
  4341  	return info, nil
  4342  }
  4343  
  4344  // The BuildInfo type encapsulates details about the running MongoDB server.
  4345  //
  4346  // Note that the VersionArray field was introduced in MongoDB 2.0+, but it is
  4347  // internally assembled from the Version information for previous versions.
  4348  // In both cases, VersionArray is guaranteed to have at least 4 entries.
  4349  type BuildInfo struct {
  4350  	Version        string
  4351  	VersionArray   []int  `bson:"versionArray"` // On MongoDB 2.0+; assembled from Version otherwise
  4352  	GitVersion     string `bson:"gitVersion"`
  4353  	OpenSSLVersion string `bson:"OpenSSLVersion"`
  4354  	SysInfo        string `bson:"sysInfo"` // Deprecated and empty on MongoDB 3.2+.
  4355  	Bits           int
  4356  	Debug          bool
  4357  	MaxObjectSize  int `bson:"maxBsonObjectSize"`
  4358  }
  4359  
  4360  // VersionAtLeast returns whether the BuildInfo version is greater than or
  4361  // equal to the provided version number. If more than one number is
  4362  // provided, numbers will be considered as major, minor, and so on.
  4363  func (bi *BuildInfo) VersionAtLeast(version ...int) bool {
  4364  	for i, vi := range version {
  4365  		if i == len(bi.VersionArray) {
  4366  			return false
  4367  		}
  4368  		if bivi := bi.VersionArray[i]; bivi != vi {
  4369  			return bivi >= vi
  4370  		}
  4371  	}
  4372  	return true
  4373  }
  4374  
  4375  // BuildInfo retrieves the version and other details about the
  4376  // running MongoDB server.
  4377  func (s *Session) BuildInfo() (info BuildInfo, err error) {
  4378  	err = s.Run(bson.D{{"buildInfo", "1"}}, &info)
  4379  	if len(info.VersionArray) == 0 {
  4380  		for _, a := range strings.Split(info.Version, ".") {
  4381  			i, err := strconv.Atoi(a)
  4382  			if err != nil {
  4383  				break
  4384  			}
  4385  			info.VersionArray = append(info.VersionArray, i)
  4386  		}
  4387  	}
  4388  	for len(info.VersionArray) < 4 {
  4389  		info.VersionArray = append(info.VersionArray, 0)
  4390  	}
  4391  	if i := strings.IndexByte(info.GitVersion, ' '); i >= 0 {
  4392  		// Strip off the " modules: enterprise" suffix. This is a _git version_.
  4393  		// That information may be moved to another field if people need it.
  4394  		info.GitVersion = info.GitVersion[:i]
  4395  	}
  4396  	if info.SysInfo == "deprecated" {
  4397  		info.SysInfo = ""
  4398  	}
  4399  	return
  4400  }
  4401  
  4402  // ---------------------------------------------------------------------------
  4403  // Internal session handling helpers.
  4404  
  4405  func (s *Session) acquireSocket(slaveOk bool) (*mongoSocket, error) {
  4406  
  4407  	// Read-only lock to check for previously reserved socket.
  4408  	s.m.RLock()
  4409  	// If there is a slave socket reserved and its use is acceptable, take it as long
  4410  	// as there isn't a master socket which would be preferred by the read preference mode.
  4411  	if s.slaveSocket != nil && s.slaveOk && slaveOk && (s.masterSocket == nil || s.consistency != PrimaryPreferred && s.consistency != Monotonic) {
  4412  		socket := s.slaveSocket
  4413  		socket.Acquire()
  4414  		s.m.RUnlock()
  4415  		return socket, nil
  4416  	}
  4417  	if s.masterSocket != nil {
  4418  		socket := s.masterSocket
  4419  		socket.Acquire()
  4420  		s.m.RUnlock()
  4421  		return socket, nil
  4422  	}
  4423  	s.m.RUnlock()
  4424  
  4425  	// No go.  We may have to request a new socket and change the session,
  4426  	// so try again but with an exclusive lock now.
  4427  	s.m.Lock()
  4428  	defer s.m.Unlock()
  4429  
  4430  	if s.slaveSocket != nil && s.slaveOk && slaveOk && (s.masterSocket == nil || s.consistency != PrimaryPreferred && s.consistency != Monotonic) {
  4431  		s.slaveSocket.Acquire()
  4432  		return s.slaveSocket, nil
  4433  	}
  4434  	if s.masterSocket != nil {
  4435  		s.masterSocket.Acquire()
  4436  		return s.masterSocket, nil
  4437  	}
  4438  
  4439  	// Still not good.  We need a new socket.
  4440  	sock, err := s.cluster().AcquireSocket(s.consistency, slaveOk && s.slaveOk, s.syncTimeout, s.sockTimeout, s.queryConfig.op.serverTags, s.poolLimit)
  4441  	if err != nil {
  4442  		return nil, err
  4443  	}
  4444  
  4445  	// Authenticate the new socket.
  4446  	if err = s.socketLogin(sock); err != nil {
  4447  		sock.Release()
  4448  		return nil, err
  4449  	}
  4450  
  4451  	// Keep track of the new socket, if necessary.
  4452  	// Note that, as a special case, if the Eventual session was
  4453  	// not refreshed (s.slaveSocket != nil), it means the developer
  4454  	// asked to preserve an existing reserved socket, so we'll
  4455  	// keep a master one around too before a Refresh happens.
  4456  	if s.consistency != Eventual || s.slaveSocket != nil {
  4457  		s.setSocket(sock)
  4458  	}
  4459  
  4460  	// Switch over a Monotonic session to the master.
  4461  	if !slaveOk && s.consistency == Monotonic {
  4462  		s.slaveOk = false
  4463  	}
  4464  
  4465  	return sock, nil
  4466  }
  4467  
  4468  // setSocket binds socket to this section.
  4469  func (s *Session) setSocket(socket *mongoSocket) {
  4470  	info := socket.Acquire()
  4471  	if info.Master {
  4472  		if s.masterSocket != nil {
  4473  			panic("setSocket(master) with existing master socket reserved")
  4474  		}
  4475  		s.masterSocket = socket
  4476  	} else {
  4477  		if s.slaveSocket != nil {
  4478  			panic("setSocket(slave) with existing slave socket reserved")
  4479  		}
  4480  		s.slaveSocket = socket
  4481  	}
  4482  }
  4483  
  4484  // unsetSocket releases any slave and/or master sockets reserved.
  4485  func (s *Session) unsetSocket() {
  4486  	if s.masterSocket != nil {
  4487  		s.masterSocket.Release()
  4488  	}
  4489  	if s.slaveSocket != nil {
  4490  		s.slaveSocket.Release()
  4491  	}
  4492  	s.masterSocket = nil
  4493  	s.slaveSocket = nil
  4494  }
  4495  
  4496  func (iter *Iter) replyFunc() replyFunc {
  4497  	return func(err error, op *replyOp, docNum int, docData []byte) {
  4498  		iter.m.Lock()
  4499  		iter.docsToReceive--
  4500  		if err != nil {
  4501  			iter.err = err
  4502  			debugf("Iter %p received an error: %s", iter, err.Error())
  4503  		} else if docNum == -1 {
  4504  			debugf("Iter %p received no documents (cursor=%d).", iter, op.cursorId)
  4505  			if op != nil && op.cursorId != 0 {
  4506  				// It's a tailable cursor.
  4507  				iter.op.cursorId = op.cursorId
  4508  			} else if op != nil && op.cursorId == 0 && op.flags&1 == 1 {
  4509  				// Cursor likely timed out.
  4510  				iter.err = ErrCursor
  4511  			} else {
  4512  				iter.err = ErrNotFound
  4513  			}
  4514  		} else if iter.findCmd {
  4515  			debugf("Iter %p received reply document %d/%d (cursor=%d)", iter, docNum+1, int(op.replyDocs), op.cursorId)
  4516  			var findReply struct {
  4517  				Ok     bool
  4518  				Code   int
  4519  				Errmsg string
  4520  				Cursor cursorData
  4521  			}
  4522  			if err := bson.Unmarshal(docData, &findReply); err != nil {
  4523  				iter.err = err
  4524  			} else if !findReply.Ok && findReply.Errmsg != "" {
  4525  				iter.err = &QueryError{Code: findReply.Code, Message: findReply.Errmsg}
  4526  			} else if len(findReply.Cursor.FirstBatch) == 0 && len(findReply.Cursor.NextBatch) == 0 {
  4527  				iter.err = ErrNotFound
  4528  			} else {
  4529  				batch := findReply.Cursor.FirstBatch
  4530  				if len(batch) == 0 {
  4531  					batch = findReply.Cursor.NextBatch
  4532  				}
  4533  				rdocs := len(batch)
  4534  				for _, raw := range batch {
  4535  					iter.docData.Push(raw.Data)
  4536  				}
  4537  				iter.docsToReceive = 0
  4538  				docsToProcess := iter.docData.Len()
  4539  				if iter.limit == 0 || int32(docsToProcess) < iter.limit {
  4540  					iter.docsBeforeMore = docsToProcess - int(iter.prefetch*float64(rdocs))
  4541  				} else {
  4542  					iter.docsBeforeMore = -1
  4543  				}
  4544  				iter.op.cursorId = findReply.Cursor.Id
  4545  			}
  4546  		} else {
  4547  			rdocs := int(op.replyDocs)
  4548  			if docNum == 0 {
  4549  				iter.docsToReceive += rdocs - 1
  4550  				docsToProcess := iter.docData.Len() + rdocs
  4551  				if iter.limit == 0 || int32(docsToProcess) < iter.limit {
  4552  					iter.docsBeforeMore = docsToProcess - int(iter.prefetch*float64(rdocs))
  4553  				} else {
  4554  					iter.docsBeforeMore = -1
  4555  				}
  4556  				iter.op.cursorId = op.cursorId
  4557  			}
  4558  			debugf("Iter %p received reply document %d/%d (cursor=%d)", iter, docNum+1, rdocs, op.cursorId)
  4559  			iter.docData.Push(docData)
  4560  		}
  4561  		iter.gotReply.Broadcast()
  4562  		iter.m.Unlock()
  4563  	}
  4564  }
  4565  
  4566  type writeCmdResult struct {
  4567  	Ok        bool
  4568  	N         int
  4569  	NModified int `bson:"nModified"`
  4570  	Upserted  []struct {
  4571  		Index int
  4572  		Id    interface{} `_id`
  4573  	}
  4574  	ConcernError writeConcernError `bson:"writeConcernError"`
  4575  	Errors       []writeCmdError   `bson:"writeErrors"`
  4576  }
  4577  
  4578  type writeConcernError struct {
  4579  	Code   int
  4580  	ErrMsg string
  4581  }
  4582  
  4583  type writeCmdError struct {
  4584  	Index  int
  4585  	Code   int
  4586  	ErrMsg string
  4587  }
  4588  
  4589  func (r *writeCmdResult) BulkErrorCases() []BulkErrorCase {
  4590  	ecases := make([]BulkErrorCase, len(r.Errors))
  4591  	for i, err := range r.Errors {
  4592  		ecases[i] = BulkErrorCase{err.Index, &QueryError{Code: err.Code, Message: err.ErrMsg}}
  4593  	}
  4594  	return ecases
  4595  }
  4596  
  4597  // writeOp runs the given modifying operation, potentially followed up
  4598  // by a getLastError command in case the session is in safe mode.  The
  4599  // LastError result is made available in lerr, and if lerr.Err is set it
  4600  // will also be returned as err.
  4601  func (c *Collection) writeOp(op interface{}, ordered bool) (lerr *LastError, err error) {
  4602  	s := c.Database.Session
  4603  	socket, err := s.acquireSocket(c.Database.Name == "local")
  4604  	if err != nil {
  4605  		return nil, err
  4606  	}
  4607  	defer socket.Release()
  4608  
  4609  	s.m.RLock()
  4610  	safeOp := s.safeOp
  4611  	bypassValidation := s.bypassValidation
  4612  	s.m.RUnlock()
  4613  
  4614  	if socket.ServerInfo().MaxWireVersion >= 2 {
  4615  		// Servers with a more recent write protocol benefit from write commands.
  4616  		if op, ok := op.(*insertOp); ok && len(op.documents) > 1000 {
  4617  			var lerr LastError
  4618  
  4619  			// Maximum batch size is 1000. Must split out in separate operations for compatibility.
  4620  			all := op.documents
  4621  			for i := 0; i < len(all); i += 1000 {
  4622  				l := i + 1000
  4623  				if l > len(all) {
  4624  					l = len(all)
  4625  				}
  4626  				op.documents = all[i:l]
  4627  				oplerr, err := c.writeOpCommand(socket, safeOp, op, ordered, bypassValidation)
  4628  				lerr.N += oplerr.N
  4629  				lerr.modified += oplerr.modified
  4630  				if err != nil {
  4631  					for ei := range oplerr.ecases {
  4632  						oplerr.ecases[ei].Index += i
  4633  					}
  4634  					lerr.ecases = append(lerr.ecases, oplerr.ecases...)
  4635  					if op.flags&1 == 0 {
  4636  						return &lerr, err
  4637  					}
  4638  				}
  4639  			}
  4640  			if len(lerr.ecases) != 0 {
  4641  				return &lerr, lerr.ecases[0].Err
  4642  			}
  4643  			return &lerr, nil
  4644  		}
  4645  		return c.writeOpCommand(socket, safeOp, op, ordered, bypassValidation)
  4646  	} else if updateOps, ok := op.(bulkUpdateOp); ok {
  4647  		var lerr LastError
  4648  		for i, updateOp := range updateOps {
  4649  			oplerr, err := c.writeOpQuery(socket, safeOp, updateOp, ordered)
  4650  			lerr.N += oplerr.N
  4651  			lerr.modified += oplerr.modified
  4652  			if err != nil {
  4653  				lerr.ecases = append(lerr.ecases, BulkErrorCase{i, err})
  4654  				if ordered {
  4655  					break
  4656  				}
  4657  			}
  4658  		}
  4659  		if len(lerr.ecases) != 0 {
  4660  			return &lerr, lerr.ecases[0].Err
  4661  		}
  4662  		return &lerr, nil
  4663  	} else if deleteOps, ok := op.(bulkDeleteOp); ok {
  4664  		var lerr LastError
  4665  		for i, deleteOp := range deleteOps {
  4666  			oplerr, err := c.writeOpQuery(socket, safeOp, deleteOp, ordered)
  4667  			lerr.N += oplerr.N
  4668  			lerr.modified += oplerr.modified
  4669  			if err != nil {
  4670  				lerr.ecases = append(lerr.ecases, BulkErrorCase{i, err})
  4671  				if ordered {
  4672  					break
  4673  				}
  4674  			}
  4675  		}
  4676  		if len(lerr.ecases) != 0 {
  4677  			return &lerr, lerr.ecases[0].Err
  4678  		}
  4679  		return &lerr, nil
  4680  	}
  4681  	return c.writeOpQuery(socket, safeOp, op, ordered)
  4682  }
  4683  
  4684  func (c *Collection) writeOpQuery(socket *mongoSocket, safeOp *queryOp, op interface{}, ordered bool) (lerr *LastError, err error) {
  4685  	if safeOp == nil {
  4686  		return nil, socket.Query(op)
  4687  	}
  4688  
  4689  	var mutex sync.Mutex
  4690  	var replyData []byte
  4691  	var replyErr error
  4692  	mutex.Lock()
  4693  	query := *safeOp // Copy the data.
  4694  	query.collection = c.Database.Name + ".$cmd"
  4695  	query.replyFunc = func(err error, reply *replyOp, docNum int, docData []byte) {
  4696  		replyData = docData
  4697  		replyErr = err
  4698  		mutex.Unlock()
  4699  	}
  4700  	err = socket.Query(op, &query)
  4701  	if err != nil {
  4702  		return nil, err
  4703  	}
  4704  	mutex.Lock() // Wait.
  4705  	if replyErr != nil {
  4706  		return nil, replyErr // XXX TESTME
  4707  	}
  4708  	if hasErrMsg(replyData) {
  4709  		// Looks like getLastError itself failed.
  4710  		err = checkQueryError(query.collection, replyData)
  4711  		if err != nil {
  4712  			return nil, err
  4713  		}
  4714  	}
  4715  	result := &LastError{}
  4716  	bson.Unmarshal(replyData, &result)
  4717  	debugf("Result from writing query: %#v", result)
  4718  	if result.Err != "" {
  4719  		result.ecases = []BulkErrorCase{{Index: 0, Err: result}}
  4720  		if insert, ok := op.(*insertOp); ok && len(insert.documents) > 1 {
  4721  			result.ecases[0].Index = -1
  4722  		}
  4723  		return result, result
  4724  	}
  4725  	// With MongoDB <2.6 we don't know how many actually changed, so make it the same as matched.
  4726  	result.modified = result.N
  4727  	return result, nil
  4728  }
  4729  
  4730  func (c *Collection) writeOpCommand(socket *mongoSocket, safeOp *queryOp, op interface{}, ordered, bypassValidation bool) (lerr *LastError, err error) {
  4731  	var writeConcern interface{}
  4732  	if safeOp == nil {
  4733  		writeConcern = bson.D{{"w", 0}}
  4734  	} else {
  4735  		writeConcern = safeOp.query.(*getLastError)
  4736  	}
  4737  
  4738  	var cmd bson.D
  4739  	switch op := op.(type) {
  4740  	case *insertOp:
  4741  		// http://docs.mongodb.org/manual/reference/command/insert
  4742  		cmd = bson.D{
  4743  			{"insert", c.Name},
  4744  			{"documents", op.documents},
  4745  			{"writeConcern", writeConcern},
  4746  			{"ordered", op.flags&1 == 0},
  4747  		}
  4748  	case *updateOp:
  4749  		// http://docs.mongodb.org/manual/reference/command/update
  4750  		cmd = bson.D{
  4751  			{"update", c.Name},
  4752  			{"updates", []interface{}{op}},
  4753  			{"writeConcern", writeConcern},
  4754  			{"ordered", ordered},
  4755  		}
  4756  	case bulkUpdateOp:
  4757  		// http://docs.mongodb.org/manual/reference/command/update
  4758  		cmd = bson.D{
  4759  			{"update", c.Name},
  4760  			{"updates", op},
  4761  			{"writeConcern", writeConcern},
  4762  			{"ordered", ordered},
  4763  		}
  4764  	case *deleteOp:
  4765  		// http://docs.mongodb.org/manual/reference/command/delete
  4766  		cmd = bson.D{
  4767  			{"delete", c.Name},
  4768  			{"deletes", []interface{}{op}},
  4769  			{"writeConcern", writeConcern},
  4770  			{"ordered", ordered},
  4771  		}
  4772  	case bulkDeleteOp:
  4773  		// http://docs.mongodb.org/manual/reference/command/delete
  4774  		cmd = bson.D{
  4775  			{"delete", c.Name},
  4776  			{"deletes", op},
  4777  			{"writeConcern", writeConcern},
  4778  			{"ordered", ordered},
  4779  		}
  4780  	}
  4781  	if bypassValidation {
  4782  		cmd = append(cmd, bson.DocElem{"bypassDocumentValidation", true})
  4783  	}
  4784  
  4785  	var result writeCmdResult
  4786  	err = c.Database.run(socket, cmd, &result)
  4787  	debugf("Write command result: %#v (err=%v)", result, err)
  4788  	ecases := result.BulkErrorCases()
  4789  	lerr = &LastError{
  4790  		UpdatedExisting: result.N > 0 && len(result.Upserted) == 0,
  4791  		N:               result.N,
  4792  
  4793  		modified: result.NModified,
  4794  		ecases:   ecases,
  4795  	}
  4796  	if len(result.Upserted) > 0 {
  4797  		lerr.UpsertedId = result.Upserted[0].Id
  4798  	}
  4799  	if len(result.Errors) > 0 {
  4800  		e := result.Errors[0]
  4801  		lerr.Code = e.Code
  4802  		lerr.Err = e.ErrMsg
  4803  		err = lerr
  4804  	} else if result.ConcernError.Code != 0 {
  4805  		e := result.ConcernError
  4806  		lerr.Code = e.Code
  4807  		lerr.Err = e.ErrMsg
  4808  		err = lerr
  4809  	}
  4810  
  4811  	if err == nil && safeOp == nil {
  4812  		return nil, nil
  4813  	}
  4814  	return lerr, err
  4815  }
  4816  
  4817  func hasErrMsg(d []byte) bool {
  4818  	l := len(d)
  4819  	for i := 0; i+8 < l; i++ {
  4820  		if d[i] == '\x02' && d[i+1] == 'e' && d[i+2] == 'r' && d[i+3] == 'r' && d[i+4] == 'm' && d[i+5] == 's' && d[i+6] == 'g' && d[i+7] == '\x00' {
  4821  			return true
  4822  		}
  4823  	}
  4824  	return false
  4825  }