0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 01:21:03 +01:00
mongodb/db/clientcursor.h

159 lines
5.1 KiB
C
Raw Normal View History

2009-03-24 19:19:03 +01:00
/* clientcursor.h */
/**
* Copyright (C) 2008 10gen Inc.
2008-12-29 02:28:49 +01:00
*
* 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.
2008-12-29 02:28:49 +01:00
*
* 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.
2008-12-29 02:28:49 +01:00
*
* 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/>.
*/
2009-03-24 19:19:03 +01:00
/* Cursor -- and its derived classes -- are our internal cursors.
2008-06-06 20:59:58 +02:00
2008-12-29 02:28:49 +01:00
ClientCursor is a wrapper that represents a cursorid from our database
2008-06-06 20:59:58 +02:00
application's perspective.
*/
#pragma once
#include "../stdafx.h"
2009-05-11 16:44:27 +02:00
#include "cursor.h"
#include "jsobj.h"
#include "../util/message.h"
#include "storage.h"
#include "dbhelpers.h"
2009-05-11 21:09:30 +02:00
#include "matcher.h"
2008-06-06 20:59:58 +02:00
2009-01-14 23:09:51 +01:00
namespace mongo {
2009-03-24 19:19:03 +01:00
typedef long long CursorId; /* passed to the client so it can send back on getMore */
class Cursor; /* internal server cursor base class */
class ClientCursor;
2009-10-09 19:37:30 +02:00
/* todo: make this map be per connection. this will prevent cursor hijacking security attacks perhaps.
*/
typedef map<CursorId, ClientCursor*> CCById;
2009-10-09 19:37:30 +02:00
typedef multimap<DiskLoc, ClientCursor*> CCByLoc;
2008-06-06 20:59:58 +02:00
2009-05-11 16:44:27 +02:00
extern BSONObj id_obj;
class ClientCursor {
2009-10-07 21:34:14 +02:00
friend class CmdCursorInfo;
2009-10-09 17:24:37 +02:00
DiskLoc _lastLoc; // use getter and setter not this (important)
unsigned _idleAgeMillis; // how long has the cursor been around, relative to server idle time
bool _liveForever; // if true, never time out cursor
2009-10-07 21:34:14 +02:00
static CCById clientCursorsById;
static CCByLoc byLoc;
2009-10-09 17:24:37 +02:00
static boost::recursive_mutex ccmutex; // must use this for all statics above!
static CursorId allocCursorId_inlock();
public:
2009-10-09 17:24:37 +02:00
/*const*/ CursorId cursorid;
string ns;
2009-04-07 16:40:10 +02:00
auto_ptr<KeyValJSMatcher> matcher;
auto_ptr<Cursor> c;
2009-10-09 17:24:37 +02:00
int pos; // # objects into the cursor so far
BSONObj query;
2009-10-09 17:24:37 +02:00
ClientCursor() : _idleAgeMillis(0), _liveForever(false), pos(0) {
recursive_boostlock lock(ccmutex);
cursorid = allocCursorId_inlock();
clientCursorsById.insert( make_pair(cursorid, this) );
}
~ClientCursor();
DiskLoc lastLoc() const {
return _lastLoc;
}
2009-10-09 17:24:37 +02:00
auto_ptr< FieldMatcher > filter; // which fields query wants returned
2009-03-27 21:27:35 +01:00
Message originalMessage; // this is effectively an auto ptr for data the matcher points to
2008-06-06 20:59:58 +02:00
/* Get rid of cursors for namespaces that begin with nsprefix.
Used by drop, deleteIndexes, dropDatabase.
*/
static void invalidate(const char *nsPrefix);
2008-07-24 22:07:18 +02:00
2009-10-09 17:24:37 +02:00
private:
2009-11-27 22:40:58 +01:00
void setLastLoc_inlock(DiskLoc);
2009-10-09 17:24:37 +02:00
static ClientCursor* find_inlock(CursorId id, bool warn = true) {
CCById::iterator it = clientCursorsById.find(id);
if ( it == clientCursorsById.end() ) {
if ( warn )
OCCASIONALLY out() << "ClientCursor::find(): cursor not found in map " << id << " (ok after a drop)\n";
return 0;
}
return it->second;
2008-12-29 02:28:49 +01:00
}
2009-10-09 17:24:37 +02:00
public:
static ClientCursor* find(CursorId id, bool warn = true) {
recursive_boostlock lock(ccmutex);
return find_inlock(id, warn);
}
static bool erase(CursorId id) {
recursive_boostlock lock(ccmutex);
ClientCursor *cc = find_inlock(id);
if ( cc ) {
delete cc;
return true;
}
return false;
}
2008-06-06 20:59:58 +02:00
/* call when cursor's location changes so that we can update the
cursorsbylocation map. if you are locked and internally iterating, only
need to call when you are ready to "unlock".
*/
void updateLocation();
2008-06-06 20:59:58 +02:00
void cleanupByLocation(DiskLoc loc);
2009-05-11 16:44:27 +02:00
void mayUpgradeStorage() {
2009-10-09 17:24:37 +02:00
/* if ( !ids_.get() )
return;
2009-05-11 16:44:27 +02:00
stringstream ss;
ss << ns << "." << cursorid;
2009-07-03 00:20:32 +02:00
ids_->mayUpgradeStorage( ss.str() );*/
2009-05-11 16:44:27 +02:00
}
2009-01-14 23:09:51 +01:00
/**
* @param millis amount of idle passed time since last call
*/
bool shouldTimeout( unsigned millis ){
_idleAgeMillis += millis;
return ! _liveForever && _idleAgeMillis > 600000;
}
unsigned idleTime(){
return _idleAgeMillis;
}
static void idleTimeReport(unsigned millis);
2009-10-09 17:24:37 +02:00
void liveForever() {
_liveForever = true;
}
static unsigned byLocSize(); // just for diagnostics
// static void idleTimeReport(unsigned millis);
2009-10-09 17:24:37 +02:00
static void informAboutToDeleteBucket(const DiskLoc& b);
static void aboutToDelete(const DiskLoc& dl);
};
2009-01-14 23:09:51 +01:00
} // namespace mongo