summaryrefslogtreecommitdiff
path: root/src/mongo/s/request.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/s/request.cpp')
-rw-r--r--src/mongo/s/request.cpp164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/mongo/s/request.cpp b/src/mongo/s/request.cpp
new file mode 100644
index 00000000000..96cce96685d
--- /dev/null
+++ b/src/mongo/s/request.cpp
@@ -0,0 +1,164 @@
+// s/request.cpp
+
+/**
+* Copyright (C) 2008 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "pch.h"
+#include "server.h"
+
+#include "../db/commands.h"
+#include "../db/dbmessage.h"
+#include "../db/stats/counters.h"
+
+#include "../client/connpool.h"
+
+#include "request.h"
+#include "config.h"
+#include "chunk.h"
+#include "stats.h"
+#include "cursors.h"
+#include "grid.h"
+#include "client.h"
+
+namespace mongo {
+
+ Request::Request( Message& m, AbstractMessagingPort* p ) :
+ _m(m) , _d( m ) , _p(p) , _didInit(false) {
+
+ assert( _d.getns() );
+ _id = _m.header()->id;
+
+ _clientInfo = ClientInfo::get();
+ _clientInfo->newRequest( p );
+ }
+
+ void Request::checkAuth( Auth::Level levelNeeded ) const {
+ char cl[256];
+ nsToDatabase(getns(), cl);
+ uassert( 15845 ,
+ str::stream() << "unauthorized for db:" << cl << " level: " << levelNeeded ,
+ _clientInfo->getAuthenticationInfo()->isAuthorizedForLevel(cl,levelNeeded) );
+ }
+
+ void Request::init() {
+ if ( _didInit )
+ return;
+ _didInit = true;
+ reset();
+ }
+
+ // Deprecated, will move to the strategy itself
+ void Request::reset() {
+ if ( _m.operation() == dbKillCursors ) {
+ return;
+ }
+
+ uassert( 13644 , "can't use 'local' database through mongos" , ! str::startsWith( getns() , "local." ) );
+
+ // TODO: Deprecated, keeping to preserve codepath for now
+ const string nsStr (getns()); // use in functions taking string rather than char*
+
+ _config = grid.getDBConfig( nsStr );
+
+ // TODO: In general, throwing an exception when the cm doesn't exist is really annoying
+ if ( _config->isSharded( nsStr ) ) {
+ _chunkManager = _config->getChunkManagerIfExists( nsStr );
+ }
+ else {
+ _chunkManager.reset();
+ }
+
+ _m.header()->id = _id;
+ _clientInfo->clearCurrentShards();
+ }
+
+ // Deprecated, will move to the strategy itself
+ Shard Request::primaryShard() const {
+ assert( _didInit );
+
+ if ( _chunkManager ) {
+ if ( _chunkManager->numChunks() > 1 )
+ throw UserException( 8060 , "can't call primaryShard on a sharded collection" );
+ return _chunkManager->findChunk( _chunkManager->getShardKey().globalMin() )->getShard();
+ }
+ Shard s = _config->getShard( getns() );
+ uassert( 10194 , "can't call primaryShard on a sharded collection!" , s.ok() );
+ return s;
+ }
+
+ void Request::process( int attempt ) {
+ init();
+ int op = _m.operation();
+ assert( op > dbMsg );
+
+ if ( op == dbKillCursors ) {
+ cursorCache.gotKillCursors( _m );
+ return;
+ }
+
+
+ LOG(3) << "Request::process ns: " << getns() << " msg id:" << (int)(_m.header()->id) << " attempt: " << attempt << endl;
+
+ Strategy * s = SHARDED;
+ _counter = &opsNonSharded;
+
+ _d.markSet();
+
+ bool iscmd = false;
+ if ( op == dbQuery ) {
+ iscmd = isCommand();
+ s->queryOp( *this );
+ }
+ else if ( op == dbGetMore ) {
+ checkAuth( Auth::READ ); // this is important so someone can't steal a cursor
+ s->getMore( *this );
+ }
+ else {
+ checkAuth( Auth::WRITE );
+ s->writeOp( op, *this );
+ }
+
+ globalOpCounters.gotOp( op , iscmd );
+ _counter->gotOp( op , iscmd );
+ }
+
+ bool Request::isCommand() const {
+ int x = _d.getQueryNToReturn();
+ return ( x == 1 || x == -1 ) && strstr( getns() , ".$cmd" );
+ }
+
+ void Request::gotInsert() {
+ globalOpCounters.gotInsert();
+ _counter->gotInsert();
+ }
+
+ void Request::reply( Message & response , const string& fromServer ) {
+ assert( _didInit );
+ long long cursor =response.header()->getCursor();
+ if ( cursor ) {
+ if ( fromServer.size() ) {
+ cursorCache.storeRef( fromServer , cursor );
+ }
+ else {
+ // probably a getMore
+ // make sure we have a ref for this
+ assert( cursorCache.getRef( cursor ).size() );
+ }
+ }
+ _p->reply( _m , response , _id );
+ }
+
+} // namespace mongo