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
}
// 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.