You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by kt...@apache.org on 2019/04/18 21:36:42 UTC
[accumulo] branch master updated: Avoid lock contention in table
configuration (#1102)
This is an automated email from the ASF dual-hosted git repository.
kturner pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/master by this push:
new 89d36cf Avoid lock contention in table configuration (#1102)
89d36cf is described below
commit 89d36cf48ee2256a4fdde30e27874f64e5225b7f
Author: Keith Turner <kt...@apache.org>
AuthorDate: Thu Apr 18 17:36:38 2019 -0400
Avoid lock contention in table configuration (#1102)
Lock contentions was observed in table configuration during profiling.
This change replaces a syncronized pointer to a ZooCache with an
AtomicReference.
---
.../server/conf/NamespaceConfiguration.java | 40 ++++++++++++++--------
.../accumulo/server/conf/TableConfiguration.java | 39 +++++++++++++--------
2 files changed, 49 insertions(+), 30 deletions(-)
diff --git a/server/base/src/main/java/org/apache/accumulo/server/conf/NamespaceConfiguration.java b/server/base/src/main/java/org/apache/accumulo/server/conf/NamespaceConfiguration.java
index 50c15ea..b3e9d76 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/conf/NamespaceConfiguration.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/conf/NamespaceConfiguration.java
@@ -17,6 +17,7 @@
package org.apache.accumulo.server.conf;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import org.apache.accumulo.core.Constants;
@@ -39,7 +40,7 @@ public class NamespaceConfiguration extends ObservableConfiguration {
private static final Map<PropCacheKey,ZooCache> propCaches = new java.util.HashMap<>();
private final AccumuloConfiguration parent;
- private ZooCachePropertyAccessor propCacheAccessor = null;
+ private final AtomicReference<ZooCachePropertyAccessor> propCacheAccessor = new AtomicReference<>();
protected NamespaceId namespaceId = null;
protected ServerContext context;
private ZooCacheFactory zcf = new ZooCacheFactory();
@@ -67,20 +68,27 @@ public class NamespaceConfiguration extends ObservableConfiguration {
this.zcf = zcf;
}
- private synchronized ZooCachePropertyAccessor getPropCacheAccessor() {
- if (propCacheAccessor == null) {
- synchronized (propCaches) {
- PropCacheKey key = new PropCacheKey(context.getInstanceID(), namespaceId.canonical());
- ZooCache propCache = propCaches.get(key);
- if (propCache == null) {
- propCache = zcf.getZooCache(context.getZooKeepers(),
- context.getZooKeepersSessionTimeOut(), new NamespaceConfWatcher(context));
- propCaches.put(key, propCache);
- }
- propCacheAccessor = new ZooCachePropertyAccessor(propCache);
+ private ZooCache getZooCache() {
+ synchronized (propCaches) {
+ PropCacheKey key = new PropCacheKey(context.getInstanceID(), namespaceId.canonical());
+ ZooCache propCache = propCaches.get(key);
+ if (propCache == null) {
+ propCache = zcf.getZooCache(context.getZooKeepers(), context.getZooKeepersSessionTimeOut(),
+ new NamespaceConfWatcher(context));
+ propCaches.put(key, propCache);
}
+ return propCache;
}
- return propCacheAccessor;
+ }
+
+ private ZooCachePropertyAccessor getPropCacheAccessor() {
+ // updateAndGet below always calls compare and set, so avoid if not null
+ ZooCachePropertyAccessor zcpa = propCacheAccessor.get();
+ if (zcpa != null)
+ return zcpa;
+
+ return propCacheAccessor
+ .updateAndGet(pca -> pca == null ? new ZooCachePropertyAccessor(getZooCache()) : pca);
}
private String getPath() {
@@ -155,8 +163,10 @@ public class NamespaceConfiguration extends ObservableConfiguration {
@Override
public synchronized void invalidateCache() {
- if (propCacheAccessor != null) {
- propCacheAccessor.invalidateCache();
+ ZooCachePropertyAccessor pca = propCacheAccessor.get();
+
+ if (pca != null) {
+ pca.invalidateCache();
}
// Else, if the accessor is null, we could lock and double-check
// to see if it happened to be created so we could invalidate its cache
diff --git a/server/base/src/main/java/org/apache/accumulo/server/conf/TableConfiguration.java b/server/base/src/main/java/org/apache/accumulo/server/conf/TableConfiguration.java
index 7652604..c1bbfcd 100644
--- a/server/base/src/main/java/org/apache/accumulo/server/conf/TableConfiguration.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/conf/TableConfiguration.java
@@ -54,7 +54,7 @@ public class TableConfiguration extends ObservableConfiguration {
private static final Map<PropCacheKey,ZooCache> propCaches = new java.util.HashMap<>();
- private ZooCachePropertyAccessor propCacheAccessor = null;
+ private final AtomicReference<ZooCachePropertyAccessor> propCacheAccessor = new AtomicReference<>();
private final ServerContext context;
private final NamespaceConfiguration parent;
private ZooCacheFactory zcf = new ZooCacheFactory();
@@ -78,20 +78,27 @@ public class TableConfiguration extends ObservableConfiguration {
this.zcf = zcf;
}
- private synchronized ZooCachePropertyAccessor getPropCacheAccessor() {
- if (propCacheAccessor == null) {
- synchronized (propCaches) {
- PropCacheKey key = new PropCacheKey(context.getInstanceID(), tableId.canonical());
- ZooCache propCache = propCaches.get(key);
- if (propCache == null) {
- propCache = zcf.getZooCache(context.getZooKeepers(),
- context.getZooKeepersSessionTimeOut(), new TableConfWatcher(context));
- propCaches.put(key, propCache);
- }
- propCacheAccessor = new ZooCachePropertyAccessor(propCache);
+ private ZooCache getZooCache() {
+ synchronized (propCaches) {
+ PropCacheKey key = new PropCacheKey(context.getInstanceID(), tableId.canonical());
+ ZooCache propCache = propCaches.get(key);
+ if (propCache == null) {
+ propCache = zcf.getZooCache(context.getZooKeepers(), context.getZooKeepersSessionTimeOut(),
+ new TableConfWatcher(context));
+ propCaches.put(key, propCache);
}
+ return propCache;
}
- return propCacheAccessor;
+ }
+
+ private ZooCachePropertyAccessor getPropCacheAccessor() {
+ // updateAndGet below always calls compare and set, so avoid if not null
+ ZooCachePropertyAccessor zcpa = propCacheAccessor.get();
+ if (zcpa != null)
+ return zcpa;
+
+ return propCacheAccessor
+ .updateAndGet(pca -> pca == null ? new ZooCachePropertyAccessor(getZooCache()) : pca);
}
@Override
@@ -163,8 +170,10 @@ public class TableConfiguration extends ObservableConfiguration {
@Override
public synchronized void invalidateCache() {
- if (propCacheAccessor != null) {
- propCacheAccessor.invalidateCache();
+ ZooCachePropertyAccessor pca = propCacheAccessor.get();
+
+ if (pca != null) {
+ pca.invalidateCache();
}
// Else, if the accessor is null, we could lock and double-check
// to see if it happened to be created so we could invalidate its cache