void SysParamInit( void ) //system param init { char* pdst = NULL; int iRet; /* BEGIN: Added by wupm, 2013/3/12 */ #ifdef HONESTECH ReadHTClassParams(); #endif InitSystemParam(); Textout("Read Config File , UUID = [%s], MAC = [%s]", bparam.stIEBaseParam.dwDeviceID, bparam.stIEBaseParam.szMac ); Textout("ApiLisense = [%s]",bparam.stIEBaseParam.dwApiLisense); nvram_init( RT2860_NVRAM ); IPCStart(); //ipc init #ifndef NOT_READ_MAC ReadFactoryMac(); //read mac Textout("ReadFactoryMac, UUID = [%s], MAC = [%s]", bparam.stIEBaseParam.dwDeviceID, bparam.stIEBaseParam.szMac ); Textout("ApiLisense = [%s]",bparam.stIEBaseParam.dwApiLisense); #endif ReadRactoryID(); //read deviceid Textout("ReadRactoryID, UUID = [%s], MAC = [%s]", bparam.stIEBaseParam.dwDeviceID, bparam.stIEBaseParam.szMac ); Textout("ApiLisense = [%s]",bparam.stIEBaseParam.dwApiLisense); //ReadDnsFactory(); //read dns factory ConfigVersion(); //config system version DateInit(); FactoryUpdateInit(); }
const ConfigVersion ShardedConnectionInfo::getVersion( const string& ns ) const { NSVersionMap::const_iterator it = _versions.find( ns ); if ( it != _versions.end() ) { return it->second; } else { return ConfigVersion( 0, OID() ); } }
const ConfigVersion ShardingState::getVersion( const string& ns ) const { scoped_lock lk(_mutex); ChunkManagersMap::const_iterator it = _chunks.find( ns ); if ( it != _chunks.end() ) { ShardChunkManagerPtr p = it->second; return p->getVersion(); } else { return ConfigVersion( 0, OID() ); } }
bool run(const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) { // Steps // 1. check basic config // 2. extract params from command // 3. fast check // 4. slow check (LOCKS) // step 1 lastError.disableForCommand(); ShardedConnectionInfo* info = ShardedConnectionInfo::get( true ); // make sure we have the mongos id for writebacks if ( ! checkMongosID( info , cmdObj["serverID"] , errmsg ) ) return false; bool authoritative = cmdObj.getBoolField( "authoritative" ); // check config server is ok or enable sharding if ( ! checkConfigOrInit( cmdObj["configdb"].valuestrsafe() , authoritative , errmsg , result ) ) return false; // check shard name/hosts are correct if ( cmdObj["shard"].type() == String ) { shardingState.gotShardName( cmdObj["shard"].String() ); shardingState.gotShardHost( cmdObj["shardHost"].String() ); } // Handle initial shard connection if( cmdObj["version"].eoo() && cmdObj["init"].trueValue() ) { result.append( "initialized", true ); return true; } // we can run on a slave up to here if ( ! isMaster( "admin" ) ) { result.append( "errmsg" , "not master" ); result.append( "note" , "from post init in setShardVersion" ); return false; } // step 2 string ns = cmdObj["setShardVersion"].valuestrsafe(); if ( ns.size() == 0 ) { errmsg = "need to specify namespace"; return false; } const ConfigVersion version = ConfigVersion( extractVersion( cmdObj["version"] , errmsg ), OID() ); if ( errmsg.size() ) return false; // step 3 const ConfigVersion oldVersion = info->getVersion(ns); const ConfigVersion globalVersion = shardingState.getVersion(ns); oldVersion.addToBSON( result, "oldVersion" ); if ( globalVersion.isSet() && version.isSet() ) { // this means there is no reset going on an either side // so its safe to make some assumptions if ( version.isEquivalentTo( globalVersion ) ) { // mongos and mongod agree! if ( ! oldVersion.isEquivalentTo( version ) ) { if ( oldVersion < globalVersion ) { info->setVersion( ns , version ); } else if ( authoritative ) { // this means there was a drop and our version is reset info->setVersion( ns , version ); } else { result.append( "ns" , ns ); result.appendBool( "need_authoritative" , true ); errmsg = "verifying drop on '" + ns + "'"; return false; } } return true; } } // step 4 // this is because of a weird segfault I saw and I can't see why this should ever be set massert( 13647 , str::stream() << "context should be empty here, is: " << cc().getContext()->ns() , cc().getContext() == 0 ); Lock::GlobalWrite setShardVersionLock; // TODO: can we get rid of this?? if ( oldVersion.isSet() && ! globalVersion.isSet() ) { // this had been reset info->setVersion( ns , ShardChunkVersion( 0, OID() ) ); } if ( ! version.isSet() && ! globalVersion.isSet() ) { // this connection is cleaning itself info->setVersion( ns , ShardChunkVersion( 0, OID() ) ); return true; } if ( ! version.isSet() && globalVersion.isSet() ) { if ( ! authoritative ) { result.appendBool( "need_authoritative" , true ); result.append( "ns" , ns ); globalVersion.addToBSON( result, "globalVersion" ); errmsg = "dropping needs to be authoritative"; return false; } log() << "wiping data for: " << ns << endl; globalVersion.addToBSON( result, "beforeDrop" ); // only setting global version on purpose // need clients to re-find meta-data shardingState.resetVersion( ns ); info->setVersion( ns , ShardChunkVersion( 0, OID() ) ); return true; } if ( version < oldVersion ) { errmsg = "this connection already had a newer version of collection '" + ns + "'"; result.append( "ns" , ns ); version.addToBSON( result, "newVersion" ); globalVersion.addToBSON( result, "globalVersion" ); return false; } if ( version < globalVersion ) { while ( shardingState.inCriticalMigrateSection() ) { dbtemprelease r; sleepmillis(2); OCCASIONALLY log() << "waiting till out of critical section" << endl; } errmsg = "shard global version for collection is higher than trying to set to '" + ns + "'"; result.append( "ns" , ns ); version.addToBSON( result, "version" ); globalVersion.addToBSON( result, "globalVersion" ); result.appendBool( "reloadConfig" , true ); return false; } if ( ! globalVersion.isSet() && ! authoritative ) { // Needed b/c when the last chunk is moved off a shard, the version gets reset to zero, which // should require a reload. // TODO: Maybe a more elegant way of doing this while ( shardingState.inCriticalMigrateSection() ) { dbtemprelease r; sleepmillis(2); OCCASIONALLY log() << "waiting till out of critical section for version reset" << endl; } // need authoritative for first look result.append( "ns" , ns ); result.appendBool( "need_authoritative" , true ); errmsg = "first time for collection '" + ns + "'"; return false; } Timer relockTime; { dbtemprelease unlock; ShardChunkVersion currVersion = version; if ( ! shardingState.trySetVersion( ns , currVersion ) ) { errmsg = str::stream() << "client version differs from config's for collection '" << ns << "'"; result.append( "ns" , ns ); version.addToBSON( result, "version" ); globalVersion.addToBSON( result, "globalVersion" ); return false; } } if ( relockTime.millis() >= ( cmdLine.slowMS - 10 ) ) { log() << "setShardVersion - relocking slow: " << relockTime.millis() << endl; } info->setVersion( ns , version ); return true; }
bool ShardingState::trySetVersion( const string& ns , ConfigVersion& version /* IN-OUT */ ) { // Currently this function is called after a getVersion(), which is the first "check", and the assumption here // is that we don't do anything nearly as long as a remote query in a thread between then and now. // Otherwise it may be worth adding an additional check without the _configServerMutex below, since then it // would be likely that the version may have changed in the meantime without waiting for or fetching config results. // TODO: Mutex-per-namespace? LOG( 2 ) << "trying to set shard version of " << version.toString() << " for '" << ns << "'" << endl; _configServerTickets.waitForTicket(); TicketHolderReleaser needTicketFrom( &_configServerTickets ); // fast path - double-check if requested version is at the same version as this chunk manager before verifying // against config server // // This path will short-circuit the version set if another thread already managed to update the version in the // meantime. First check is from getVersion(). // // cases: // + this shard updated the version for a migrate's commit (FROM side) // a client reloaded chunk state from config and picked the newest version // + two clients reloaded // one triggered the 'slow path' (below) // when the second's request gets here, the version is already current ConfigVersion storedVersion; ShardChunkManagerPtr currManager; { scoped_lock lk( _mutex ); ChunkManagersMap::const_iterator it = _chunks.find( ns ); if( it == _chunks.end() ){ // TODO: We need better semantic distinction between *no manager found* and // *manager of version zero found* log() << "no current chunk manager found for this shard, will initialize" << endl; } else{ currManager = it->second; if( ( storedVersion = it->second->getVersion() ).isEquivalentTo( version ) ) return true; } } LOG( 2 ) << "verifying cached version " << storedVersion.toString() << " and new version " << version.toString() << " for '" << ns << "'" << endl; // slow path - requested version is different than the current chunk manager's, if one exists, so must check for // newest version in the config server // // cases: // + a chunk moved TO here // (we don't bump up the version on the TO side but the commit to config does use higher version) // a client reloads from config an issued the request // + there was a take over from a secondary // the secondary had no state (managers) at all, so every client request will fall here // + a stale client request a version that's not current anymore // Can't lock default mutex while creating ShardChunkManager, b/c may have to create a new connection to myself const string c = (_configServer == _shardHost) ? "" /* local */ : _configServer; // If our epochs aren't compatible, it's not useful to use the old manager for chunk diffs if( currManager && ! currManager->getCollVersion().hasCompatibleEpoch( version ) ){ warning() << "detected incompatible version epoch in new version " << version << ", old version was " << currManager->getCollVersion() << endl; currManager.reset(); } ShardChunkManagerPtr p( ShardChunkManager::make( c , ns , _shardName, currManager ) ); // Handle the case where the collection isn't sharded more gracefully if( p->getKey().isEmpty() ){ version = ConfigVersion( 0, OID() ); // There was an error getting any data for this collection, return false return false; } { // NOTE: This lock prevents the ns version from changing while a write operation occurs. Lock::DBRead readLk(ns); // This lock prevents simultaneous metadata changes using the same map scoped_lock lk( _mutex ); // since we loaded the chunk manager unlocked, other thread may have done the same // make sure we keep the freshest config info only ChunkManagersMap::const_iterator it = _chunks.find( ns ); if ( it == _chunks.end() || p->getVersion() >= it->second->getVersion() ) { _chunks[ns] = p; } ChunkVersion oldVersion = version; version = p->getVersion(); return oldVersion.isEquivalentTo( version ); } }
bool _handlePossibleShardedMessage( Message &m, DbResponse* dbresponse ) { DEV verify( shardingState.enabled() ); int op = m.operation(); if ( op < 2000 || op >= 3000 || op == dbGetMore // cursors are weird ) return false; DbMessage d(m); const char *ns = d.getns(); string errmsg; // We don't care about the version here, since we're returning it later in the writeback ConfigVersion received, wanted; if ( shardVersionOk( ns , errmsg, received, wanted ) ) { return false; } LOG(1) << "connection meta data too old - will retry ns:(" << ns << ") op:(" << opToString(op) << ") " << errmsg << endl; if ( doesOpGetAResponse( op ) ) { verify( dbresponse ); BufBuilder b( 32768 ); b.skip( sizeof( QueryResult ) ); { BSONObj obj = BSON( "$err" << errmsg << "ns" << ns ); b.appendBuf( obj.objdata() , obj.objsize() ); } QueryResult *qr = (QueryResult*)b.buf(); qr->_resultFlags() = ResultFlag_ErrSet | ResultFlag_ShardConfigStale; qr->len = b.len(); qr->setOperation( opReply ); qr->cursorId = 0; qr->startingFrom = 0; qr->nReturned = 1; b.decouple(); Message * resp = new Message(); resp->setData( qr , true ); dbresponse->response = resp; dbresponse->responseTo = m.header()->id; return true; } uassert( 9517 , "writeback" , ( d.reservedField() & DbMessage::Reserved_FromWriteback ) == 0 ); OID writebackID; writebackID.init(); lastError.getSafe()->writeback( writebackID ); const OID& clientID = ShardedConnectionInfo::get(false)->getID(); massert( 10422 , "write with bad shard config and no server id!" , clientID.isSet() ); LOG(1) << "got write with an old config - writing back ns: " << ns << endl; LOG(1) << m.toString() << endl; BSONObjBuilder b; b.appendBool( "writeBack" , true ); b.append( "ns" , ns ); b.append( "id" , writebackID ); b.append( "connectionId" , cc().getConnectionId() ); b.append( "instanceIdent" , prettyHostName() ); shardingState.getVersion( ns ).addToBSON( b ); ShardedConnectionInfo* info = ShardedConnectionInfo::get( false ); ( info ? info->getVersion(ns) : ConfigVersion( 0, OID() ) ).addToBSON( b, "yourVersion" ); b.appendBinData( "msg" , m.header()->len , bdtCustom , (char*)(m.singleData()) ); LOG(2) << "writing back msg with len: " << m.header()->len << " op: " << m.operation() << endl; writeBackManager.queueWriteBack( clientID.str() , b.obj() ); return true; }