Godeps/_workspace/src/gopkg.in/mgo.v2/session.go
func (c *Collection) writeQuery(op interface{}) (lerr *LastError, err error) {
	s := c.Database.Session
	dbname := c.Database.Name
	socket, err := s.acquireSocket(dbname == "local")
	if err != nil {
		return nil, err
	}
	defer socket.Release()

	s.m.RLock()
	safeOp := s.safeOp
	s.m.RUnlock()

	// TODO Enable this path for wire version 2 as well.
	if socket.ServerInfo().MaxWireVersion >= 3 {
		// Servers with a more recent write protocol benefit from write commands.
		if op, ok := op.(*insertOp); ok && len(op.documents) > 1000 {
			var firstErr error
			// Maximum batch size is 1000. Must split out in separate operations for compatibility.
			all := op.documents
			for i := 0; i < len(all); i += 1000 {
				l := i + 1000
				if l > len(all) {
					l = len(all)
				}
				op.documents = all[i:l]
				_, err := c.writeCommand(socket, safeOp, op)
				if err != nil {
					if op.flags&1 != 0 {
						if firstErr == nil {
							firstErr = err
						}
					} else {
						return nil, err
					}
				}
			}
			return nil, firstErr
		}
		return c.writeCommand(socket, safeOp, op)
	}

	if safeOp == nil {
		return nil, socket.Query(op)
	}

	var mutex sync.Mutex
	var replyData []byte
	var replyErr error
	mutex.Lock()
	query := *safeOp // Copy the data.
	query.collection = dbname + ".$cmd"
	query.replyFunc = func(err error, reply *replyOp, docNum int, docData []byte) {
		replyData = docData
		replyErr = err
		mutex.Unlock()
	}
	err = socket.Query(op, &query)
	if err != nil {
		return nil, err
	}
	mutex.Lock() // Wait.
	if replyErr != nil {
		return nil, replyErr // XXX TESTME
	}
	if hasErrMsg(replyData) {
		// Looks like getLastError itself failed.
		err = checkQueryError(query.collection, replyData)
		if err != nil {
			return nil, err
		}
	}
	result := &LastError{}
	bson.Unmarshal(replyData, &result)
	debugf("Result from writing query: %#v", result)
	if result.Err != "" {
		return result, result
	}
	return result, nil
}
func (c *Collection) writeQuery(op interface{}) (lerr *LastError, err error) {
	s := c.Database.Session
	dbname := c.Database.Name
	socket, err := s.acquireSocket(dbname == "local")
	if err != nil {
		return nil, err
	}
	defer socket.Release()

	s.m.RLock()
	safeOp := s.safeOp
	s.m.RUnlock()

	// TODO Enable this path for wire version 2 as well.
	if socket.ServerInfo().MaxWireVersion >= 3 {
		// Servers with a more recent write protocol benefit from write commands.
		if op, ok := op.(*insertOp); ok && len(op.documents) > 1000 {
			var firstErr error
			// Maximum batch size is 1000. Must split out in separate operations for compatibility.
			all := op.documents
			for i := 0; i < len(all); i += 1000 {
				l := i + 1000
				if l > len(all) {
					l = len(all)
				}
				op.documents = all[i:l]
				_, err := c.writeCommand(socket, safeOp, op)
				if err != nil {
					if op.flags&1 != 0 {
						if firstErr == nil {
							firstErr = err
						}
					} else {
						return nil, err
					}
				}
			}
			return nil, firstErr
		}
		return c.writeCommand(socket, safeOp, op)
	}

	if safeOp == nil {
		return nil, socket.Query(op)
	}

	var mutex sync.Mutex
	var replyData []byte
	var replyErr error
	mutex.Lock()
	query := *safeOp // Copy the data.
	query.collection = dbname + ".$cmd"
	query.replyFunc = func(err error, reply *replyOp, docNum int, docData []byte) {
		replyData = docData
		replyErr = err
		mutex.Unlock()
	}
	err = socket.Query(op, &query)
	if err != nil {
		return nil, err
	}
	mutex.Lock() // Wait.
	if replyErr != nil {
		return nil, replyErr // XXX TESTME
	}
	if hasErrMsg(replyData) {
		// Looks like getLastError itself failed.
		err = checkQueryError(query.collection, replyData)
		if err != nil {
			return nil, err
		}
	}
	result := &LastError{}
	bson.Unmarshal(replyData, &result)
	debugf("Result from writing query: %#v", result)
	if result.Err != "" {
		return result, result
	}
	return result, nil
}
func ( c * Collection ) writeQuery ( op interface { } ) ( lerr * LastError , err error ) { s := c . Database . Session dbname := c . Database . Name socket , err := s . acquireSocket ( dbname == " " ) if err != nil { return nil , err } defer socket . Release ( ) s . m . RLock ( ) safeOp := s . safeOp s . m . RUnlock ( ) // TODO Enable this path for wire version 2 as well. if socket . ServerInfo ( ) . MaxWireVersion >= 3 { // Servers with a more recent write protocol benefit from write commands. if op , ok := op . ( * insertOp ) ; ok && len ( op . documents ) > 1000 { var firstErr error // Maximum batch size is 1000. Must split out in separate operations for compatibility. all := op . documents for i := 0 ; i < len ( all ) ; i += 1000 { l := i + 1000 if l > len ( all ) { l = len ( all ) } op . documents = all [ i : l ] _ , err := c . writeCommand ( socket , safeOp , op ) if err != nil { if op . flags & 1 != 0 { if firstErr == nil { firstErr = err } } else { return nil , err } } } return nil , firstErr } return c . writeCommand ( socket , safeOp , op ) } if safeOp == nil { return nil , socket . Query ( op ) } var mutex sync . Mutex var replyData [ ] byte var replyErr error mutex . Lock ( ) query := * safeOp // Copy the data. query . collection = dbname + " " query . replyFunc = func ( err error , reply * replyOp , docNum int , docData [ ] byte ) { replyData = docData replyErr = err mutex . Unlock ( ) } err = socket . Query ( op , & query ) if err != nil { return nil , err } mutex . Lock ( ) // Wait. if replyErr != nil { return nil , replyErr // XXX TESTME } if hasErrMsg ( replyData ) { // Looks like getLastError itself failed. err = checkQueryError ( query . collection , replyData ) if err != nil { return nil , err } } result := & LastError { } bson . Unmarshal ( replyData , & result ) debugf ( " " , result ) if result . Err != " " { return result , result } return result , nil }
// writeQuery runs the given modifying operation, potentially followed up
// by a getLastError command in case the session is in safe mode.  The
// LastError result is made available in lerr, and if lerr.Err is set it
// will also be returned as err.
writeQuery runs the given modifying operation potentially followed up by a getLastError command in case the session is in safe mode . The LastError result is made available in lerr and if lerr . Err is set it will also be returned as err .