static void parse_options(int argc, char ** argv) { string skill_spec(""); string robot_spec(""); servo_rate = 500; for (int ii(1); ii < argc; ++ii) { if ((strlen(argv[ii]) < 2) || ('-' != argv[ii][0])) { usage(EXIT_FAILURE, "problem with option `" + string(argv[ii]) + "'"); } else switch (argv[ii][1]) { case 'h': usage(EXIT_SUCCESS, "servo [-h] [-v] [-s skillspec] -r robotspec"); case 'v': verbose = true; break; case 'r': ++ii; if (ii >= argc) { usage(EXIT_FAILURE, "-r requires parameter"); } robot_spec = argv[ii]; break; case 'f': ++ii; if (ii >= argc) { usage(EXIT_FAILURE, "-f requires parameter"); } else { istringstream is(argv[ii]); is >> servo_rate; if ( ! is) { usage(EXIT_FAILURE, "failed to read servo rate from `" + string(argv[ii]) + "'"); } if (0 >= servo_rate) { usage(EXIT_FAILURE, "servo rate has to be positive"); } } break; case 's': ++ii; if (ii >= argc) { usage(EXIT_FAILURE, "-s requires parameter"); } skill_spec = argv[ii]; break; default: usage(EXIT_FAILURE, "invalid option `" + string(argv[ii]) + "'"); } } try { if (robot_spec.empty()) { usage(EXIT_FAILURE, "no robot specification (see option -r)"); } if (verbose) { warnx("reading robot spec from %s", robot_spec.c_str()); } static bool const enable_coriolis_centrifugal(false); model.reset(jspace::test::parse_sai_xml_file(robot_spec, enable_coriolis_centrifugal)); } catch (runtime_error const & ee) { errx(EXIT_FAILURE, "exception while parsing robot specification\n" " filename: %s\n" " error: %s", robot_spec.c_str(), ee.what()); } factory.reset(new Factory()); Status st; if (skill_spec.empty()) { if (verbose) { warnx("using fallback task/posture skill"); } st = factory->parseString(opspace_fallback_str); } else { if (verbose) { warnx("reading skills from %s", skill_spec.c_str()); } st = factory->parseFile(skill_spec); } if ( ! st) { errx(EXIT_FAILURE, "failed to parse skills\n" " specification file: %s\n" " error description: %s", skill_spec.c_str(), st.errstr.c_str()); } if (verbose) { factory->dump(cout, "*** parsed tasks and skills", "* "); } }
/** * Run a query with a cursor provided by the query optimizer, or FindingStartCursor. * @yields the db lock. */ string queryWithQueryOptimizer( int queryOptions, const string& ns, const BSONObj &jsobj, CurOp& curop, const BSONObj &query, const BSONObj &order, const shared_ptr<ParsedQuery> &pq_shared, const BSONObj &oldPlan, const ChunkVersion &shardingVersionAtStart, scoped_ptr<PageFaultRetryableSection>& parentPageFaultSection, scoped_ptr<NoPageFaultsAllowed>& noPageFault, Message &result ) { const ParsedQuery &pq( *pq_shared ); shared_ptr<Cursor> cursor; QueryPlanSummary queryPlan; if ( pq.hasOption( QueryOption_OplogReplay ) ) { cursor = FindingStartCursor::getCursor( ns.c_str(), query, order ); } else { cursor = getOptimizedCursor( ns.c_str(), query, order, QueryPlanSelectionPolicy::any(), pq_shared, false, &queryPlan ); } verify( cursor ); scoped_ptr<QueryResponseBuilder> queryResponseBuilder ( QueryResponseBuilder::make( pq, cursor, queryPlan, oldPlan ) ); bool saveClientCursor = false; OpTime slaveReadTill; ClientCursorHolder ccPointer( new ClientCursor( QueryOption_NoCursorTimeout, cursor, ns ) ); for( ; cursor->ok(); cursor->advance() ) { bool yielded = false; if ( !ccPointer->yieldSometimes( ClientCursor::MaybeCovered, &yielded ) || !cursor->ok() ) { cursor.reset(); queryResponseBuilder->noteYield(); // !!! TODO The queryResponseBuilder still holds cursor. Currently it will not do // anything unsafe with the cursor in handoff(), but this is very fragile. // // We don't fail the query since we're fine with returning partial data if the // collection was dropped. // NOTE see SERVER-2454. // TODO This is wrong. The cursor could be gone if the closeAllDatabases command // just ran. break; } if ( yielded ) { queryResponseBuilder->noteYield(); } if ( pq.getMaxScan() && cursor->nscanned() > pq.getMaxScan() ) { break; } if ( !queryResponseBuilder->addMatch() ) { continue; } // Note slave's position in the oplog. if ( pq.hasOption( QueryOption_OplogReplay ) ) { BSONObj current = cursor->current(); BSONElement e = current["ts"]; if ( e.type() == Date || e.type() == Timestamp ) { slaveReadTill = e._opTime(); } } if ( !cursor->supportGetMore() || pq.isExplain() ) { if ( queryResponseBuilder->enoughTotalResults() ) { break; } } else if ( queryResponseBuilder->enoughForFirstBatch() ) { // if only 1 requested, no cursor saved for efficiency...we assume it is findOne() if ( pq.wantMore() && pq.getNumToReturn() != 1 ) { queryResponseBuilder->finishedFirstBatch(); if ( cursor->advance() ) { saveClientCursor = true; } } break; } } if ( cursor ) { if ( pq.hasOption( QueryOption_CursorTailable ) && pq.getNumToReturn() != 1 ) { cursor->setTailable(); } // If the tailing request succeeded. if ( cursor->tailable() ) { saveClientCursor = true; } } if ( ! shardingState.getVersion( ns ).isWriteCompatibleWith( shardingVersionAtStart ) ) { // if the version changed during the query // we might be missing some data // and its safe to send this as mongos can resend // at this point throw SendStaleConfigException(ns, "version changed during initial query", shardingVersionAtStart, shardingState.getVersion(ns)); } parentPageFaultSection.reset(0); noPageFault.reset( new NoPageFaultsAllowed() ); int nReturned = queryResponseBuilder->handoff( result ); ccPointer.reset(); long long cursorid = 0; if ( saveClientCursor ) { // Create a new ClientCursor, with a default timeout. ccPointer.reset( new ClientCursor( queryOptions, cursor, ns, jsobj.getOwned() ) ); cursorid = ccPointer->cursorid(); DEV { MONGO_TLOG(2) << "query has more, cursorid: " << cursorid << endl; } if ( cursor->supportYields() ) { ClientCursor::YieldData data; ccPointer->prepareToYield( data ); } else { ccPointer->c()->noteLocation(); } // Save slave's position in the oplog. if ( pq.hasOption( QueryOption_OplogReplay ) && !slaveReadTill.isNull() ) { ccPointer->slaveReadTill( slaveReadTill ); } if ( !ccPointer->ok() && ccPointer->c()->tailable() ) { DEV { MONGO_TLOG(0) << "query has no more but tailable, cursorid: " << cursorid << endl; } } if( queryOptions & QueryOption_Exhaust ) { curop.debug().exhaust = true; } // Set attributes for getMore. ccPointer->setCollMetadata( queryResponseBuilder->collMetadata() ); ccPointer->setPos( nReturned ); ccPointer->pq = pq_shared; ccPointer->fields = pq.getFieldPtr(); // If the query had a time limit, remaining time is "rolled over" to the cursor (for // use by future getmore ops). ccPointer->setLeftoverMaxTimeMicros( curop.getRemainingMaxTimeMicros() ); ccPointer.release(); }