AppFabric Cache Versioning and Concurrency

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

This post contains a caching example which explains line by line versioning and concurrency features. In general AppFabric (both Azure and Server) caching supports optimistic and pessimistic concurrency models. Following MSDN article describes shortly all of them.
Please read this article first and then step trough this example.

/// <summary>
        /// Demonstrates versioning and concurrency.
        /// </summary>
        private static void sampleMethod()
        {
            SampleClass myObj = new SampleClass() { Id = 1 };

            var fact = new DataCacheFactory();
            var cache = fact.GetDefaultCache();

            SampleClass item;
         
            DataCacheItemVersion ver1 = null, ver2 = null, ver3 = null;
            DataCacheLockHandle hLock;
            string myKey = "KEY1";

            try
            {
                removeIfExists(cache, myKey);

                cache.Add(myKey, myObj);

                // Do a Simple Get, lock the object for 200 seconds
                item = (SampleClass)cache.GetAndLock(myKey, new TimeSpan(0, 0, 200), out hLock);
                if (item != null)
                {
                    Debug.Assert(item.Id == 1);

                    // If you try to execute GetAndLock in next 200 seconds following exception will be thrown:
                    // ErrorCode<ERRCA0011>:SubStatus<ES0001>:
                    // Object being referred to is currently locked, and cannot be accessed 
                    // until it is unlocked by the locking client. Please retry later.
                    // Use this method if you want to coordinate concurrency. Note that simple Get() is optimistic one
                    // and will always get the latest version. It will not take care about locks.
                    // Note that Put method on locked object will unlock it.

                }

                //
                // Optimistic Get of last version
                // Does not take care abaut any locks. It always succeeds if the item exists.
                // If the object is being updated, the Get method does not wait and always
                // the current version of the object is returned.
                item = (SampleClass)cache.Get(myKey);
                if (item != null)
                {
                    // Get() works always. It returns the last version, independent if it is locked or not.
                    Debug.Assert(item.Id == 1);                  
                }
             
                // Now we perform an optimistic Get() and return version information
                if ((item = (SampleClass)cache.Get(myKey, out ver1)) != null)
                {
                    // We expect ver1 here.
                    Debug.Assert(item.Id == 1);
                }


                // Get the Object only if the version has changed
                if ((item = (SampleClass)cache.GetIfNewer(myKey, ref ver1)) != null)
                {
                    // We do not enter here, because the unhanged version is in cache.
                }
                else
                {
                    // We still expect ver1 here.
                }

                // Now we update the object version v1 with a Put().  
                // This will work, b ecause the object in the cache is of version v1.
                ver2 = cache.Put(myKey, new SampleClass() { Id = 2 }, ver1);

          
                // Now we have v2 in the cache.
                if ((item = (SampleClass)cache.GetIfNewer(myKey, ref ver1)) != null)
                {
                    // We enter here, because object has changed in cache in relation to verBeforeChange.
                }
                else
                {
                    // We do not enter here.
                }

                if ((item = (SampleClass)cache.GetIfNewer(myKey, ref ver2)) != null)
                {
                    // We do not enter here.
                }
                else
                {
                    // We enter here, because no new version after versionAfterChange is added in cache.
                }

                // Now we replace very first version with the new one.
                // By passing the oldVersion parameter, this method can maintain concurrency.
                // If another process updates the cached object before this method is called, this method
                // will fail with following exception:
                // ErrorCode<ERRCA0001>:SubStatus<ES0001>:Client referring to the object has an older version of the object.
                // Latest version of the objects should be fetched for this client operation.
                // To demonstrate this start VS and run the program in debugger till this breakpoint.
                // Then step over with F10 in one VS instance and switch to another VS instance and press F10.
                ver3 = cache.Put(myKey, new SampleClass() { Id = 3 }, ver1);

                // If you use optimistic Put(), new version will be added even if the object is locked.
                // Lock will be released. Application is responsible to maintain concurrency by design.
                var ver4 = cache.Put(myKey, new SampleClass() { Id = 3 });

                try
                {
                    // Try the above PutAndUnlock . This will enable anothe rprocess to execute GetAndLock,
                    // which would otherwise fail
                    ver3 = cache.PutAndUnlock(myKey, new SampleClass() { Id = 11 }, hLock);
                }
                catch (DataCacheException ex)
                {
                    //ErrorCode<ERRCA0012>:SubStatus<ES0001>:Object being referred to is not locked by any client.
                }

                // Unlock Object
                try
                {
                    cache.Unlock(myKey, hLock);
                }
                catch (DataCacheException ex)
                {
                }

            }
            catch (DataCacheException ex)
            {
     
            }
        }




        private static void removeIfExists(DataCache cache, string key)
        {
            if (null != cache.Get(key))
           
{
                cache.Remove(key);
            }
        }




Posted Jun 10 2011, 11:00 PM by Damir Dobric
Filed under: , ,
developers.de is a .Net Community Blog powered by daenet GmbH.