From b2e08cf9ea24fb646e8e68f37bbb8db449e7b5e9 Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Sun, 19 Aug 2007 23:28:49 +0000
Subject: [PATCH] - implement new toVerboseString() method. - fix bugs found by entry cache unit tests. - sanitize backend map maintenance.
---
opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java | 13 +++
opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java | 37 +++++++++
opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java | 11 ++
opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java | 62 +++++++++++++++
opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java | 61 +++++++++++++++
5 files changed, 181 insertions(+), 3 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java
index 09c7d0c..085c5c0 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java
@@ -526,6 +526,19 @@
/**
+ * Return a verbose string representation of the current cache maps.
+ * This is useful primary for debugging and diagnostic purposes such
+ * as in the entry cache unit tests.
+ * @return String verbose string representation of the current cache
+ * maps in the following format: dn:id:backend
+ * one cache entry map representation per line
+ * or <CODE>null</CODE> if all maps are empty.
+ */
+ public abstract String toVerboseString();
+
+
+
+ /**
* Retrieves the maximum length of time in milliseconds to wait for
* a lock before giving up.
*
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
index 7633e06..e66f9ca 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
@@ -210,6 +210,17 @@
/**
* {@inheritDoc}
*/
+ public String toVerboseString()
+ {
+ // This implementation does not store entries.
+ return null;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
public boolean isConfigurationChangeAcceptable(
EntryCacheCfg configuration,
List<Message> unacceptableReasons
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
index a500207..201df37 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
@@ -562,9 +562,10 @@
return;
}
+ Backend backend = entry.getBackend();
// Try to remove the entry from the ID list as well.
- Map<Long,CacheEntry> map = idMap.get(entry.getBackend());
+ Map<Long,CacheEntry> map = idMap.get(backend);
if (map == null)
{
// This should't happen, but the entry isn't cached in the ID map so
@@ -573,6 +574,12 @@
}
map.remove(entry.getEntryID());
+
+ // If this backend becomes empty now remove it from the idMap map.
+ if (map.isEmpty())
+ {
+ idMap.remove(backend);
+ }
}
catch (Exception e)
{
@@ -858,6 +865,59 @@
/**
* {@inheritDoc}
*/
+ public String toVerboseString()
+ {
+ String verboseString = new String();
+
+ Map<DN,CacheEntry> dnMapCopy;
+ Map<Backend,HashMap<Long,CacheEntry>> idMapCopy;
+
+ // Grab cache lock to prevent any modifications
+ // to the cache maps until a snapshot is taken.
+ cacheLock.lock();
+ try {
+ // Examining the real maps will hold the lock and can cause map
+ // modifications in case of any access order maps, make copies
+ // instead.
+ dnMapCopy = new LinkedHashMap<DN,CacheEntry>(dnMap);
+ idMapCopy = new HashMap<Backend,HashMap<Long,CacheEntry>>(idMap);
+ } finally {
+ cacheLock.unlock();
+ }
+
+ // Check dnMap first.
+ for(DN dn : dnMapCopy.keySet()) {
+ verboseString = verboseString + dn.toString() + ":" +
+ (dnMapCopy.get(dn) != null ?
+ Long.toString(dnMapCopy.get(dn).getEntryID()) : null) +
+ ":" + (dnMapCopy.get(dn) != null ?
+ dnMapCopy.get(dn).getBackend().getBackendID() : null) +
+ "\n";
+ }
+
+ // See if there is anything on idMap that isnt reflected on
+ // dnMap in case maps went out of sync.
+ for (Backend backend : idMapCopy.keySet()) {
+ for (Long id : idMapCopy.get(backend).keySet()) {
+ if ((idMapCopy.get(backend).get(id) == null) ||
+ !dnMapCopy.containsKey(
+ idMapCopy.get(backend).get(id).getDN())) {
+ verboseString = verboseString +
+ (idMapCopy.get(backend).get(id) != null ?
+ idMapCopy.get(backend).get(id).getDN().toString() : null) +
+ ":" + id.toString() + ":" + backend.getBackendID() + "\n";
+ }
+ }
+ }
+
+ return (verboseString.length() > 0 ? verboseString : null);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
@Override()
public boolean isConfigurationAcceptable(EntryCacheCfg configuration,
List<Message> unacceptableReasons)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
index 75f38a8..816a658 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
@@ -662,7 +662,8 @@
Entry entry = null;
cacheReadLock.lock();
try {
- if (dnMap.containsKey(entryDN)) {
+ // Use get to generate entry access.
+ if (dnMap.get(entryDN) != null) {
entry = getEntryFromDB(entryDN);
}
} finally {
@@ -1017,6 +1018,64 @@
/**
* {@inheritDoc}
*/
+ public String toVerboseString()
+ {
+ String verboseString = new String();
+
+ Map<DN,Long> dnMapCopy;
+ Map<Backend,Map<Long,DN>> backendMapCopy;
+
+ // Grab write lock to prevent any modifications
+ // to the cache maps until a snapshot is taken.
+ cacheWriteLock.lock();
+ try {
+ // Examining the real maps will hold the lock
+ // and can cause map modifications in case of
+ // any access order maps, make copies instead.
+ dnMapCopy = new LinkedHashMap<DN,Long>(dnMap);
+ backendMapCopy =
+ new LinkedHashMap<Backend,Map<Long,DN>>
+ (backendMap);
+ } finally {
+ cacheWriteLock.unlock();
+ }
+
+ // Check dnMap first.
+ for (DN dn : dnMapCopy.keySet()) {
+ Backend backend = null;
+ Iterator<Backend> backendIterator = backendMapCopy.keySet().iterator();
+ while (backendIterator.hasNext()) {
+ backend = backendIterator.next();
+ Map<Long, DN> map = backendMapCopy.get(backend);
+ if ((map.get(dnMapCopy.get(dn)) != null) &&
+ (map.get(dnMapCopy.get(dn)).equals(dn))) {
+ break;
+ }
+ }
+ }
+
+ // See if there is anything on backendMap that isnt reflected on dnMap
+ // in case maps went out of sync.
+ Backend backend = null;
+ Iterator<Backend> backendIterator = backendMapCopy.keySet().iterator();
+ while (backendIterator.hasNext()) {
+ backend = backendIterator.next();
+ Map<Long, DN> map = backendMapCopy.get(backend);
+ for (Long id : map.keySet()) {
+ if (!dnMapCopy.containsKey(map.get(id)) || map.get(id) == null) {
+ verboseString = verboseString + (map.get(id) != null ?
+ map.get(id) : null) + ":" + id.toString() + ":" +
+ backend.getBackendID() + "\n";
+ }
+ }
+ }
+
+ return (verboseString.length() > 0 ? verboseString : null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override()
public boolean isConfigurationAcceptable(EntryCacheCfg configuration,
List<Message> unacceptableReasons)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
index 85f9f34..1cf9825 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
@@ -282,6 +282,7 @@
{
map = new ConcurrentHashMap<Long,SoftReference<CacheEntry>>();
map.put(entryID, ref);
+ idMap.put(backend, map);
}
else
{
@@ -361,6 +362,12 @@
{
ref.clear();
}
+ // If this backend becomes empty now remove
+ // it from the idMap map.
+ if (map.isEmpty())
+ {
+ idMap.remove(backend);
+ }
}
}
}
@@ -441,6 +448,28 @@
/**
* {@inheritDoc}
*/
+ public String toVerboseString()
+ {
+ String verboseString = new String();
+
+ // There're no locks in this cache to keep dnMap and idMap in
+ // sync. Examine dnMap only since its more likely to be up to
+ // date than idMap. Dont bother with copies either since this
+ // is SoftReference based implementation.
+ for(SoftReference<CacheEntry> ce : dnMap.values()) {
+ verboseString = verboseString + ce.get().getDN().toString() +
+ ":" + Long.toString(ce.get().getEntryID()) + ":" +
+ ce.get().getBackend().getBackendID() + "\n";
+ }
+
+ return (verboseString.length() > 0 ? verboseString : null);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
@Override()
public boolean isConfigurationAcceptable(EntryCacheCfg configuration,
List<Message> unacceptableReasons)
@@ -611,8 +640,9 @@
{
ref.clear();
+ Backend backend = freedEntry.getBackend();
ConcurrentHashMap<Long,SoftReference<CacheEntry>> map =
- idMap.get(freedEntry.getBackend());
+ idMap.get(backend);
if (map != null)
{
ref = map.remove(freedEntry.getEntryID());
@@ -620,6 +650,11 @@
{
ref.clear();
}
+ // If this backend becomes empty now remove
+ // it from the idMap map.
+ if (map.isEmpty()) {
+ idMap.remove(backend);
+ }
}
}
}
--
Gitblit v1.10.0