/// <summary> /// Create a subscriptionId that is unique per grainId, grainType, namespace combination. /// </summary> private Guid MakeSubscriptionGuid(GrainType grainType, InternalChannelId channelId) { // next 2 shorts inc guid are from namespace hash var namespaceHash = JenkinsHash.ComputeHash(channelId.GetNamespace()); var namespaceHashByes = BitConverter.GetBytes(namespaceHash); var s1 = BitConverter.ToInt16(namespaceHashByes, 0); var s2 = BitConverter.ToInt16(namespaceHashByes, 2); // Tailing 8 bytes of the guid are from the hash of the channelId Guid and a hash of the provider name. // get channelId guid hash code var channelIdGuidHash = JenkinsHash.ComputeHash(channelId.ChannelId.Key.Span); // get provider name hash code var providerHash = JenkinsHash.ComputeHash(channelId.ProviderName); // build guid tailing 8 bytes from grainIdHash and the hash of the provider name. var tail = new List <byte>(); tail.AddRange(BitConverter.GetBytes(channelIdGuidHash)); tail.AddRange(BitConverter.GetBytes(providerHash)); // make guid. // - First int is grain type // - Two shorts from namespace hash // - 8 byte tail from channelId Guid and provider name hash. var id = new Guid((int)JenkinsHash.ComputeHash(grainType.ToString()), s1, s2, tail.ToArray()); var result = MarkSubscriptionGuid(id, isImplicitSubscription: true); return(result); }
/// <summary> /// Retrieve a map of implicit subscriptionsIds to implicit subscribers, given a channel ID. This method throws an exception if there's no namespace associated with the channel ID. /// </summary> /// <param name="channelId">A channel ID.</param> /// <param name="grainFactory">The grain factory used to get consumer references.</param> /// <returns>A set of references to implicitly subscribed grains. They are expected to support the broadcast channel consumer extension.</returns> /// <exception cref="ArgumentException">The channel ID doesn't have an associated namespace.</exception> /// <exception cref="InvalidOperationException">Internal invariant violation.</exception> internal IDictionary <Guid, IBroadcastChannelConsumerExtension> GetImplicitSubscribers(InternalChannelId channelId, IGrainFactory grainFactory) { if (!IsImplicitSubscribeEligibleNameSpace(channelId.GetNamespace())) { throw new ArgumentException("The channel ID doesn't have an associated namespace.", nameof(channelId)); } var entries = GetOrAddImplicitSubscribers(channelId.GetNamespace()); var result = new Dictionary <Guid, IBroadcastChannelConsumerExtension>(); foreach (var entry in entries) { var consumer = MakeConsumerReference(grainFactory, channelId, entry); var subscriptionGuid = MakeSubscriptionGuid(entry.GrainType, channelId); if (result.ContainsKey(subscriptionGuid)) { throw new InvalidOperationException( $"Internal invariant violation: generated duplicate subscriber reference: {consumer}, subscriptionId: {subscriptionGuid}"); } result.Add(subscriptionGuid, consumer); } return(result); }
/// <summary> /// Determines whether the specified grain is an implicit subscriber of a given channel. /// </summary> /// <param name="grainId">The grain identifier.</param> /// <param name="channelId">The channel identifier.</param> /// <returns>true if the grain id describes an implicit subscriber of the channel described by the channel id.</returns> internal bool IsImplicitSubscriber(GrainId grainId, InternalChannelId channelId) { return(HasImplicitSubscription(channelId.GetNamespace(), grainId.Type)); }