protected override void OnInit() { base.OnInit(); namedCache = CacheFactory.GetCache("SossSessionState"); createPolicy = new CreatePolicy(TimeSpan.FromMinutes(Timeout)); }
/// <summary> /// Run shopping cart analysis on ScaleOut's distributed data grid, /// only considering carts whose value is at least $20. /// </summary> /// <param name="collection">Collection of shopping carts.</param> /// <remarks> /// Filtering for with a LINQ .Where() call is performed in the ScaleOut service /// when an object's property is marked with a [SossIndex] attribute /// (like ShoppingCart.TotalValue, in this case). You can reduce deserialization /// overhead during ForEach analysis by filtering as much as possible in the /// storage engine. /// </remarks> static void RunDistributedAnalysisMin20(NamedCache cartCache) { string productName = "Acme Snow Globe"; // product to find in the carts Result finalResult; // result of the computation finalResult = cartCache.QueryObjects <ShoppingCart>() .Where(cart => cart.TotalValue >= 20.00m) // filter out low-value carts in the server. .ForEach( productName, // parameter () => new Result(), // result-initialization delegate (cart, pName, result) => // body of analysis logic { // see if the selected product is in the cart: if (cart.Items.Any(item => item.Name.Equals(pName))) { result.numMatches++; } result.numCarts++; return(result); }, (result1, result2) => // merge logic { result1.numMatches += result2.numMatches; result1.numCarts += result2.numCarts; return(result1); }); float resultPct = (float)finalResult.numMatches / finalResult.numCarts * 100; Console.WriteLine($"{resultPct:N1} percent of $20+ carts contain {productName}"); }
/// <summary> /// Run shopping cart analysis on ScaleOut's distributed data grid /// using Invoke() and Merge() extension methods. /// </summary> /// <param name="collection">Collection of shopping carts.</param> /// <remarks> /// Using the .Invoke() and .Merge() extension methods on a NamedCache /// can give you the same result as .ForEach(), but with higher /// GC overhead (more temporary Result objects are created). /// </remarks> static void RunDistributedAnalysisViaPMI(NamedCache cartCache) { string productName = "Acme Snow Globe"; // product to find in the carts Result finalResult; // result of the computation finalResult = cartCache.QueryObjects <ShoppingCart>() .Invoke( timeout: TimeSpan.FromMinutes(1), param: productName, evalMethod: (cart, pName) => { var result = new Result(); result.numCarts = 1; // see if the selected product is in the cart: if (cart.Items.Any(item => item.Name.Equals(pName))) { result.numMatches++; } return(result); }) .Merge( (result1, result2) => { result1.numMatches += result2.numMatches; result1.numCarts += result2.numCarts; return(result1); }); float resultPct = (float)finalResult.numMatches / finalResult.numCarts * 100; Console.WriteLine($"{resultPct:N1} percent of carts contain {productName}"); }
/// <summary> /// Executes when a Start command is sent to the service by the Service Control Manager. /// </summary> /// <param name="args">Data passed by the start command.</param> protected override void OnStart(string[] args) { try { // Reading service configuration settings from its configuration file Configuration.ReadConfigParams(); /// /// Configure this service to receive backing store events /// NamedCache cache = CacheFactory.GetCache(Configuration.CACHE_NAME); BackingStorePolicy policy = new BackingStorePolicy(); // We want to receive asynchronous write-behind events from StateServer: policy.EnableAsyncOperations = true; // Our customized IBackingStore implementation that knows how to write a cached // object to the database: BackingStoreAdapter adapter = new BackingStoreAdapter(); // Register to handle backing store events: cache.SetBackingStoreAdapter(adapter, policy); Logger.WriteMessage(TraceEventType.Information, 1, $"[OnStart] Backing store adapter was successfully registered for handling events in named cache '{Configuration.CACHE_NAME}'"); } catch (Exception ex) { Logger.WriteError(2, ex); throw; } }
static void Main(string[] args) { var carts = new CartGenerator(CART_COUNT).ToList(); NamedCache cartCache = StoreLoader.Load(carts); RunParallelAnalysis(carts); RunDistributedAnalysis(cartCache); RunDistributedAnalysisMin20(cartCache); RunDistributedAnalysisViaPMI(cartCache); }
/// <summary> /// Initialize the service. /// </summary> /// <param name="args">Data passed by the SCM's start command.</param> protected override void OnStart(string[] args) { try { _nc = CacheFactory.GetCache(_cacheName); _nc.ObjectExpired += HandleObjectExpired; _traceSource.TraceEvent(TraceEventType.Verbose, 1, $"Registered for event handling for named cache '{_cacheName}'"); } catch (Exception ex) { _traceSource.TraceData(TraceEventType.Error, 2, ex); throw; } }
public SossSessionStateItemCollection(string keyPrefix, int timeout) { this.keyPrefix = keyPrefix + "_"; countIndex = keyPrefix + ".Count"; versionIndex = keyPrefix + ".Version"; createPolicy = new CreatePolicy(TimeSpan.FromMinutes(timeout)); infinitePolicy = new CreatePolicy(TimeSpan.Zero); namedCache = CacheFactory.GetCache("SossSessionState"); keyPrefixIndexValue = new IndexValue(this.keyPrefix); keyPrefixInternalIndexValue = new IndexValue(keyPrefix + "."); SyncRoot = new object(); IsSynchronized = true; }
/// <summary> /// Copies the elements of the <b>ICollection</b> to an array, /// starting at a particular array index. /// </summary> /// <param name="array"> /// The one-dimensional array that is the destination of the elements /// copied from <b>ICollection</b>. /// </param> /// <param name="index"> /// The zero-based index in array at which copying begins. /// </param> public virtual void CopyTo(Array array, int index) { NamedCache.CopyTo(array, index); }
/// <summary> /// Remove a cache listener that previously signed up for events /// based on a filter evaluation. /// </summary> /// <param name="listener"> /// The <see cref="ICacheListener"/> to remove. /// </param> /// <param name="filter"> /// A filter used to evaluate events; <c>null</c> is equivalent to a /// filter that alway returns <b>true</b>. /// </param> public virtual void RemoveCacheListener(ICacheListener listener, IFilter filter) { NamedCache.RemoveCacheListener(listener, filter); }
/// <summary> /// Invoke the passed <see cref="IEntryProcessor"/> against the /// entries specified by the passed keys, returning the result of the /// invocation for each. /// </summary> /// <param name="keys"> /// The keys to process; these keys are not required to exist within /// the cache. /// </param> /// <param name="agent"> /// The <b>IEntryProcessor</b> to use to process the specified keys. /// </param> /// <returns> /// A dictionary containing the results of invoking the /// <b>IEntryProcessor</b> against each of the specified keys. /// </returns> public virtual IDictionary InvokeAll(ICollection keys, IEntryProcessor agent) { return(NamedCache.InvokeAll(keys, agent)); }
private NamedCache GetOrCreateCache(string cacheName) { // 优化实现: 使用读写锁,减少高并发读取阻塞 NamedCache cache = this.GetCache(cacheName); if (cache == null) { this.lock4Caches.EnterWriteLock(); try { if (this.nameCaches.ContainsKey(cacheName)) { cache = this.nameCaches[cacheName]; } else { CacheSetting setting = GetCacheSetting(cacheName); cache = new NamedCache(cacheName, setting == null ? null : setting.DependencyFile); this.nameCaches.Add(cacheName, cache); } } finally { this.lock4Caches.ExitWriteLock(); } } return cache; }
/// <summary> /// Return a collection of the entries contained in this cache /// that satisfy the criteria expressed by the filter. /// </summary> /// <remarks> /// <p> /// It is guaranteed that enumerator will traverse the array in such /// a way that the entry values come up in ascending order, sorted by /// the specified comparer or according to the /// <i>natural ordering</i>.</p> /// </remarks> /// <param name="filter"> /// The <see cref="IFilter"/> object representing the criteria that /// the entries of this cache should satisfy. /// </param> /// <param name="comparer"> /// The <b>IComparable</b> object which imposes an ordering on /// entries in the resulting collection; or <c>null</c> if the /// entries' values natural ordering should be used. /// </param> /// <returns> /// A collection of entries that satisfy the specified criteria. /// </returns> public virtual ICacheEntry[] GetEntries(IFilter filter, IComparer comparer) { return(NamedCache.GetEntries(filter, comparer)); }
/// <summary> /// Remove an index from this IQueryCache. /// </summary> /// <param name="extractor"> /// The <see cref="IValueExtractor"/> object that is used to extract /// an indexable object from a value stored in the cache. /// </param> public virtual void RemoveIndex(IValueExtractor extractor) { NamedCache.RemoveIndex(extractor); }
/// <summary> /// Returns an enumerator that iterates through cache items. /// </summary> /// <returns> /// An <b>IEnumerator</b> object that can be used to iterate through /// cache items. /// </returns> public virtual ICacheEnumerator GetEnumerator() { return(NamedCache.GetEnumerator()); }
/// <summary> /// Return a collection of the keys contained in this cache for /// entries that satisfy the criteria expressed by the filter. /// </summary> /// <param name="filter"> /// The <see cref="IFilter"/> object representing the criteria that /// the entries of this cache should satisfy. /// </param> /// <returns> /// A collection of keys for entries that satisfy the specified /// criteria. /// </returns> public virtual object[] GetKeys(IFilter filter) { return(NamedCache.GetKeys(filter)); }
/// <summary> /// Associates the specified value with the specified key in this /// cache. /// </summary> /// <remarks> /// <p> /// If the cache previously contained a mapping for this key, the old /// value is replaced.</p> /// This variation of the <see cref="Insert(object, object)"/> /// method allows the caller to specify an expiry (or "time to live") /// for the cache entry. /// </remarks> /// <param name="key"> /// Key with which the specified value is to be associated. /// </param> /// <param name="value"> /// Value to be associated with the specified key. /// </param> /// <param name="millis"> /// The number of milliseconds until the cache entry will expire, /// also referred to as the entry's "time to live"; pass /// <see cref="CacheExpiration.DEFAULT"/> to use the cache's /// default time-to-live setting; pass /// <see cref="CacheExpiration.NEVER"/> to indicate that the /// cache entry should never expire; this milliseconds value is /// <b>not</b> a date/time value, but the amount of time object will /// be kept in the cache. /// </param> /// <returns> /// Previous value associated with specified key, or <c>null</c> if /// there was no mapping for key. A <c>null</c> return can also /// indicate that the cache previously associated <c>null</c> with /// the specified key, if the implementation supports <c>null</c> /// values. /// </returns> /// <exception cref="NotSupportedException"> /// If the requested expiry is a positive value and the /// implementation does not support expiry of cache entries. /// </exception> public virtual object Insert(object key, object value, long millis) { return(NamedCache.Insert(key, value, millis)); }
/// <summary> /// Copies all of the mappings from the specified dictionary to this /// cache (optional operation). /// </summary> /// <remarks> /// These mappings will replace any mappings that this cache had for /// any of the keys currently in the specified dictionary. /// </remarks> /// <param name="dictionary"> /// Mappings to be stored in this cache. /// </param> /// <exception cref="InvalidCastException"> /// If the class of a key or value in the specified dictionary /// prevents it from being stored in this cache. /// </exception> /// <exception cref="InvalidOperationException"> /// If the lock could not be succesfully obtained for some key. /// </exception> /// <exception cref="NullReferenceException"> /// This cache does not permit <c>null</c> keys or values, and the /// specified key or value is <c>null</c>. /// </exception> public virtual void InsertAll(IDictionary dictionary) { NamedCache.InsertAll(dictionary); }
/// <summary> /// Associates the specified value with the specified key in this /// cache. /// </summary> /// <remarks> /// <p> /// If the cache previously contained a mapping for this key, the old /// value is replaced.</p> /// <p> /// Invoking this method is equivalent to the following call: /// <pre> /// Insert(key, value, CacheExpiration.Default); /// </pre></p> /// </remarks> /// <param name="key"> /// Key with which the specified value is to be associated. /// </param> /// <param name="value"> /// Value to be associated with the specified key. /// </param> /// <returns> /// Previous value associated with specified key, or <c>null</c> if /// there was no mapping for key. A <c>null</c> return can also /// indicate that the cache previously associated <c>null</c> /// with the specified key, if the implementation supports /// <c>null</c> values. /// </returns> public virtual object Insert(object key, object value) { return(NamedCache.Insert(key, value)); }
/// <summary> /// Get the values for all the specified keys, if they are in the /// cache. /// </summary> /// <remarks> /// <p> /// For each key that is in the cache, that key and its corresponding /// value will be placed in the dictionary that is returned by this /// method. The absence of a key in the returned dictionary indicates /// that it was not in the cache, which may imply (for caches that /// can load behind the scenes) that the requested data could not be /// loaded.</p> /// <p> /// The result of this method is defined to be semantically the same /// as the following implementation, without regards to threading /// issues:</p> /// <pre> /// IDictionary dict = new AnyDictionary(); /// // could be a Hashtable (but does not have to) /// foreach (object key in colKeys) /// { /// object value = this[key]; /// if (value != null || Contains(key)) /// { /// dict[key] = value; /// } /// } /// return dict; /// </pre> /// </remarks> /// <param name="keys"> /// A collection of keys that may be in the named cache. /// </param> /// <returns> /// A dictionary of keys to values for the specified keys passed in /// <paramref name="keys"/>. /// </returns> public virtual IDictionary GetAll(ICollection keys) { return(NamedCache.GetAll(keys)); }
/// <summary> /// Returns an enumerator that iterates through a collection. /// </summary> /// <returns> /// An <b>IEnumerator</b> object that can be used to iterate through /// the collection. /// </returns> ICacheEnumerator ICache.GetEnumerator() { return(NamedCache.GetEnumerator()); }
/// <summary> /// Attempt to lock the specified item within the specified period of /// time. /// </summary> /// <remarks> /// <p> /// The item doesn't have to exist to be <i>locked</i>. While the /// item is locked there is known to be a <i>lock holder</i> which /// has an exclusive right to modify (calling put and remove methods) /// that item.</p> /// <p> /// Lock holder is an abstract concept that depends on the /// IConcurrentCache implementation. For example, holder could /// be a cluster member or a thread (or both).</p> /// <p> /// Locking strategy may vary for concrete implementations as well. /// Lock could have an expiration time (this lock is sometimes called /// a "lease") or be held indefinitely (until the lock holder /// terminates).</p> /// <p> /// Some implementations may allow the entire map to be locked. If /// the map is locked in such a way, then only a lock holder is /// allowed to perform any of the "put" or "remove" operations.</p> /// <p> /// Passing the special constant /// <see cref="LockScope.LOCK_ALL"/> as the <i>key</i> /// parameter to indicate the cache lock is not allowed for /// WrapperNamedCache and will cause an exception to be thrown.</p> /// </remarks> /// <param name="key"> /// Key being locked. /// </param> /// <param name="waitTimeMillis"> /// The number of milliseconds to continue trying to obtain a lock; /// pass zero to return immediately; pass -1 to block the calling /// thread until the lock could be obtained. /// </param> /// <returns> /// <b>true</b> if the item was successfully locked within the /// specified time; <b>false</b> otherwise. /// </returns> public virtual bool Lock(object key, long waitTimeMillis) { return(NamedCache.Lock(key, waitTimeMillis)); }
/// <summary> /// Release local resources associated with this instance of /// INamedCache. /// </summary> /// <remarks> /// <p> /// Releasing a cache makes it no longer usable, but does not affect /// the cache itself. In other words, all other references to the /// cache will still be valid, and the cache data is not affected by /// releasing the reference. /// Any attempt to use this reference afterword will result in an /// exception.</p> /// </remarks> public virtual void Release() { NamedCache.Release(); }
/// <summary> /// Unlock the specified item. /// </summary> /// <remarks> /// The item doesn't have to exist to be <i>unlocked</i>. /// If the item is currently locked, only the <i>holder</i> of the /// lock could successfully unlock it. /// </remarks> /// <param name="key"> /// Key being unlocked. /// </param> /// <returns> /// <b>true</b> if the item was successfully unlocked; <b>false</b> /// otherwise. /// </returns> public virtual bool Unlock(object key) { return(NamedCache.Unlock(key)); }
/// <summary> /// Release and destroy this instance of INamedCache. /// </summary> /// <remarks> /// <p> /// <b>Warning:</b> This method is used to completely destroy the /// specified cache across the cluster. All references in the entire /// cluster to this cache will be invalidated, the cached data will /// be cleared, and all resources will be released.</p> /// </remarks> public virtual void Destroy() { NamedCache.Destroy(); }
/// <summary> /// Return a collection of the values contained in this cache for /// entries that satisfy the criteria expressed by the filter. /// </summary> /// <remarks> /// It is guaranteed that enumerator will traverse the array in such /// a way that the values come up in ascending order, sorted by /// the specified comparer or according to the /// <i>natural ordering</i>. /// </remarks> /// <param name="filter"> /// The <see cref="IFilter"/> object representing the criteria that /// the entries of this cache should satisfy. /// </param> /// <param name="comparer"> /// The <b>IComparable</b> object which imposes an ordering on /// entries in the resulting collection; or <c>null</c> if the /// entries' values natural ordering should be used. /// </param> /// <returns> /// A collection of entries that satisfy the specified criteria. /// </returns> public virtual object[] GetValues(IFilter filter, IComparer comparer) { return(NamedCache.GetValues(filter, comparer)); }
public Region(NamedCache owner, string name, int capacity, TimeSpan asyncTimeToLive, TimeSpan asyncUpdateInterval, string fileOrDirectory) { this.owner = owner; this.name = name; if (this.name == "_CFG_AppSettings") this.isAppsettingRegion = true; this.capacity = capacity; this.asyncTimeToLive = asyncTimeToLive; this.asyncUpdateInterval = asyncUpdateInterval; this.cachedItems = new Dictionary<string, CachedItem>(this.capacity, StringComparer.InvariantCultureIgnoreCase); this.cachedItemKeyByTags = new Dictionary<string, Dictionary<string, KeyValuePair<string, CachedItem>>>(16, StringComparer.InvariantCultureIgnoreCase); this.cachedItemObjectByTags = new Dictionary<string, List<KeyValuePair<string, CachedItem>>>(16, StringComparer.InvariantCultureIgnoreCase); this.Dependency = CacheDependency.Get(fileOrDirectory); }
/// <summary> /// Add an index to this IQueryCache. /// </summary> /// <remarks> /// This allows to correlate values stored in this /// <i>indexed cache</i> (or attributes of those values) to the /// corresponding keys in the indexed cache and increase the /// performance of <b>GetKeys</b> and <b>GetEntries</b> methods. /// </remarks> /// <param name="extractor"> /// The <see cref="IValueExtractor"/> object that is used to extract /// an indexable object from a value stored in the indexed /// cache. Must not be <c>null</c>. /// </param> /// <param name="isOrdered"> /// <b>true</b> if the contents of the indexed information should be /// ordered; <b>false</b> otherwise. /// </param> /// <param name="comparer"> /// The <b>IComparer</b> object which imposes an ordering on entries /// in the indexed cache; or <c>null</c> if the entries' values /// natural ordering should be used. /// </param> public virtual void AddIndex(IValueExtractor extractor, bool isOrdered, IComparer comparer) { NamedCache.AddIndex(extractor, isOrdered, comparer); }
/// <summary> /// Add a cache listener for a specific key. /// </summary> /// <remarks> /// <p> /// The listeners will receive <see cref="CacheEventArgs"/> objects, /// but if <paramref name="isLite"/> is passed as <b>true</b>, they /// <i>might</i> not contain the /// <see cref="CacheEventArgs.OldValue"/> and /// <see cref="CacheEventArgs.NewValue"/> properties.</p> /// <p> /// To unregister the ICacheListener, use the /// <see cref="RemoveCacheListener(ICacheListener, object)"/> /// method.</p> /// </remarks> /// <param name="listener"> /// The <see cref="ICacheListener"/> to add. /// </param> /// <param name="key"> /// The key that identifies the entry for which to raise events. /// </param> /// <param name="isLite"> /// <b>true</b> to indicate that the <see cref="CacheEventArgs"/> /// objects do not have to include the <b>OldValue</b> and /// <b>NewValue</b> property values in order to allow optimizations. /// </param> public virtual void AddCacheListener(ICacheListener listener, object key, bool isLite) { NamedCache.AddCacheListener(listener, key, isLite); }
/// <summary> /// Invoke the passed <see cref="IEntryProcessor"/> against the entry /// specified by the passed key, returning the result of the /// invocation. /// </summary> /// <param name="key"> /// The key to process; it is not required to exist within the /// cache. /// </param> /// <param name="agent"> /// The <b>IEntryProcessor</b> to use to process the specified key. /// </param> /// <returns> /// The result of the invocation as returned from the /// <b>IEntryProcessor</b>. /// </returns> public virtual object Invoke(object key, IEntryProcessor agent) { return(NamedCache.Invoke(key, agent)); }
/// <summary> /// Remove a cache listener that previously signed up for events /// about a specific key. /// </summary> /// <param name="listener"> /// The listener to remove. /// </param> /// <param name="key"> /// The key that identifies the entry for which to raise events. /// </param> public virtual void RemoveCacheListener(ICacheListener listener, object key) { NamedCache.RemoveCacheListener(listener, key); }
private bool RemoveCacheInternal(NamedCache cache) { if (this.nameCaches.ContainsKey(cache.Name) && this.nameCaches[cache.Name] == cache) { if (this.nameCaches.Remove(cache.Name)) { cache.Clear(); return true; } } return false; }
/// <summary> /// Add a cache listener that receives events based on a filter /// evaluation. /// </summary> /// <remarks> /// <p> /// The listeners will receive <see cref="CacheEventArgs"/> objects, /// but if <paramref name="isLite"/> is passed as <b>true</b>, they /// <i>might</i> not contain the <b>OldValue</b> and <b>NewValue</b> /// properties.</p> /// <p> /// To unregister the <see cref="ICacheListener"/>, use the /// <see cref="RemoveCacheListener(ICacheListener, IFilter)"/> /// method.</p> /// </remarks> /// <param name="listener"> /// The <see cref="ICacheListener"/> to add.</param> /// <param name="filter"> /// A filter that will be passed <b>CacheEvent</b> objects to /// select from; a <b>CacheEvent</b> will be delivered to the /// listener only if the filter evaluates to <b>true</b> for that /// <b>CacheEvent</b>; <c>null</c> is equivalent to a filter /// that alway returns <b>true</b>. /// </param> /// <param name="isLite"> /// <b>true</b> to indicate that the <see cref="CacheEventArgs"/> /// objects do not have to include the <b>OldValue</b> and /// <b>NewValue</b> property values in order to allow optimizations. /// </param> public virtual void AddCacheListener(ICacheListener listener, IFilter filter, bool isLite) { NamedCache.AddCacheListener(listener, filter, isLite); }
/// <summary> /// Removes all mappings from this instance of INamedCache. /// </summary> /// <remarks> /// Note: the removal of entries caused by this truncate operation will /// not be observable. /// </remarks> public virtual void Truncate() { NamedCache.Truncate(); }
public Region(NamedCache owner, string name, int capacity, int asyncUpdateInterval, string fileOrDirectory) { this.owner = owner; this.name = name; this.capacity = capacity; this.asyncUpdateInterval = asyncUpdateInterval; this.cachedItems = new Dictionary<string, CachedItem>(this.capacity, StringComparer.InvariantCultureIgnoreCase); this.cachedItemKeyByTags = new Dictionary<string, Dictionary<string, KeyValuePair<string, CachedItem>>>(16, StringComparer.InvariantCultureIgnoreCase); this.cachedItemObjectByTags = new Dictionary<string, List<KeyValuePair<string, CachedItem>>>(16, StringComparer.InvariantCultureIgnoreCase); this.Dependency = CacheDependency.Get(fileOrDirectory); }