authentication_table.h   authentication_table.h 
skipping to change at line 62 skipping to change at line 62
BSONObj toBSON() const; BSONObj toBSON() const;
BSONObj copyCommandObjAddingAuth( const BSONObj& cmdObj ) const; BSONObj copyCommandObjAddingAuth( const BSONObj& cmdObj ) const;
static const AuthenticationTable& getInternalSecurityAuthentication Table(); static const AuthenticationTable& getInternalSecurityAuthentication Table();
// Only used once at startup to setup the authentication table. // Only used once at startup to setup the authentication table.
static AuthenticationTable& getMutableInternalSecurityAuthenticatio nTable(); static AuthenticationTable& getMutableInternalSecurityAuthenticatio nTable();
static const string fieldName; static const string fieldName;
private: private:
bool _shouldSendInternalSecurityTable() const;
typedef map<std::string,Auth> DBAuthMap; typedef map<std::string,Auth> DBAuthMap;
DBAuthMap _dbs; // dbname -> auth DBAuthMap _dbs; // dbname -> auth
}; };
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 3 lines changed or added


 chunk.h   chunk.h 
skipping to change at line 98 skipping to change at line 98
void appendShortVersion( const char * name , BSONObjBuilder& b ) co nst; void appendShortVersion( const char * name , BSONObjBuilder& b ) co nst;
ShardChunkVersion getLastmod() const { return _lastmod; } ShardChunkVersion getLastmod() const { return _lastmod; }
void setLastmod( ShardChunkVersion v ) { _lastmod = v; } void setLastmod( ShardChunkVersion v ) { _lastmod = v; }
// //
// split support // split support
// //
long getBytesWritten() const { return _dataWritten; }
// Const since _dataWritten is mutable and a heuristic
// TODO: Split data tracking and chunk information
void setBytesWritten( long bytesWritten ) const { _dataWritten = by
tesWritten; }
/** /**
* if the amount of data written nears the max size of a shard * if the amount of data written nears the max size of a shard
* then we check the real size, and if its too big, we split * then we check the real size, and if its too big, we split
* @return if something was split * @return if something was split
*/ */
bool splitIfShould( long dataWritten ) const; bool splitIfShould( long dataWritten ) const;
/** /**
* Splits this chunk at a non-specificed split key to be chosen by the mongod holding this chunk. * Splits this chunk at a non-specificed split key to be chosen by the mongod holding this chunk.
* *
 End of changes. 1 change blocks. 
0 lines changed or deleted 6 lines changed or added


 client_common.h   client_common.h 
skipping to change at line 46 skipping to change at line 46
class ClientBasic : boost::noncopyable { class ClientBasic : boost::noncopyable {
public: public:
virtual ~ClientBasic(){} virtual ~ClientBasic(){}
virtual const AuthenticationInfo * getAuthenticationInfo() const = 0; virtual const AuthenticationInfo * getAuthenticationInfo() const = 0;
virtual AuthenticationInfo * getAuthenticationInfo() = 0; virtual AuthenticationInfo * getAuthenticationInfo() = 0;
virtual bool hasRemote() const = 0; virtual bool hasRemote() const = 0;
virtual HostAndPort getRemote() const = 0; virtual HostAndPort getRemote() const = 0;
static ClientBasic* getCurrent(); static ClientBasic* getCurrent();
static bool hasCurrent();
}; };
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 client_info.h   client_info.h 
skipping to change at line 101 skipping to change at line 101
BSONObjBuilder& result , BSONObjBuilder& result ,
string& errmsg, string& errmsg,
bool fromWriteBackListener = false ); bool fromWriteBackListener = false );
/** @return if its ok to auto split from this client */ /** @return if its ok to auto split from this client */
bool autoSplitOk() const { return _autoSplitOk && Chunk::ShouldAuto Split; } bool autoSplitOk() const { return _autoSplitOk && Chunk::ShouldAuto Split; }
void noAutoSplit() { _autoSplitOk = false; } void noAutoSplit() { _autoSplitOk = false; }
static ClientInfo * get(); static ClientInfo * get();
// Returns whether or not a ClientInfo for this thread has already
been created and stored
// in _tlInfo.
static bool exists();
const AuthenticationInfo* getAuthenticationInfo() const { return (A uthenticationInfo*)&_ai; } const AuthenticationInfo* getAuthenticationInfo() const { return (A uthenticationInfo*)&_ai; }
AuthenticationInfo* getAuthenticationInfo() { return (Authenticatio nInfo*)&_ai; } AuthenticationInfo* getAuthenticationInfo() { return (Authenticatio nInfo*)&_ai; }
bool isAdmin() { return _ai.isAuthorized( "admin" ); } bool isAdmin() { return _ai.isAuthorized( "admin" ); }
private: private:
AuthenticationInfo _ai; AuthenticationInfo _ai;
struct WBInfo { struct WBInfo {
WBInfo( const WriteBackListener::ConnectionIdent& c, OID o, boo l fromLastOperation ) WBInfo( const WriteBackListener::ConnectionIdent& c, OID o, boo l fromLastOperation )
: ident( c ), id( o ), fromLastOperation( fromLastOperation ) {} : ident( c ), id( o ), fromLastOperation( fromLastOperation ) {}
WriteBackListener::ConnectionIdent ident; WriteBackListener::ConnectionIdent ident;
 End of changes. 1 change blocks. 
0 lines changed or deleted 6 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 146 skipping to change at line 146
_id = c->_cursorid; _id = c->_cursorid;
} }
else { else {
_c = 0; _c = 0;
_id = INVALID_CURSOR_ID; _id = INVALID_CURSOR_ID;
} }
} }
~Holder() { ~Holder() {
DESTRUCTOR_GUARD ( reset(); ); DESTRUCTOR_GUARD ( reset(); );
} }
ClientCursor* get() { return _c; }
operator bool() { return _c; } operator bool() { return _c; }
ClientCursor * operator-> () { return _c; } ClientCursor * operator-> () { return _c; }
const ClientCursor * operator-> () const { return _c; } const ClientCursor * operator-> () const { return _c; }
/** Release ownership of the ClientCursor. */ /** Release ownership of the ClientCursor. */
void release() { void release() {
_c = 0; _c = 0;
_id = INVALID_CURSOR_ID; _id = INVALID_CURSOR_ID;
} }
private: private:
ClientCursor *_c; ClientCursor *_c;
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 d_logic.h   d_logic.h 
skipping to change at line 47 skipping to change at line 47
// -------------- // --------------
class ShardingState { class ShardingState {
public: public:
ShardingState(); ShardingState();
bool enabled() const { return _enabled; } bool enabled() const { return _enabled; }
const string& getConfigServer() const { return _configServer; } const string& getConfigServer() const { return _configServer; }
void enable( const string& server ); void enable( const string& server );
// Initialize sharding state and begin authenticating outgoing conn
ections and handling
// shard versions. If this is not run before sharded operations oc
cur auth will not work
// and versions will not be tracked.
static void initialize(const string& server);
void gotShardName( const string& name ); void gotShardName( const string& name );
void gotShardHost( string host ); void gotShardHost( string host );
string getShardName() { return _shardName; } string getShardName() { return _shardName; }
string getShardHost() { return _shardHost; } string getShardHost() { return _shardHost; }
/** Reverts back to a state where this mongod is not sharded. */ /** Reverts back to a state where this mongod is not sharded. */
void resetShardingState(); void resetShardingState();
// versioning support // versioning support
 End of changes. 1 change blocks. 
0 lines changed or deleted 7 lines changed or added


 log.h   log.h 
skipping to change at line 41 skipping to change at line 41
#include "mongo/util/exit_code.h" #include "mongo/util/exit_code.h"
#ifndef _WIN32 #ifndef _WIN32
#include <syslog.h> #include <syslog.h>
#endif #endif
namespace mongo { namespace mongo {
enum ExitCode; enum ExitCode;
enum LogLevel { LL_DEBUG , LL_INFO , LL_NOTICE , LL_WARNING , LL_ERROR // using negative numbers so these are always less than ::mongo::loglev
, LL_SEVERE }; el (see MONGO_LOG)
enum LogLevel { LL_DEBUG=-1000 , LL_INFO , LL_NOTICE , LL_WARNING , LL
_ERROR , LL_SEVERE };
inline const char * logLevelToString( LogLevel l ) { inline const char * logLevelToString( LogLevel l ) {
switch ( l ) { switch ( l ) {
case LL_DEBUG: case LL_DEBUG:
case LL_INFO: case LL_INFO:
case LL_NOTICE: case LL_NOTICE:
return ""; return "";
case LL_WARNING: case LL_WARNING:
return "warning" ; return "warning" ;
case LL_ERROR: case LL_ERROR:
skipping to change at line 113 skipping to change at line 114
} }
const string& getLabel() const { return _label; } const string& getLabel() const { return _label; }
int getLevel() const { return _level; } int getLevel() const { return _level; }
private: private:
string _label; string _label;
int _level; int _level;
}; };
inline bool operator<( const LabeledLevel& ll, const int i ) { return l
l.getLevel() < i; }
inline bool operator<( const int i, const LabeledLevel& ll ) { return i
< ll.getLevel(); }
inline bool operator>( const LabeledLevel& ll, const int i ) { return l
l.getLevel() > i; }
inline bool operator>( const int i, const LabeledLevel& ll ) { return i
> ll.getLevel(); }
inline bool operator<=( const LabeledLevel& ll, const int i ) { return
ll.getLevel() <= i; }
inline bool operator<=( const int i, const LabeledLevel& ll ) { return
i <= ll.getLevel(); }
inline bool operator>=( const LabeledLevel& ll, const int i ) { return
ll.getLevel() >= i; }
inline bool operator>=( const int i, const LabeledLevel& ll ) { return
i >= ll.getLevel(); }
inline bool operator==( const LabeledLevel& ll, const int i ) { return
ll.getLevel() == i; }
inline bool operator==( const int i, const LabeledLevel& ll ) { return
i == ll.getLevel(); }
class LazyString { class LazyString {
public: public:
virtual ~LazyString() {} virtual ~LazyString() {}
virtual string val() const = 0; virtual string val() const = 0;
}; };
// Utility class for stringifying object only when val() called. // Utility class for stringifying object only when val() called.
template< class T > template< class T >
class LazyStringImpl : public LazyString { class LazyStringImpl : public LazyString {
public: public:
skipping to change at line 332 skipping to change at line 344
globalTees->push_back( t ); globalTees->push_back( t );
} }
void removeGlobalTee( Tee * tee ); void removeGlobalTee( Tee * tee );
void indentInc(){ indent++; } void indentInc(){ indent++; }
void indentDec(){ indent--; } void indentDec(){ indent--; }
int getIndent() const { return indent; } int getIndent() const { return indent; }
private: private:
static boost::thread_specific_ptr<Logstream> tsp;
Logstream() { Logstream() {
indent = 0; indent = 0;
_init(); _init();
} }
void _init() { void _init() {
ss.str(""); ss.str("");
logLevel = LL_INFO; logLevel = LL_INFO;
} }
public: public:
static Logstream& get(); static Logstream& get();
skipping to change at line 379 skipping to change at line 390
set tlogLevel to -1 to suppress tlog() output in a test program. */ set tlogLevel to -1 to suppress tlog() output in a test program. */
Nullstream& tlog( int level = 0 ); Nullstream& tlog( int level = 0 );
// log if debug build or if at a certain level // log if debug build or if at a certain level
inline Nullstream& dlog( int level ) { inline Nullstream& dlog( int level ) {
if ( level <= logLevel || DEBUG_BUILD ) if ( level <= logLevel || DEBUG_BUILD )
return Logstream::get().prolog(); return Logstream::get().prolog();
return nullstream; return nullstream;
} }
inline Nullstream& log( int level ) { #define MONGO_LOG(level) \
( MONGO_likely( ::mongo::logLevel < (level) ) ) \
? ::mongo::nullstream : ::mongo::logWithLevel(level)
#define LOG MONGO_LOG
inline Nullstream& log() {
return Logstream::get().prolog();
}
// Use MONGO_LOG() instead of this
inline Nullstream& logWithLevel( int level ) {
if ( level > logLevel ) if ( level > logLevel )
return nullstream; return nullstream;
return Logstream::get().prolog(); return Logstream::get().prolog();
} }
#define MONGO_LOG(level) if ( MONGO_likely(logLevel < (level)) ) { } else l inline Nullstream& logWithLevel( LogLevel l ) {
og( level )
#define LOG MONGO_LOG
inline Nullstream& log( LogLevel l ) {
return Logstream::get().prolog().setLogLevel( l ); return Logstream::get().prolog().setLogLevel( l );
} }
inline Nullstream& log( const LabeledLevel& ll ) { inline Nullstream& logWithLevel( const LabeledLevel& ll ) {
Nullstream& stream = log( ll.getLevel() ); Nullstream& stream = logWithLevel( ll.getLevel() );
if( ll.getLabel() != "" ) if( ll.getLabel() != "" )
stream << "[" << ll.getLabel() << "] "; stream << "[" << ll.getLabel() << "] ";
return stream; return stream;
} }
inline Nullstream& log() {
return Logstream::get().prolog();
}
inline Nullstream& error() { inline Nullstream& error() {
return log( LL_ERROR ); return logWithLevel( LL_ERROR );
} }
inline Nullstream& warning() { inline Nullstream& warning() {
return log( LL_WARNING ); return logWithLevel( LL_WARNING );
} }
/* default impl returns "" -- mongod overrides */ /* default impl returns "" -- mongod overrides */
extern const char * (*getcurns)(); extern const char * (*getcurns)();
inline Nullstream& problem( int level = 0 ) { inline Nullstream& problem( int level = 0 ) {
if ( level > logLevel ) if ( level > logLevel )
return nullstream; return nullstream;
Logstream& l = Logstream::get().prolog(); Logstream& l = Logstream::get().prolog();
l << ' ' << getcurns() << ' '; l << ' ' << getcurns() << ' ';
 End of changes. 9 change blocks. 
17 lines changed or deleted 41 lines changed or added


 optime.h   optime.h 
skipping to change at line 45 skipping to change at line 45
*/ */
#pragma pack(4) #pragma pack(4)
class OpTime { class OpTime {
unsigned i; // ordinal comes first so we can do a single 64 bit com pare on little endian unsigned i; // ordinal comes first so we can do a single 64 bit com pare on little endian
unsigned secs; unsigned secs;
static OpTime last; static OpTime last;
static OpTime skewed(); static OpTime skewed();
public: public:
static void setLast(const Date_t &date) { static void setLast(const Date_t &date) {
mutex::scoped_lock lk(m); mutex::scoped_lock lk(m);
notifier.notify_all(); // won't really do anything until write- lock released
last = OpTime(date); last = OpTime(date);
notifier.notify_all();
} }
static void setLast(const OpTime &new_last) {
mutex::scoped_lock lk(m);
last = new_last;
notifier.notify_all();
}
unsigned getSecs() const { unsigned getSecs() const {
return secs; return secs;
} }
unsigned getInc() const { unsigned getInc() const {
return i; return i;
} }
OpTime(Date_t date) { OpTime(Date_t date) {
reinterpret_cast<unsigned long long&>(*this) = date.millis; reinterpret_cast<unsigned long long&>(*this) = date.millis;
dassert( (int)secs >= 0 ); dassert( (int)secs >= 0 );
} }
 End of changes. 3 change blocks. 
1 lines changed or deleted 7 lines changed or added


 paths.h   paths.h 
skipping to change at line 112 skipping to change at line 112
#ifdef __linux__ // this isn't needed elsewhere #ifdef __linux__ // this isn't needed elsewhere
// if called without a fully qualified path it asserts; that makes mongoperf fail. so make a warning. need a better solution longer term. // if called without a fully qualified path it asserts; that makes mongoperf fail. so make a warning. need a better solution longer term.
// massert(13652, str::stream() << "Couldn't find parent dir for fi le: " << file.string(), ); // massert(13652, str::stream() << "Couldn't find parent dir for fi le: " << file.string(), );
if( !file.has_branch_path() ) { if( !file.has_branch_path() ) {
log() << "warning flushMYDirectory couldn't find parent dir for file: " << file.string() << endl; log() << "warning flushMYDirectory couldn't find parent dir for file: " << file.string() << endl;
return; return;
} }
boost::filesystem::path dir = file.branch_path(); // parent_path in new boosts boost::filesystem::path dir = file.branch_path(); // parent_path in new boosts
log(1) << "flushing directory " << dir.string() << endl; LOG(1) << "flushing directory " << dir.string() << endl;
int fd = ::open(dir.string().c_str(), O_RDONLY); // DO NOT THROW OR ASSERT BEFORE CLOSING int fd = ::open(dir.string().c_str(), O_RDONLY); // DO NOT THROW OR ASSERT BEFORE CLOSING
massert(13650, str::stream() << "Couldn't open directory '" << dir. string() << "' for flushing: " << errnoWithDescription(), fd >= 0); massert(13650, str::stream() << "Couldn't open directory '" << dir. string() << "' for flushing: " << errnoWithDescription(), fd >= 0);
if (fsync(fd) != 0){ if (fsync(fd) != 0){
int e = errno; int e = errno;
close(fd); close(fd);
massert(13651, str::stream() << "Couldn't fsync directory '" << dir.string() << "': " << errnoWithDescription(e), false); massert(13651, str::stream() << "Couldn't fsync directory '" << dir.string() << "': " << errnoWithDescription(e), false);
} }
close(fd); close(fd);
#endif #endif
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 rs.h   rs.h 
skipping to change at line 483 skipping to change at line 483
// this is called from within a writelock in logOpRS // this is called from within a writelock in logOpRS
unsigned selfId() const { return _id; } unsigned selfId() const { return _id; }
Manager *mgr; Manager *mgr;
GhostSync *ghost; GhostSync *ghost;
/** /**
* This forces a secondary to go into recovering state and stay the re * This forces a secondary to go into recovering state and stay the re
* until this is called again, passing in "false". Multiple thread s can * until this is called again, passing in "false". Multiple thread s can
* call this and it will leave maintenance mode once all of the cal lers * call this and it will leave maintenance mode once all of the cal lers
* have called it again, passing in false. * have called it again, passing in false.
*/ */
void setMaintenanceMode(const bool inc); bool setMaintenanceMode(const bool inc);
private: private:
Member* head() const { return _members.head(); } Member* head() const { return _members.head(); }
public: public:
const Member* findById(unsigned id) const; const Member* findById(unsigned id) const;
private: private:
void _getTargets(list<Target>&, int &configVersion); void _getTargets(list<Target>&, int &configVersion);
void getTargets(list<Target>&, int &configVersion); void getTargets(list<Target>&, int &configVersion);
void startThreads(); void startThreads();
friend class FeedbackThread; friend class FeedbackThread;
friend class CmdReplSetElect; friend class CmdReplSetElect;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 security.h   security.h 
skipping to change at line 47 skipping to change at line 47
public: public:
void startRequest(); // need to call at the beginning of each reque st void startRequest(); // need to call at the beginning of each reque st
void setIsALocalHostConnectionWithSpecialAuthPowers(); // called, i f localhost, when conneciton established. void setIsALocalHostConnectionWithSpecialAuthPowers(); // called, i f localhost, when conneciton established.
AuthenticationInfo() { AuthenticationInfo() {
_isLocalHost = false; _isLocalHost = false;
_isLocalHostAndLocalHostIsAuthorizedForAll = false; _isLocalHostAndLocalHostIsAuthorizedForAll = false;
_usingTempAuth = false; _usingTempAuth = false;
} }
~AuthenticationInfo() {} ~AuthenticationInfo() {}
bool isLocalHost() const { return _isLocalHost; } // why are you ca lling this? makes no sense to be externalized bool isLocalHost() const { return _isLocalHost; } // why are you ca lling this? makes no sense to be externalized
bool isSpecialLocalhostAdmin() const;
// -- modifiers ---- // -- modifiers ----
void logout(const std::string& dbname ) { void logout(const std::string& dbname ) {
scoped_spinlock lk(_lock); scoped_spinlock lk(_lock);
_authTable.removeAuth( dbname ); _authTable.removeAuth( dbname );
} }
void authorize(const std::string& dbname , const std::string& user ) { void authorize(const std::string& dbname , const std::string& user ) {
scoped_spinlock lk(_lock); scoped_spinlock lk(_lock);
_authTable.addAuth( dbname, user, Auth::WRITE ); _authTable.addAuth( dbname, user, Auth::WRITE );
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 shard.h   shard.h 
skipping to change at line 287 skipping to change at line 287
bool ok() const { return _conn > 0; } bool ok() const { return _conn > 0; }
/** /**
this just passes through excpet it checks for stale configs this just passes through excpet it checks for stale configs
*/ */
bool runCommand( const string& db , const BSONObj& cmd , BSONObj& r es ); bool runCommand( const string& db , const BSONObj& cmd , BSONObj& r es );
/** checks all of my thread local connections for the version of th is ns */ /** checks all of my thread local connections for the version of th is ns */
static void checkMyConnectionVersions( const string & ns ); static void checkMyConnectionVersions( const string & ns );
/**
* Whether or not we should release all connections after an operat
ion with
* a response.
*/
static bool releaseConnectionsAfterResponse;
/**
* Returns all the current sharded connections to the pool.
* Note: This is *dangerous* if we have GLE state.
*/
static void releaseMyConnections();
private: private:
void _init(); void _init();
void _finishInit(); void _finishInit();
bool _finishedInit; bool _finishedInit;
string _addr; string _addr;
string _ns; string _ns;
ChunkManagerPtr _manager; ChunkManagerPtr _manager;
 End of changes. 1 change blocks. 
0 lines changed or deleted 13 lines changed or added


 update_internal.h   update_internal.h 
skipping to change at line 437 skipping to change at line 437
return true; return true;
case Mod::BIT: case Mod::BIT:
case Mod::BITAND: case Mod::BITAND:
case Mod::BITOR: case Mod::BITOR:
return true; return true;
default: default:
return false; return false;
} }
} }
const char* getOpLogName() const;
void appendForOpLog( BSONObjBuilder& b ) const; void appendForOpLog( BSONObjBuilder& b ) const;
void apply( BSONBuilderBase& b , BSONElement in ) { void apply( BSONBuilderBase& b , BSONElement in ) {
m->apply( b , in , *this ); m->apply( b , in , *this );
} }
void appendIncValue( BSONBuilderBase& b , bool useFullName ) const { void appendIncValue( BSONBuilderBase& b , bool useFullName ) const {
const char* n = useFullName ? m->fieldName : m->shortFieldName; const char* n = useFullName ? m->fieldName : m->shortFieldName;
switch ( incType ) { switch ( incType ) {
skipping to change at line 617 skipping to change at line 618
// re-writing for oplog // re-writing for oplog
bool DEPRECATED_needOpLogRewrite() const { bool DEPRECATED_needOpLogRewrite() const {
for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ )
if ( i->second->DEPRECATED_needOpLogRewrite() ) if ( i->second->DEPRECATED_needOpLogRewrite() )
return true; return true;
return false; return false;
} }
BSONObj getOpLogRewrite() const { BSONObj getOpLogRewrite() const;
BSONObjBuilder b;
for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m
ods.end(); i++ )
i->second->appendForOpLog( b );
return b.obj();
}
bool DEPRECATED_haveArrayDepMod() const { bool DEPRECATED_haveArrayDepMod() const {
for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ )
if ( i->second->m->arrayDep() ) if ( i->second->m->arrayDep() )
return true; return true;
return false; return false;
} }
void DEPRECATED_appendSizeSpecForArrayDepMods( BSONObjBuilder& b ) const { void DEPRECATED_appendSizeSpecForArrayDepMods( BSONObjBuilder& b ) const {
for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) { for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) {
 End of changes. 2 change blocks. 
7 lines changed or deleted 2 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/