Uploaded image for project: 'Spring Modules'
  1. Spring Modules
  2. MOD-489

Need to acquire lock before inserting data in cache

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: 0.9
    • Fix Version/s: None
    • Component/s: CACHE
    • Labels:
      None

      Description

      We have observed a problem using spring for OSCache. This issue happens when a thread inserts data into the cache while an other thread is handling a needsRefreshException.
      Consider the following example with 2 thread (th1, th2);
      At time t = 0, th1 wants to get some data from the cache. The method protected Object onGetFromCache(Serializable key, CachingModel model) from the OsCacheFacade is called. A Needs refresh exception is thrown, therefore th1 calls cacheManager.cancelUpdate(newKey);
      At time t = 1, th2 wants to get the same data from the cache, a needsRefreshException is thrown.
      At time t = 2, th1 has loaded the value and inserts it by calling onPutInCache.
      At time t = 3, th2 handles the needsRefreshException and calls cacheManager.cancelUpdate(newKey);

      The first problem occurs at time = 2, when th1 performs completeUpdate in EntryUpdateState :

      if (state != UPDATE_IN_PROGRESS)

      { throw new IllegalStateException("Cannot complete cache update - current state (" + state + ") is not UPDATE_IN_PROGRESS"); }

      There will be an exception a time = 3, in method public void cancelUpdate(String key) of the cache, because the state is null : log.error("internal error: expected to get a state from key [" + key + "]");

      The solution consists in acquiring a lock on the entry before performing any update. A possible (ugly solution), is to replace :

      /**

      • @see AbstractCacheProviderFacade#onPutInCache(Serializable, CachingModel,
      • Object)
        */
        protected void onPutInCache(Serializable key, CachingModel model, Object obj) {
        OsCacheCachingModel cachingModel = (OsCacheCachingModel) model;

      String newKey = getEntryKey(key);
      String[] groups = cachingModel.getGroups();

      if (groups == null || groups.length == 0) {
      try

      { cacheManager.getFromCache(newKey); } catch(NeedsRefreshException e) { cacheManager.putInCache(newKey, obj); }
      } else {
      try{ cacheManager.getFromCache(newKey); }

      catch(NeedsRefreshException e)

      { cacheManager.putInCache(newKey, obj, groups); }

      }
      }

        Attachments

          Activity

            People

            Assignee:
            yatesco Colin Yates
            Reporter:
            ekaspi Eyal Kaspi
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:

                Time Tracking

                Estimated:
                Original Estimate - 1m
                1m
                Remaining:
                Remaining Estimate - 1m
                1m
                Logged:
                Time Spent - Not Specified
                Not Specified