From a1cc2468fa0336f909c0db925d95c0d594b0b9db Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Tue, 4 Dec 2012 10:48:10 -0600 Subject: [PATCH] Issue #1383 fix grid_info purging Change-Id: I275869e9c9c93ed345298e1ef5e746a80e5f4b27 Former-commit-id: 090c916e49d46d65a0a0d5af587778f085ca91be [formerly 0de8b1014a90bc67ee3d6468590d878eb9e53755 [formerly de868e782076fa5ca77bd5bb69898ebed626fa45]] Former-commit-id: 0de8b1014a90bc67ee3d6468590d878eb9e53755 Former-commit-id: a8597ff254308b686403efbef51d3965a807466b --- .../edex/plugin/grid/dao/GridInfoCache.java | 104 ++++++++++++++---- 1 file changed, 80 insertions(+), 24 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridInfoCache.java b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridInfoCache.java index ae17c6708c..108992daec 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridInfoCache.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.grid/src/com/raytheon/uf/edex/plugin/grid/dao/GridInfoCache.java @@ -20,13 +20,18 @@ package com.raytheon.uf.edex.plugin.grid.dao; import java.lang.ref.SoftReference; +import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import com.raytheon.uf.common.dataplugin.grid.GridInfoRecord; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; +import com.raytheon.uf.edex.database.cluster.ClusterLockUtils; +import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState; +import com.raytheon.uf.edex.database.cluster.ClusterTask; import com.raytheon.uf.edex.database.dao.CoreDao; import com.raytheon.uf.edex.database.dao.DaoConfig; @@ -69,27 +74,9 @@ public class GridInfoCache { public GridInfoRecord getGridInfo(GridInfoRecord record) { GridInfoRecord result = checkLocalCache(record); if (result == null) { - synchronized (this) { - // It is possible that this query will return multiple results, - // for example if the record we are looking for has a null - // secondaryId but some db entries have a secondaryId set then - // this query will return all matching models ignoring - // secondaryId. In general these cases should be rare and small. - // So we handle it by caching everything returned and then - // double checking the cache. - List> dbList = dao - .queryByExample(record); - if (dbList != null && !dbList.isEmpty()) { - for (PersistableDataObject pdo : dbList) { - GridInfoRecord gir = (GridInfoRecord) pdo; - cache.put(gir, new SoftReference(gir)); - } - } - result = checkLocalCache(record); - if (result == null) { - dao.saveOrUpdate(record); - result = record; - } + result = query(record); + if (result == null) { + result = insert(record); } } return result; @@ -104,9 +91,78 @@ public class GridInfoCache { return result; } - public void purgeCache(List modelKeys) { - for (Integer key : modelKeys) { - cache.remove(key); + /** + * Query the database for a record, if a record is found then it will be + * added to the cache and returned. + * + * @param record + * @return + */ + private GridInfoRecord query(GridInfoRecord record) { + // It is possible that this query will return multiple + // results, for example if the record we are looking for has + // a null secondaryId but some db entries have a secondaryId + // set then this query will return all matching models + // ignoring secondaryId. In general these cases should be + // rare and small. So we handle it by caching everything + // returned and then double checking the cache. + List> dbList = dao + .queryByExample(record); + if (dbList != null && !dbList.isEmpty()) { + for (PersistableDataObject pdo : dbList) { + GridInfoRecord gir = (GridInfoRecord) pdo; + // if we don't remove then when an entry exists already the key + // and value become references to different objects which is not + // what we want. + cache.remove(gir); + cache.put(gir, new SoftReference(gir)); + } + } + return checkLocalCache(record); + } + + /** + * Insert the record into the database if there is no current record that + * equals this one. This method uses a fairly broad cluster lock so only one + * thread at a time across all clustered edices can insert at a time. This + * method should not be used much on running systems since gridded models + * maintain fairly consistent info records over time. + * + * @param record + * @return + */ + private GridInfoRecord insert(GridInfoRecord record) { + ClusterTask ct = null; + do { + ct = ClusterLockUtils.lock("grid_info", "newEntry", 30000, true); + } while (!LockState.SUCCESSFUL.equals(ct.getLockState())); + try { + GridInfoRecord existing = query(record); + if (existing != null) { + return existing; + } + dao.saveOrUpdate(record); + } finally { + ClusterLockUtils.unlock(ct, false); + } + cache.put(record, new SoftReference(record)); + return record; + } + + /** + * Remove the info records with the specified ids from the cache. + * + * @param infoKeys + */ + public void purgeCache(Collection infoKeys) { + synchronized (cache) { + Iterator it = cache.keySet().iterator(); + while (it.hasNext()) { + GridInfoRecord next = it.next(); + if (infoKeys.contains(next.getId())) { + it.remove(); + } + } } }