Пример #1
0
void Strategy::clientCommandOp(OperationContext* txn, Request& request) {
    QueryMessage q(request.d());

    LOG(3) << "command: " << q.ns << " " << q.query << " ntoreturn: " << q.ntoreturn
           << " options: " << q.queryOptions;

    if (q.queryOptions & QueryOption_Exhaust) {
        uasserted(18527,
                  string("the 'exhaust' query option is invalid for mongos commands: ") + q.ns +
                      " " + q.query.toString());
    }

    NamespaceString nss(request.getns());
    // Regular queries are handled in strategy_shard.cpp
    verify(nss.isCommand() || nss.isSpecialCommand());

    if (handleSpecialNamespaces(txn, request, q))
        return;

    int loops = 5;
    bool cmChangeAttempted = false;

    while (true) {
        BSONObjBuilder builder;
        try {
            BSONObj cmdObj = q.query;
            {
                BSONElement e = cmdObj.firstElement();
                if (e.type() == Object &&
                    (e.fieldName()[0] == '$' ? str::equals("query", e.fieldName() + 1)
                                             : str::equals("query", e.fieldName()))) {
                    // Extract the embedded query object.

                    if (cmdObj.hasField(Query::ReadPrefField.name())) {
                        // The command has a read preference setting. We don't want
                        // to lose this information so we copy this to a new field
                        // called $queryOptions.$readPreference
                        BSONObjBuilder finalCmdObjBuilder;
                        finalCmdObjBuilder.appendElements(e.embeddedObject());

                        BSONObjBuilder queryOptionsBuilder(
                            finalCmdObjBuilder.subobjStart("$queryOptions"));
                        queryOptionsBuilder.append(cmdObj[Query::ReadPrefField.name()]);
                        queryOptionsBuilder.done();

                        cmdObj = finalCmdObjBuilder.obj();
                    } else {
                        cmdObj = e.embeddedObject();
                    }
                }
            }

            Command::runAgainstRegistered(txn, q.ns, cmdObj, builder, q.queryOptions);
            BSONObj x = builder.done();
            replyToQuery(0, request.p(), request.m(), x);
            return;
        } catch (const StaleConfigException& e) {
            if (loops <= 0)
                throw e;

            loops--;
            log() << "retrying command: " << q.query;

            // For legacy reasons, ns may not actually be set in the exception :-(
            string staleNS = e.getns();
            if (staleNS.size() == 0)
                staleNS = q.ns;

            ShardConnection::checkMyConnectionVersions(txn, staleNS);
            if (loops < 4)
                versionManager.forceRemoteCheckShardVersionCB(txn, staleNS);
        } catch (const DBException& e) {
            if (e.getCode() == ErrorCodes::IncompatibleCatalogManager) {
                fassert(28791, !cmChangeAttempted);
                cmChangeAttempted = true;

                grid.forwardingCatalogManager()->waitForCatalogManagerChange(txn);
            } else {
                Command::appendCommandStatus(builder, e.toStatus());
                BSONObj x = builder.done();
                replyToQuery(0, request.p(), request.m(), x);
                return;
            }
        }
    }
}
Пример #2
0
        virtual void queryOp( Request& r ) {
            QueryMessage q( r.d() );

            LOG(3) << "single query: " << q.ns << "  " << q.query << "  ntoreturn: " << q.ntoreturn << " options : " << q.queryOptions << endl;

            NamespaceString nss( r.getns() );
            // Regular queries are handled in strategy_shard.cpp
            verify( nss.isCommand() || nss.isSpecialCommand() );

            if ( handleSpecialNamespaces( r , q ) )
                return;

            int loops = 5;
            while ( true ) {
                BSONObjBuilder builder;
                try {
                    BSONObj cmdObj = q.query;
                    {
                        BSONElement e = cmdObj.firstElement();
                        if (e.type() == Object && (e.fieldName()[0] == '$'
                                                     ? str::equals("query", e.fieldName()+1)
                                                     : str::equals("query", e.fieldName()))) {
                            // Extract the embedded query object.

                            if (cmdObj.hasField(Query::ReadPrefField.name())) {
                                // The command has a read preference setting. We don't want
                                // to lose this information so we copy this to a new field
                                // called $queryOptions.$readPreference
                                BSONObjBuilder finalCmdObjBuilder;
                                finalCmdObjBuilder.appendElements(e.embeddedObject());

                                BSONObjBuilder queryOptionsBuilder(
                                        finalCmdObjBuilder.subobjStart("$queryOptions"));
                                queryOptionsBuilder.append(cmdObj[Query::ReadPrefField.name()]);
                                queryOptionsBuilder.done();

                                cmdObj = finalCmdObjBuilder.obj();
                            }
                            else {
                                cmdObj = e.embeddedObject();
                            }
                        }
                    }

                    Command::runAgainstRegistered(q.ns, cmdObj, builder, q.queryOptions);
                    BSONObj x = builder.done();
                    replyToQuery(0, r.p(), r.m(), x);
                    return;
                }
                catch ( StaleConfigException& e ) {
                    if ( loops <= 0 )
                        throw e;

                    loops--;
                    log() << "retrying command: " << q.query << endl;

                    // For legacy reasons, ns may not actually be set in the exception :-(
                    string staleNS = e.getns();
                    if( staleNS.size() == 0 ) staleNS = q.ns;

                    ShardConnection::checkMyConnectionVersions( staleNS );
                    if( loops < 4 ) versionManager.forceRemoteCheckShardVersionCB( staleNS );
                }
                catch ( AssertionException& e ) {
                    Command::appendCommandStatus(builder, e.toStatus());
                    BSONObj x = builder.done();
                    replyToQuery(0, r.p(), r.m(), x);
                    return;
                }
            }
        }