예제 #1
0
        /// <summary>
        /// For Inproc only
        /// </summary>
        /// <param name="entry"></param>
        /// <returns></returns>
        internal static EventCacheItem ConvertToItem(EventCacheEntry entry)
        {
            Byte[] objectValue = null;
            if (entry != null)
            {
                EventCacheItem item = new EventCacheItem();
                item.CacheItemPriority = (CacheItemPriority)entry.Priority;
                if (entry.Value != null)
                {
                    UserBinaryObject ubObject = entry.Value as UserBinaryObject;
                    if (ubObject != null)
                    {
                        objectValue = ubObject.GetFullObject();
                        item.Value  = objectValue;
                    }
                    else
                    {
                        item.Value = entry.Value;
                    }
                }


                return(item);
            }

            return(null);
        }
예제 #2
0
        /// <summary>
        /// For Inproc only
        /// </summary>
        /// <param name="entry"></param>
        /// <returns></returns>
        internal static EventCacheItem ConvertToItem(EventCacheEntry entry)
        {
            Byte[] objectValue = null;
            if (entry != null)
            {
                EventCacheItem item = new EventCacheItem();
                item.CacheItemPriority  = (CacheItemPriority)entry.Priority;
                item.CacheItemVersion   = new Caching.CacheItemVersion(entry.Version);
                item.Group              = entry.Group;
                item.ResyncExpiredItems = entry.ReSyncExpiredItems;
                item.ResyncProviderName = entry.ReSyncProviderCacheItem;
                item.SubGroup           = entry.SubGroup;
                if (entry.Value != null)
                {
                    UserBinaryObject ubObject = entry.Value as UserBinaryObject;
                    if (ubObject != null)
                    {
                        objectValue = ubObject.GetFullObject();
                        item.Value  = objectValue;
                    }
                    else
                    {
                        item.Value = entry.Value;
                    }
                }


                return(item);
            }

            return(null);
        }
예제 #3
0
            internal static void RemoveAllEventHandlers(Action <EventRegistrationToken> removeMethod)
            {
                object instanceKey = GetInstanceKey(removeMethod);

                System.Collections.Generic.Internal.List <EventRegistrationToken> tokensToRemove = new System.Collections.Generic.Internal.List <EventRegistrationToken>();

                //
                // The whole add/remove code has to be protected by a reader/writer lock
                // Add/Remove cannot run at the same time with cache cleanup but Add/Remove can run at the same time
                //
                s_eventCacheRWLock.EnterReadLock();
                try
                {
                    EventCacheEntry registrationTokens = GetEventRegistrationTokenTableNoCreate(instanceKey, removeMethod);
                    if (registrationTokens == null)
                    {
                        // We have no information regarding this particular instance (IUnknown*/type) - just return
                        // This is necessary to avoid leaking empty dictionary/conditionalWeakTables for this instance
                        return;
                    }

                    try
                    {
                        registrationTokens.LockAcquire();

                        // Copy all tokens to tokensToRemove array which later we'll call removeMethod on
                        // outside this lock
                        foreach (KeyValuePair <object, EventRegistrationTokenListWithCount> item in registrationTokens.registrationTable)
                        {
                            item.Value.CopyTo(tokensToRemove);
                        }

                        // Clear the table - at this point all event handlers are no longer in the cache
                        // but they are not removed yet
                        registrationTokens.registrationTable.Clear();
#if false
                        BCLDebug.Log("INTEROP", "[WinRT_Eventing] Cache cleared for managed instance = " + instanceKey + "\n");
#endif
                    }
                    finally
                    {
                        registrationTokens.LockRelease();
                    }
                }
                finally
                {
                    s_eventCacheRWLock.ExitReadLock();
                }

                //
                // Remove all handlers outside the lock
                //
#if false
                BCLDebug.Log("INTEROP", "[WinRT_Eventing] Start removing all events for instance = " + instanceKey + "\n");
#endif
                CallRemoveMethods(removeMethod, tokensToRemove);
#if false
                BCLDebug.Log("INTEROP", "[WinRT_Eventing] Finished removing all events for instance = " + instanceKey + "\n");
#endif
            }
예제 #4
0
        /// <summary>
        /// For Inproc only
        /// </summary>
        /// <param name="entry"></param>
        /// <returns></returns>
        internal static EventCacheItem ConvertToItem(EventCacheEntry entry)
        {
            Byte[] objectValue = null;
            if (entry != null)
            {
                EventCacheItem item = new EventCacheItem();
                item.CacheItemPriority = (CacheItemPriority)entry.Priority;
                item.CacheItemVersion  = new CacheItemVersion(entry.Version);
                item.Group             = entry.Group;
                item.SubGroup          = entry.SubGroup;

                if (entry.Value != null)
                {
                    UserBinaryObject ubObject = entry.Value as UserBinaryObject;
                    if (ubObject != null)
                    {
                        objectValue = ubObject.GetFullObject();
                        item.SetValue(objectValue);
                    }
                    else
                    {
                        item.SetValue(entry.Value);
                    }
                }
                item.EntryType = entry.EntryType;

                return(item);
            }

            return(null);
        }
예제 #5
0
        public static EventCacheEntry CreateCacheEventEntry(ArrayList listeners, CacheEntry cacheEntry, CacheRuntimeContext context)
        {
            EventCacheEntry entry     = null;
            EventDataFilter maxFilter = EventDataFilter.None;


            return(CreateCacheEventEntry(maxFilter, cacheEntry, context));
        }
예제 #6
0
        public override void Deserialize(CompactReader reader)
        {
            base.Deserialize(reader);

            lock (this)
            {
                Item    = EventCacheEntry.ReadItemInfo(reader);
                OldItem = EventCacheEntry.ReadItemInfo(reader);
            }
        }
예제 #7
0
        public override void Serialize(CompactWriter writer)
        {
            base.Serialize(writer);

            lock (this)
            {
                EventCacheEntry.WriteItemInfo(writer, Item);
                EventCacheEntry.WriteItemInfo(writer, OldItem);
            }
        }
예제 #8
0
        private static UserBinaryObject getData(EventCacheEntry entry)
        {
            object userValue = entry.Value;

            if (userValue is UserBinaryObject)
            {
                userValue = ((UserBinaryObject)userValue).GetFullObject();
            }
            BitSet flag = entry.Flags;

            object ubObj = _eventDataFormat.GetClientData(userValue, ref flag, LanguageContext.DOTNET);

            return(ubObj is UserBinaryObject ? (UserBinaryObject)ubObj : (UserBinaryObject)entry.Value);
        }
예제 #9
0
            // Get the event registration token table for an event.  These are indexed by the remove method of the event.
            private static EventCacheEntry GetEventRegistrationTokenTableInternal(object instance, Action <EventRegistrationToken> removeMethod, bool createIfNotFound)
            {
                Debug.Assert(instance != null);
                Debug.Assert(removeMethod != null);
                Debug.Assert(s_eventRegistrations != null);

                EventCacheKey eventCacheKey;

                eventCacheKey.target = instance;
#if false
                eventCacheKey.method = removeMethod.Method;
#endif
                RuntimeTypeHandle thDummy;
                eventCacheKey.method = removeMethod.GetFunctionPointer(out thDummy);

                try
                {
                    s_eventRegistrationsLock.Acquire();

                    EventCacheEntry eventCacheEntry;

                    if (!s_eventRegistrations.TryGetValue(eventCacheKey, out eventCacheEntry))
                    {
                        if (!createIfNotFound)
                        {
                            // No need to create an entry in this case
                            return(null);
                        }
#if false
                        BCLDebug.Log("INTEROP", "[WinRT_Eventing] Adding (" + instance + "," + removeMethod.Method + ") into cache" + "\n");
#endif
                        eventCacheEntry = new EventCacheEntry();
                        eventCacheEntry.registrationTable = new ConditionalWeakTable <object, EventRegistrationTokenListWithCount>();
                        eventCacheEntry.tokenListCount    = new TokenListCount(eventCacheKey);
                        eventCacheEntry._lock             = new Lock();

                        s_eventRegistrations.Add(eventCacheKey, eventCacheEntry);
                    }

                    return(eventCacheEntry);
                }
                finally
                {
                    s_eventRegistrationsLock.Release();
                }
            }
예제 #10
0
        public static EventCacheEntry CreateCacheEventEntry(ArrayList listeners, CacheEntry cacheEntry)
        {
            EventCacheEntry entry     = null;
            EventDataFilter maxFilter = EventDataFilter.None;

            foreach (CallbackInfo cbInfo in listeners)
            {
                if (cbInfo.DataFilter > maxFilter)
                {
                    maxFilter = cbInfo.DataFilter;
                }
                if (maxFilter == EventDataFilter.DataWithMetadata)
                {
                    break;
                }
            }

            return(CreateCacheEventEntry(maxFilter, cacheEntry));
        }
예제 #11
0
        internal static EventCacheItem ConvertToEventItem(EventCacheEntry entry, EventDataFilter?datafilter)
        {
            if (datafilter == EventDataFilter.None || entry == null)
            {
                return(null);
            }

            EventCacheItem cacheItem = new EventCacheItem();

            cacheItem.priority = (int)entry.Priority;

            UserBinaryObject userBinary = entry.Value as UserBinaryObject;

            if (userBinary == null)
            {
                if (entry.Value is CallbackEntry)
                {
                    userBinary = ((CallbackEntry)entry.Value).Value as UserBinaryObject;
                }
            }

            if (userBinary != null)
            {
                cacheItem.value.AddRange(userBinary.DataList);
            }

            //Can be optimized
            if (datafilter != null)
            {
                if (datafilter == EventDataFilter.None)
                {
                    return(null);
                }
                else if (datafilter == EventDataFilter.Metadata)
                {
                    cacheItem.value.Clear();
                }
            }

            return(cacheItem);
        }
예제 #12
0
        internal static EventCacheItem ConvertToEventItem(EventCacheEntry entry, EventDataFilter?datafilter)
        {
            if (datafilter == EventDataFilter.None || entry == null)
            {
                return(null);
            }

            EventCacheItem cacheItem = new EventCacheItem();

            cacheItem.group    = entry.Group;
            cacheItem.subGroup = entry.SubGroup;

            cacheItem.itemVersion        = entry.Version;
            cacheItem.priority           = (int)entry.Priority;
            cacheItem.resyncExpiredItems = entry.ReSyncExpiredItems;
            cacheItem.resyncProviderName = entry.ReSyncProviderCacheItem;

            UserBinaryObject userBinary = getData(entry);

            if (userBinary != null)
            {
                cacheItem.value.AddRange(userBinary.DataList);
            }

            // Can be optimized
            if (datafilter != null)
            {
                if (datafilter == EventDataFilter.None)
                {
                    return(null);
                }
                else if (datafilter == EventDataFilter.Metadata)
                {
                    cacheItem.value.Clear();
                }
            }
            return(cacheItem);
        }
예제 #13
0
        public static EventCacheEntry CreateCacheEventEntry(EventDataFilter?filter, CacheEntry cacheEntry)
        {
            if (filter != EventDataFilter.None && cacheEntry != null)
            {
                cacheEntry = (CacheEntry)cacheEntry.Clone();
                EventCacheEntry entry = new EventCacheEntry(cacheEntry);
                entry.Flags = cacheEntry.Flag;

                if (filter == EventDataFilter.DataWithMetadata)
                {
                    if (cacheEntry.Value is CallbackEntry)
                    {
                        entry.Value = ((CallbackEntry)cacheEntry.Value).Value;
                    }
                    else
                    {
                        entry.Value = cacheEntry.Value;
                    }
                }
                return(entry);
            }
            return(null);
        }
예제 #14
0
        internal static EventCacheItem ConvertToEventItem(EventCacheEntry entry, EventDataFilter?datafilter)
        {
            if (datafilter == EventDataFilter.None || entry == null)
            {
                return(null);
            }

            EventCacheItem cacheItem = new EventCacheItem();

            cacheItem.group    = entry.Group;
            cacheItem.subGroup = entry.SubGroup;

            cacheItem.itemVersion        = entry.Version;
            cacheItem.priority           = (int)entry.Priority;
            cacheItem.resyncExpiredItems = entry.ReSyncExpiredItems;
            cacheItem.resyncProviderName = entry.ReSyncProviderCacheItem;

            UserBinaryObject userBinary = getData(entry);

            if (userBinary != null)
            {
                cacheItem.value.AddRange(userBinary.DataList);
            }

            cacheItem.itemType = Alachisoft.NCache.Util.MiscUtil.EntryTypeToProtoItemType(entry.EntryType);
            cacheItem.flagMap  = entry.Flags.Data;
            //Can be optimized
            if (datafilter != null)
            {
                if (datafilter == EventDataFilter.None)
                {
                    return(null);
                }
            }

            return(cacheItem);
        }
예제 #15
0
            internal static void AddEventHandler <T>(Func <T, EventRegistrationToken> addMethod,
                                                     Action <EventRegistrationToken> removeMethod,
                                                     T handler)
            {
                // The instanceKey will be IUnknown * of the target object
                object instanceKey = GetInstanceKey(removeMethod);

                // Call addMethod outside of RW lock
                // At this point we don't need to worry about race conditions and we can avoid deadlocks
                // if addMethod waits on finalizer thread
                // If we later throw we need to remove the method
                EventRegistrationToken token = addMethod(handler);

                bool tokenAdded = false;

                try
                {
                    EventRegistrationTokenListWithCount tokens;

                    //
                    // The whole add/remove code has to be protected by a reader/writer lock
                    // Add/Remove cannot run at the same time with cache cleanup but Add/Remove can run at the same time
                    //
                    s_eventCacheRWLock.EnterReadLock();
                    try
                    {
                        // Add the method, and make a note of the delegate -> token mapping.
                        EventCacheEntry registrationTokens = GetOrCreateEventRegistrationTokenTable(instanceKey, removeMethod);

                        try
                        {
                            registrationTokens.LockAcquire();

                            //
                            // We need to find the key that equals to this handler
                            // Suppose we have 3 handlers A, B, C that are equal (refer to the same object and method),
                            // the first handler (let's say A) will be used as the key and holds all the tokens.
                            // We don't need to hold onto B and C, because the COM object itself will keep them alive,
                            // and they won't die anyway unless the COM object dies or they get unsubscribed.
                            // It may appear that it is fine to hold A, B, C, and add them and their corresponding tokens
                            // into registrationTokens table. However, this is very dangerous, because this COM object
                            // may die, but A, B, C might not get collected yet, and another COM object comes into life
                            // with the same IUnknown address, and we subscribe event B. In this case, the right token
                            // will be added into B's token list, but once we unsubscribe B, we might end up removing
                            // the last token in C, and that may lead to crash.
                            //
                            object key = FindEquivalentKeyUnsafe(registrationTokens.registrationTable, handler, out tokens);

                            if (key == null)
                            {
                                tokens = new EventRegistrationTokenListWithCount(registrationTokens.tokenListCount, token);
                                registrationTokens.registrationTable.Add(handler, tokens);
                            }
                            else
                            {
                                tokens.Push(token);
                            }

                            tokenAdded = true;
                        }
                        finally
                        {
                            registrationTokens.LockRelease();
                        }
                    }
                    finally
                    {
                        s_eventCacheRWLock.ExitReadLock();
                    }
#if false
                    BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event subscribed for instance = " + instanceKey + ", handler = " + handler + "\n");
#endif
                }
                catch (Exception)
                {
                    // If we've already added the token and go there, we don't need to "UNDO" anything
                    if (!tokenAdded)
                    {
                        // Otherwise, "Undo" addMethod if any exception occurs
                        // There is no need to cleanup our data structure as we haven't added the token yet
                        removeMethod(token);
                    }


                    throw;
                }
            }
예제 #16
0
            internal static void RemoveEventHandler <T>(Action <EventRegistrationToken> removeMethod, T handler)
            {
                object instanceKey = GetInstanceKey(removeMethod);

                EventRegistrationToken token;

                //
                // The whole add/remove code has to be protected by a reader/writer lock
                // Add/Remove cannot run at the same time with cache cleanup but Add/Remove can run at the same time
                //
                s_eventCacheRWLock.EnterReadLock();
                try
                {
                    EventCacheEntry registrationTokens = GetEventRegistrationTokenTableNoCreate(instanceKey, removeMethod);
                    if (registrationTokens == null)
                    {
                        // We have no information regarding this particular instance (IUnknown*/type) - just return
                        // This is necessary to avoid leaking empty dictionary/conditionalWeakTables for this instance
#if false
                        BCLDebug.Log("INTEROP", "[WinRT_Eventing] no registrationTokens found for instance=" + instanceKey + ", handler= " + handler + "\n");
#endif
                        return;
                    }

                    try
                    {
                        registrationTokens.LockAcquire();

                        EventRegistrationTokenListWithCount tokens;

                        // Note:
                        // When unsubscribing events, we allow subscribing the event using a different delegate
                        // (but with the same object/method), so we need to find the first delegate that matches
                        // and unsubscribe it
                        // It actually doesn't matter which delegate - as long as it matches
                        // Note that inside TryGetValueWithValueEquality we assumes that any delegate
                        // with the same value equality would have the same hash code
                        object key = FindEquivalentKeyUnsafe(registrationTokens.registrationTable, handler, out tokens);

                        Debug.Assert((key != null && tokens != null) || (key == null && tokens == null),
                                     "key and tokens must be both null or non-null");
                        if (tokens == null)
                        {
                            // Failure to find a registration for a token is not an error - it's simply a no-op.
#if false
                            BCLDebug.Log("INTEROP", "[WinRT_Eventing] no token list found for instance=" + instanceKey + ", handler= " + handler + "\n");
#endif
                            return;
                        }

                        // Select a registration token to unregister
                        // Note that we need to always get the last token just in case another COM object
                        // is created at the same address before the entry for the old one goes away.
                        // See comments above s_eventRegistrations for more details
                        bool moreItems = tokens.Pop(out token);

                        // If the last token is removed from token list, we need to remove it from the cache
                        // otherwise FindEquivalentKeyUnsafe may found this empty token list even though there could be other
                        // equivalent keys in there with non-0 token list
                        if (!moreItems)
                        {
                            // Remove it from (handler)->(tokens)
                            // NOTE: We should not check whether registrationTokens has 0 entries and remove it from the cache
                            // (just like managed event implementation), because this might race with the finalizer of
                            // EventRegistrationTokenList
                            registrationTokens.registrationTable.Remove(key);
                        }
#if false
                        BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event unsubscribed for managed instance = " + instanceKey + ", handler = " + handler + ", token = " + token.m_value + "\n");
#endif
                    }
                    finally
                    {
                        registrationTokens.LockRelease();
                    }
                }
                finally
                {
                    s_eventCacheRWLock.ExitReadLock();
                }
                // Call removeMethod outside of RW lock
                // At this point we don't need to worry about race conditions and we can avoid deadlocks
                // if removeMethod waits on finalizer thread
                removeMethod(token);
            }
예제 #17
0
        public override object RemoveSync(object[] keys, ItemRemoveReason reason, bool notify, OperationContext operationContext)
        {
            ArrayList depenedentItemList = new ArrayList();

            try
            {
                Hashtable totalRemovedItems = new Hashtable();

                CacheEntry            entry = null;
                IDictionaryEnumerator ide   = null;


                for (int i = 0; i < keys.Length; i++)
                {
                    try
                    {
                        if (keys[i] != null)
                        {
                            entry = Internal.Remove(keys[i], reason, false, null, LockAccessType.IGNORE_LOCK, operationContext);
                        }


                        if (entry != null)
                        {
                            totalRemovedItems.Add(keys[i], entry);
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                }
                ide = totalRemovedItems.GetEnumerator();
                while (ide.MoveNext())
                {
                    try
                    {
                        entry = ide.Value as CacheEntry;
                        if (entry != null)
                        {
                            if (entry.Value is CallbackEntry)
                            {
                                EventId       eventId      = null;
                                OperationID   opId         = operationContext.OperatoinID;
                                CallbackEntry cbEtnry      = (CallbackEntry)entry.Value;
                                EventContext  eventContext = null;

                                if (cbEtnry != null && cbEtnry.ItemRemoveCallbackListener != null && cbEtnry.ItemRemoveCallbackListener.Count > 0)
                                {
                                    //generate event id
                                    if (!operationContext.Contains(OperationContextFieldName.EventContext)) //for atomic operations
                                    {
                                        eventId = EventId.CreateEventId(opId);
                                    }
                                    else //for bulk
                                    {
                                        eventId = ((EventContext)operationContext.GetValueByField(OperationContextFieldName.EventContext)).EventID;
                                    }

                                    eventId.EventType = EventType.ITEM_REMOVED_CALLBACK;
                                    eventContext      = new EventContext();
                                    eventContext.Add(EventContextFieldName.EventID, eventId);
                                    EventCacheEntry eventCacheEntry = CacheHelper.CreateCacheEventEntry(cbEtnry.ItemRemoveCallbackListener, entry);
                                    eventContext.Item = eventCacheEntry;
                                    eventContext.Add(EventContextFieldName.ItemRemoveCallbackList, cbEtnry.ItemRemoveCallbackListener.Clone());

                                    //Will always reaise the whole entry for old clients
                                    NotifyCustomRemoveCallback(ide.Key, entry, reason, true, operationContext, eventContext);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }

            return(depenedentItemList);
        }