Esempio n. 1
0
void NetworkTableConnection::read(ConnectionAdapter& adapter) {
	int messageType = ioStream->readByte();
	switch (messageType) {
	case KEEP_ALIVE:
		adapter.keepAlive();
		return;
	case CLIENT_HELLO: {
		uint16_t protocolRevision = ioStream->read2BytesBE();
		adapter.clientHello(protocolRevision);
		return;
	}
	case SERVER_HELLO_COMPLETE: {
		adapter.serverHelloComplete();
		return;
	}
	case PROTOCOL_VERSION_UNSUPPORTED: {
		uint16_t protocolRevision = ioStream->read2BytesBE();
		adapter.protocolVersionUnsupported(protocolRevision);
		return;
	}
	case ENTRY_ASSIGNMENT: {
		std::string* entryName = ioStream->readString();
		TypeId typeId = ioStream->readByte();
		NetworkTableEntryType* entryType = typeManager.GetType(typeId);
		if (!entryType){
			char exceptionMessageBuffer[50];
			sprintf (exceptionMessageBuffer, "Unknown data type: %#x", typeId);
			throw BadMessageException(exceptionMessageBuffer);
		}
		EntryId entryId = ioStream->read2BytesBE();
		SequenceNumber entrySequenceNumber = ioStream->read2BytesBE();
		EntryValue value = entryType->readValue(*ioStream);
		adapter.offerIncomingAssignment(new NetworkTableEntry(entryId, *entryName, entrySequenceNumber, entryType, value));
		entryType->deleteValue(value);
		delete entryName;
		return;
	}
	case FIELD_UPDATE: {
		EntryId entryId = ioStream->read2BytesBE();
		SequenceNumber entrySequenceNumber = ioStream->read2BytesBE();
		NetworkTableEntry* entry = adapter.GetEntry(entryId);
		if (!entry){
			char exceptionMessageBuffer[50];
			sprintf (exceptionMessageBuffer, "Received update for unknown entry id: %d", entryId);
			throw BadMessageException(exceptionMessageBuffer);
		}
		EntryValue value = entry->GetType()->readValue(*ioStream);

		adapter.offerIncomingUpdate(entry, entrySequenceNumber, value);
		entry->GetType()->deleteValue(value);
		return;
	}
	default:
		char exceptionMessageBuffer[50];
		sprintf (exceptionMessageBuffer, "Unknown Network Table Message Type: %d", messageType);
		throw BadMessageException(exceptionMessageBuffer);
	}
}
Esempio n. 2
0
EntryValue NetworkTableNode::GetValue(std::string& name){//TODO don't allow get of complex types
	{ 
		NTSynchronized sync(entryStore.LOCK);
		NetworkTableEntry* entry = entryStore.GetEntry(name);
		if(entry==NULL)
			throw TableKeyNotDefinedException(name);
		return entry->GetValue();
	}
}
Esempio n. 3
0
void NetworkTableConnection::sendEntryUpdate(NetworkTableEntry& entry) {
	{
		Synchronized sync(WRITE_LOCK);
		sendMessageHeader(FIELD_UPDATE);
		ioStream->write2BytesBE(entry.GetId());
		ioStream->write2BytesBE(entry.GetSequenceNumber());
		entry.SendValue(*ioStream);
	}
}
	/**
	 * Called to say that a listener should notify the listener manager of all of the entries
	 * @param listener
	 * @param table 
	 */
	void AbstractNetworkTableEntryStore::notifyEntries(ITable* table, ITableListener* listener){
		{ 
			Synchronized sync(LOCK);
			std::map<std::string, NetworkTableEntry*>::iterator itr;
			for(itr = namedEntries.begin(); itr != namedEntries.end(); itr++)
			{
				NetworkTableEntry* entry = itr->second;
				listener->ValueChanged(table, itr->first, entry->GetValue(), true);
			}
		}
	}
Esempio n. 5
0
void NetworkTableConnection::sendEntryAssignment(NetworkTableEntry& entry) {
	{
		Synchronized sync(WRITE_LOCK);
		sendMessageHeader(ENTRY_ASSIGNMENT);
		ioStream->writeString(entry.name);
		ioStream->writeByte(entry.GetType()->id);
		ioStream->write2BytesBE(entry.GetId());
		ioStream->write2BytesBE(entry.GetSequenceNumber());
		entry.SendValue(*ioStream);
	}
}
Esempio n. 6
0
void NetworkTableNode::retrieveValue(std::string& name, ComplexData& externalData){
	{ 
		NTSynchronized sync(entryStore.LOCK);
		NetworkTableEntry* entry = entryStore.GetEntry(name);
		if(entry==NULL)
			throw TableKeyNotDefinedException(name);
		NetworkTableEntryType* entryType = entry->GetType();
		if(!entryType->isComplex())
			throw TableKeyExistsWithDifferentTypeException(name, entryType, "Is not a complex data type");
		ComplexEntryType* complexType = (ComplexEntryType*)entryType;
		complexType->exportValue(name, entry->GetValue(), externalData);
	}
}
/**
 * Send all unknown entries in the entry store to the given connection
 * @param connection
 * @throws IOException
 */
void ClientNetworkTableEntryStore::sendUnknownEntries(NetworkTableConnection& connection) {
	{ 
		Synchronized sync(LOCK);
		std::map<std::string, NetworkTableEntry*>::iterator itr;
		for(itr = namedEntries.begin(); itr != namedEntries.end(); itr++)
		{
			NetworkTableEntry* entry = (*itr).second;
			if(entry && entry->GetId()==NetworkTableEntry::UNKNOWN_ID)
				connection.sendEntryAssignment(*entry);
		}
		connection.flush();
	}
}
Esempio n. 8
0
void WriteManager::run() {
	{
		Synchronized sync(transactionsLock);
		//swap the assignment and update queue
		volatile std::queue<NetworkTableEntry*>* tmp = incomingAssignmentQueue;
		incomingAssignmentQueue = outgoingAssignmentQueue;
		outgoingAssignmentQueue = tmp;
		
		tmp = incomingUpdateQueue;
		incomingUpdateQueue = outgoingUpdateQueue;
		outgoingUpdateQueue = tmp;
	}
	
	bool wrote = false;
	NetworkTableEntry* entry;
	
	while(!((std::queue<NetworkTableEntry*>*)outgoingAssignmentQueue)->empty()){
		entry = ((std::queue<NetworkTableEntry*>*)outgoingAssignmentQueue)->front();
		((std::queue<NetworkTableEntry*>*)outgoingAssignmentQueue)->pop();
		{
			Synchronized sync(entryStore.LOCK);
			entry->MakeClean();
			wrote = true;
			receiver.offerOutgoingAssignment(entry);
		}
	}
	
	while(!((std::queue<NetworkTableEntry*>*)outgoingUpdateQueue)->empty()){
		entry = ((std::queue<NetworkTableEntry*>*)outgoingUpdateQueue)->front();
		((std::queue<NetworkTableEntry*>*)outgoingUpdateQueue)->pop();
		{ 
			Synchronized sync(entryStore.LOCK);
			entry->MakeClean();
			wrote = true;
			receiver.offerOutgoingUpdate(entry);
		}
	}
	
	
	
	if(wrote){
		receiver.flush();
		lastWrite = currentTimeMillis();
	}
	else if(currentTimeMillis()-lastWrite>keepAliveDelay)
		receiver.ensureAlive();
	
	sleep_ms(20);
}
	/**
	 * Stores the given value under the given name and queues it for 
	 * transmission to the server.
	 * 
	 * @param name The name under which to store the given value.
	 * @param type The type of the given value.
	 * @param value The value to store.
	 * @throws TableKeyExistsWithDifferentTypeException Thrown if an 
	 *  entry already exists with the given name and is of a different type.
	 */
	void AbstractNetworkTableEntryStore::PutOutgoing(std::string& name, NetworkTableEntryType* type, EntryValue value){
		{ 
			NTSynchronized sync(LOCK);
			std::map<std::string, NetworkTableEntry*>::iterator index = namedEntries.find(name);
			NetworkTableEntry* tableEntry;
			if(index == namedEntries.end())//if the name does not exist in the current entries
			  {
				tableEntry = new NetworkTableEntry(name, type, value);
				if(addEntry(tableEntry))
				{
					tableEntry->FireListener(listenerManager);
					outgoingReceiver->offerOutgoingAssignment(tableEntry);
				}
			}
			else
			{
				tableEntry = index->second;
				if(tableEntry->GetType()->id != type->id){
					throw TableKeyExistsWithDifferentTypeException(name, tableEntry->GetType());
				}
				
				EntryValue oldValue = tableEntry->GetValue();
				if(!type->areEqual(value, oldValue)){
				  if(updateEntry(tableEntry, (SequenceNumber)(tableEntry->GetSequenceNumber() + 1), value)){
				    outgoingReceiver->offerOutgoingUpdate(tableEntry);
				  }
				
				  tableEntry->FireListener(listenerManager);
				}
			}
		}
	}
	void AbstractNetworkTableEntryStore::offerIncomingAssignment(NetworkTableEntry* entry){
		{ 
			NTSynchronized sync(LOCK);
			std::map<std::string, NetworkTableEntry*>::iterator itr = namedEntries.find(entry->name);
			NetworkTableEntry* tableEntry;
			if(addEntry(entry)){
				if(itr != namedEntries.end()){
					tableEntry = itr->second;
				}
				else{
					tableEntry = entry;
				}
				
				tableEntry->FireListener(listenerManager);//if we didnt have a pointer, then the copy of the version in the list would call this method, however with the pointer we are updating the version in the list
				incomingReceiver->offerOutgoingAssignment(tableEntry);
			}
			else
			  delete entry;
		}
	}
bool ClientNetworkTableEntryStore::addEntry(NetworkTableEntry* newEntry){
	{
		Synchronized sync(LOCK);
		NetworkTableEntry* entry = (NetworkTableEntry*)namedEntries[newEntry->name];

		if(entry!=NULL){
			if(entry->GetId()!=newEntry->GetId()){
				idEntries.erase(entry->GetId());
				if(newEntry->GetId()!=NetworkTableEntry::UNKNOWN_ID){
					entry->SetId(newEntry->GetId());
					idEntries[newEntry->GetId()] = entry;
				}
			}
			
			entry->ForcePut(newEntry->GetSequenceNumber(), newEntry->GetType(), newEntry->GetValue());
		}
		else{
			if(newEntry->GetId()!=NetworkTableEntry::UNKNOWN_ID)
				idEntries[newEntry->GetId()] = newEntry;
			namedEntries[newEntry->name] = newEntry;
		}
	}
	return true;
}
Esempio n. 12
0
void NetworkTableNode::PutValue(std::string& name, NetworkTableEntryType* type, EntryValue value){
	if(type->isComplex()){
		{ 
			NTSynchronized sync(entryStore.LOCK);
			ComplexData* complexData = (ComplexData*)value.ptr;
			ComplexEntryType* entryType = (ComplexEntryType*)type;
			NetworkTableEntry* entry = entryStore.GetEntry(name);
			if(entry!=NULL)
				entryStore.PutOutgoing(entry, entryType->internalizeValue(entry->name, *complexData, entry->GetValue()));
			else{
				EntryValue nullValue = {0};
				EntryValue entryValue = entryType->internalizeValue(name, *complexData, nullValue);
				entryStore.PutOutgoing(name, type, entryValue);//TODO the entry gets copied when creating the entry should make lifecycle cleaner
				type->deleteValue(entryValue);
			}
		}
	}
	else
		entryStore.PutOutgoing(name, type, value);
}
Esempio n. 13
0
std::string& NetworkTableNode::GetString(std::string& name) {
	NetworkTableEntry* entry = entryStore.GetEntry(name);
	if(entry==NULL)
		throw TableKeyNotDefinedException(name);
	return *(std::string*)(entry->GetValue().ptr);
}
Esempio n. 14
0
double NetworkTableNode::GetDouble(std::string& name){
	NetworkTableEntry* entry = entryStore.GetEntry(name);
	if(entry==NULL)
		throw TableKeyNotDefinedException(name);
	return entry->GetValue().f;
}