int CollectorList::sendUpdates (int cmd, ClassAd * ad1, ClassAd* ad2, bool nonblocking) { int success_count = 0; if ( ! adSeq) { adSeq = new DCCollectorAdSequences(); } // advance the sequence numbers for these ads // time_t now = time(NULL); DCCollectorAdSeq * seqgen = adSeq->getAdSeq(*ad1); if (seqgen) { seqgen->advance(now); } this->rewind(); DCCollector * daemon; while (this->next(daemon)) { dprintf( D_FULLDEBUG, "Trying to update collector %s\n", daemon->addr() ); if( daemon->sendUpdate(cmd, ad1, *adSeq, ad2, nonblocking) ) { success_count++; } } return success_count; }
// Copy constructor for the Ad Sequence Number DCCollectorAdSeq::DCCollectorAdSeq( const DCCollectorAdSeq &ref ) { const char *tmp; tmp = ref.getName( ); if ( tmp ) { this->Name = strdup( tmp ); } else { this->Name = NULL; } tmp = ref.getMyType( ); if ( tmp ) { this->MyType = strdup( tmp ); } else { this->MyType = NULL; } tmp = ref.getMachine( ); if ( tmp ) { this->Machine = strdup( tmp ); } else { this->Machine = NULL; } this->sequence = ref.getSequence( ); }
// Get the sequence number unsigned DCCollectorAdSeqMan::getSequence( const ClassAd *ad ) { int adNum; char *name = NULL; char *myType = NULL; char *machine = NULL; DCCollectorAdSeq *adSeq = NULL; // Extract the 'key' attributes of the ClassAd ad->LookupString( ATTR_NAME, &name ); ad->LookupString( ATTR_MY_TYPE, &myType ); ad->LookupString( ATTR_MACHINE, &machine ); // Walk through the ads that we know of, find a match... for ( adNum = 0; adNum < numAds; adNum++ ) { if ( adSeqInfo[adNum]->Match( name, myType, machine ) ) { adSeq = adSeqInfo[adNum]; break; } } // No matches; create a new one, add to the list if ( ! adSeq ) { adSeq = new DCCollectorAdSeq ( name, myType, machine ); adSeqInfo[numAds++] = adSeq; } // Free up memory... if ( name ) { free( name ); name = NULL; } if ( myType ) { free( myType ); myType = NULL; } if ( machine ) { free( machine ); machine = NULL; } // Finally, return the sequence return adSeq->getSequenceAndIncrement( ); }
bool DCCollector::sendUpdate( int cmd, ClassAd* ad1, DCCollectorAdSequences& adSeq, ClassAd* ad2, bool nonblocking ) { if( ! _is_configured ) { // nothing to do, treat it as success... return true; } if(!use_nonblocking_update || !daemonCore) { // Either caller OR config may turn off nonblocking updates. // In other words, both must be true to enable nonblocking. // Also, must have DaemonCore intialized. nonblocking = false; } // Add start time & seq # to the ads before we publish 'em if ( ad1 ) { ad1->Assign(ATTR_DAEMON_START_TIME, startTime); } if ( ad2 ) { ad2->Assign(ATTR_DAEMON_START_TIME, startTime); } if ( ad1 ) { DCCollectorAdSeq* seqgen = adSeq.getAdSeq(*ad1); if (seqgen) { long long seq = seqgen->getSequence(); ad1->Assign(ATTR_UPDATE_SEQUENCE_NUMBER, seq); if (ad2) { ad2->Assign(ATTR_UPDATE_SEQUENCE_NUMBER, seq); } } } // Prior to 7.2.0, the negotiator depended on the startd // supplying matching MyAddress in public and private ads. if ( ad1 && ad2 ) { ad2->CopyAttribute(ATTR_MY_ADDRESS,ad1); } // We never want to try sending an update to port 0. If we're // about to try that, and we're trying to talk to a local // collector, we should try re-reading the address file and // re-setting our port. if( _port == 0 ) { dprintf( D_HOSTNAME, "About to update collector with port 0, " "attempting to re-read address file\n" ); if( readAddressFile(_subsys) ) { _port = string_to_port( _addr ); parseTCPInfo(); // update use_tcp dprintf( D_HOSTNAME, "Using port %d based on address \"%s\"\n", _port, _addr ); } } if( _port <= 0 ) { // If it's still 0, we've got to give up and fail. std::string err_msg; formatstr(err_msg, "Can't send update: invalid collector port (%d)", _port ); newError( CA_COMMUNICATION_ERROR, err_msg.c_str() ); return false; } // // We don't want the collector to send TCP updates to itself, since // this could cause it to deadlock. Since the only ad a collector // will ever advertise is its own, only check for *_COLLECTOR_ADS. // if( cmd == UPDATE_COLLECTOR_AD || cmd == INVALIDATE_COLLECTOR_ADS ) { if( daemonCore ) { const char * myOwnSinful = daemonCore->InfoCommandSinfulString(); if( myOwnSinful == NULL ) { dprintf( D_ALWAYS, "Unable to determine my own address, will not update or invalidate collector ad to avoid potential deadlock.\n" ); return false; } if( _addr == NULL ) { dprintf( D_ALWAYS, "Failing attempt to update or invalidate collector ad because of missing daemon address (probably an unresolved hostname; daemon name is '%s').\n", _name ); return false; } if( strcmp( myOwnSinful, _addr ) == 0 ) { EXCEPT( "Collector attempted to send itself an update.\n" ); } } } if( use_tcp ) { return sendTCPUpdate( cmd, ad1, ad2, nonblocking ); } return sendUDPUpdate( cmd, ad1, ad2, nonblocking ); }