void DBClientMultiCommand::sendAll() {

    for ( deque<PendingCommand*>::iterator it = _pendingCommands.begin();
            it != _pendingCommands.end(); ++it ) {

        PendingCommand* command = *it;
        dassert( NULL == command->conn );

        try {
            // TODO: Figure out how to handle repl sets, configs
            dassert( command->endpoint.type() == ConnectionString::MASTER ||
                     command->endpoint.type() == ConnectionString::CUSTOM );
            command->conn = shardConnectionPool.get( command->endpoint, 0 /*timeout*/);

            if ( hasBatchWriteFeature( command->conn )
                    || !isBatchWriteCommand( command->cmdObj ) ) {
                // Do normal command dispatch
                sayAsCmd( command->conn, command->dbName, command->cmdObj );
            }
            else {
                // Sending a batch as safe writes necessarily blocks, so we can't do anything
                // here.  Instead we do the safe writes in recvAny(), which can block.
            }
        }
        catch ( const DBException& ex ) {
            command->status = ex.toStatus();
            if ( NULL != command->conn ) delete command->conn;
            command->conn = NULL;
        }
    }
}
    Status DBClientMultiCommand::recvAny( ConnectionString* endpoint, BSONSerializable* response ) {

        scoped_ptr<PendingCommand> command( _pendingCommands.front() );
        _pendingCommands.pop_front();

        *endpoint = command->endpoint;
        if ( !command->status.isOK() ) return command->status;

        dassert( NULL != command->conn );

        try {

            // Holds the data and BSONObj for the command result
            Message toRecv;
            BSONObj result;

            if ( hasBatchWriteFeature( command->conn )
                 || !isBatchWriteCommand( command->cmdObj ) ) {
                // Recv data from command sent earlier
                recvAsCmd( command->conn, &toRecv, &result );
            }
            else {
                // We can safely block in recvAny, so dispatch writes as safe writes for hosts
                // that don't understand batch write commands.
                legacySafeWrite( command->conn, command->dbName, command->cmdObj, &result );
            }

            shardConnectionPool.release( command->endpoint.toString(), command->conn );
            command->conn = NULL;

            string errMsg;
            if ( !response->parseBSON( result, &errMsg ) || !response->isValid( &errMsg ) ) {
                return Status( ErrorCodes::FailedToParse, errMsg );
            }
        }
        catch ( const DBException& ex ) {

            // Confusingly, the pool needs to know about failed connections so that it can
            // invalidate other connections which might be bad.  But if the connection doesn't seem
            // bad, don't send it back, because we don't want to reuse it.
            if ( !command->conn->isFailed() ) {
                delete command->conn;
            }
            else {
                shardConnectionPool.release( command->endpoint.toString(), command->conn );
            }
            command->conn = NULL;

            return ex.toStatus();
        }

        return Status::OK();
    }
    void DBClientMultiCommand::sendAll() {

        for ( deque<PendingCommand*>::iterator it = _pendingCommands.begin();
            it != _pendingCommands.end(); ++it ) {

            PendingCommand* command = *it;
            dassert( NULL == command->conn );

            try {
                dassert( command->endpoint.type() == ConnectionString::MASTER ||
                    command->endpoint.type() == ConnectionString::CUSTOM );

                // TODO: Fix the pool up to take millis directly
                int timeoutSecs = _timeoutMillis / 1000;
                command->conn = shardConnectionPool.get( command->endpoint, timeoutSecs );

                if ( hasBatchWriteFeature( command->conn )
                     || !isBatchWriteCommand( command->cmdObj ) ) {
                    // Do normal command dispatch
                    sayAsCmd( command->conn, command->dbName, command->cmdObj );
                }
                else {
                    // Sending a batch as safe writes necessarily blocks, so we can't do anything
                    // here.  Instead we do the safe writes in recvAny(), which can block.
                }
            }
            catch ( const DBException& ex ) {
                command->status = ex.toStatus();

                if ( NULL != command->conn ) {

                    // Confusingly, the pool needs to know about failed connections so that it can
                    // invalidate other connections which might be bad.  But if the connection
                    // doesn't seem bad, don't send it back, because we don't want to reuse it.
                    if ( !command->conn->isFailed() ) {
                        delete command->conn;
                    }
                    else {
                        shardConnectionPool.release( command->endpoint.toString(), command->conn );
                    }

                    command->conn = NULL;
                }
            }
        }
    }
Status DBClientMultiCommand::recvAny( ConnectionString* endpoint, BSONSerializable* response ) {

    scoped_ptr<PendingCommand> command( _pendingCommands.front() );
    _pendingCommands.pop_front();

    *endpoint = command->endpoint;
    if ( !command->status.isOK() ) return command->status;

    dassert( NULL != command->conn );

    try {

        // Holds the data and BSONObj for the command result
        Message toRecv;
        BSONObj result;

        if ( hasBatchWriteFeature( command->conn )
                || !isBatchWriteCommand( command->cmdObj ) ) {
            // Recv data from command sent earlier
            recvAsCmd( command->conn, &toRecv, &result );
        }
        else {
            // We can safely block in recvAny, so dispatch writes as safe writes for hosts
            // that don't understand batch write commands.
            legacySafeWrite( command->conn, command->dbName, command->cmdObj, &result );
        }

        shardConnectionPool.release( command->endpoint.toString(), command->conn );
        command->conn = NULL;

        string errMsg;
        if ( !response->parseBSON( result, &errMsg ) || !response->isValid( &errMsg ) ) {
            return Status( ErrorCodes::FailedToParse, errMsg );
        }
    }
    catch ( const DBException& ex ) {

        delete command->conn;
        command->conn = NULL;

        return ex.toStatus();
    }

    return Status::OK();
}