/** @file touch.cpp
compaction of deleted space in pdfiles (datafiles)
*/
/**
* Copyright (C) 2012 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,b
* 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 .
*/
#include "pch.h"
#include
#include
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/commands.h"
#include "mongo/db/d_concurrency.h"
#include "mongo/db/curop-inl.h"
#include "mongo/db/index.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/pdfile.h"
#include "mongo/util/timer.h"
#include "mongo/util/touch_pages.h"
namespace mongo {
class TouchCmd : public Command {
public:
virtual LockType locktype() const { return NONE; }
virtual bool adminOnly() const { return false; }
virtual bool slaveOk() const { return true; }
virtual bool maintenanceMode() const { return true; }
virtual bool logTheOp() { return false; }
virtual void help( stringstream& help ) const {
help << "touch collection\n"
"Page in all pages of memory containing every extent for the given collection\n"
"{ touch : , [data : true] , [index : true] }\n"
" at least one of data or index must be true; default is both are false\n";
}
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector* out) {
ActionSet actions;
actions.addAction(ActionType::touch);
out->push_back(Privilege(AuthorizationManager::SERVER_RESOURCE_NAME, actions));
}
TouchCmd() : Command("touch") { }
virtual bool run(const string& db,
BSONObj& cmdObj,
int,
string& errmsg,
BSONObjBuilder& result,
bool fromRepl) {
string coll = cmdObj.firstElement().valuestr();
if( coll.empty() || db.empty() ) {
errmsg = "no collection name specified";
return false;
}
string ns = db + '.' + coll;
if ( ! NamespaceString::normal(ns.c_str()) ) {
errmsg = "bad namespace name";
return false;
}
bool touch_indexes( cmdObj["index"].trueValue() );
bool touch_data( cmdObj["data"].trueValue() );
if ( ! (touch_indexes || touch_data) ) {
errmsg = "must specify at least one of (data:true, index:true)";
return false;
}
bool ok = touch( ns, errmsg, touch_data, touch_indexes, result );
return ok;
}
bool touch( std::string& ns,
std::string& errmsg,
bool touch_data,
bool touch_indexes,
BSONObjBuilder& result ) {
if (touch_data) {
log() << "touching namespace " << ns << endl;
touchNs( ns );
log() << "touching namespace " << ns << " complete" << endl;
}
if (touch_indexes) {
// enumerate indexes
std::vector< std::string > indexes;
{
Client::ReadContext ctx(ns);
NamespaceDetails *nsd = nsdetails(ns);
massert( 16153, "namespace does not exist", nsd );
NamespaceDetails::IndexIterator ii = nsd->ii();
while ( ii.more() ) {
IndexDetails& idx = ii.next();
indexes.push_back( idx.indexNamespace() );
}
}
for ( std::vector::const_iterator it = indexes.begin();
it != indexes.end();
it++ ) {
touchNs( *it );
}
}
return true;
}
};
static TouchCmd touchCmd;
}