/// <summary> /// Register new object /// </summary> /// <param name="newObject">Object to be registered</param> public void RegisterObject(IIdentifiedObject newObject) { if (keyToIdDictionary.ContainsKey(newObject.Key)) { return; } if (AssignIds) { var id = idManager.GetId(); idToObjectDictionary.Add(id, newObject); keyToIdDictionary.Add(newObject.Key, id); idRegistrationTimestamp.Add(id, DateTime.UtcNow); BroadcastMessage(GetCommandMessage(IdsRegisterCommandType.BindIdAndKey, newObject)); ObjectBoundToId?.Invoke(newObject, id); return; } lock (unboundObjects) unboundObjects.Add(newObject); if (!awaitingKeyIdBinds.TryGetValue(newObject.Key, out var bindId)) { return; } awaitingKeyIdBinds.Remove(newObject.Key); TryBindReceiver(newObject.Key, bindId); }
/// <summary> /// Check if bytes stack contains internal id for the register /// </summary> /// <param name="sender">The peer from which message has been received</param> /// <param name="distributedMessage">Checked message</param> /// <returns>True if bytes stack contains internal id for register, false otherwise</returns> public bool IsInitializationMessage(IPeerManager sender, DistributedMessage distributedMessage) { if (isInternalIdBound || AssignIds) { return(false); } //Check if this is not an initial message var command = (IdsRegisterCommandType)distributedMessage.Content.PeekInt(BytesPerCommandType); if (command != IdsRegisterCommandType.BindIdAndKey) { return(false); } try { var offset = BytesPerCommandType; var key = distributedMessage.Content.PeekString(offset); if (Key == key) { offset += 4 + Encoding.UTF8.GetBytes(key).Length; var id = distributedMessage.Content.PeekInt(BytesPerId, offset); offset += BytesPerId; isInternalIdBound = true; var timeDifference = distributedMessage.Content.PeekLong(8, offset); var calculatedTimestamp = messagesManager.TimeManager.GetTimestamp(timeDifference); InternalIdBindUtcTime = distributedMessage.ServerTimestamp; idRegistrationTimestamp.Add(id, InternalIdBindUtcTime); idToObjectDictionary.Add(id, this); keyToIdDictionary.Add(Key, id); ObjectBoundToId?.Invoke(this, id); return(true); } } catch (IndexOutOfRangeException) { return(false); } return(false); }
/// <summary> /// Bind unbound object with the Key-Id pair /// </summary> /// <param name="key">Key to bind</param> /// <param name="id">Id to bind</param> private void TryBindReceiver(string key, int id) { IIdentifiedObject objectToBind; //Check is there is corresponding identified object with same key lock (unboundObjects) { objectToBind = unboundObjects.Find(r => r.Key == key); if (objectToBind != null) { unboundObjects.Remove(objectToBind); } } //If corresponding identified object is found bind it to the id if (objectToBind != null) { idToObjectDictionary.Add(id, objectToBind); keyToIdDictionary.Add(objectToBind.Key, id); ObjectBoundToId?.Invoke(objectToBind, id); } //If there is no proper unbound identified object add key-id binding to the list else { if (!awaitingKeyIdBinds.TryGetValue(key, out var currentIdForKey)) { awaitingKeyIdBinds.Add(key, id); } else if (currentIdForKey != id) { //Id changed awaitingKeyIdBinds.Remove(key); awaitingKeyIdBinds.Add(key, id); } } }