[NO ISSUE][OTH] Introduce NC CacheManager
- user model changes: no
- storage format changes: no
- interface changes: yes
Details:
- Introduce NC CacheManager that can be used to cache
values and reevaluate them based on cache policy.
- Add test case for CacheManager.
Change-Id: I8cba7753af11469e8a45cb1d59dfd70c17cd05f6
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3277
Sonar-Qube: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Michael Blow <mblow@apache.org>
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
index 724691c..e663b49 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
@@ -108,6 +108,8 @@
import org.apache.hyracks.storage.common.file.ILocalResourceRepositoryFactory;
import org.apache.hyracks.storage.common.file.IResourceIdFactory;
import org.apache.hyracks.util.MaintainedThreadNameExecutorService;
+import org.apache.hyracks.util.cache.CacheManager;
+import org.apache.hyracks.util.cache.ICacheManager;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -149,6 +151,7 @@
private IIndexCheckpointManagerProvider indexCheckpointManagerProvider;
private IReplicaManager replicaManager;
private IReceptionist receptionist;
+ private ICacheManager cacheManager;
public NCAppRuntimeContext(INCServiceContext ncServiceContext, List<AsterixExtension> extensions,
IPropertiesFactory propertiesFactory) throws AsterixException, InstantiationException,
@@ -175,6 +178,7 @@
componentProvider = new StorageComponentProvider();
resourceIdFactory = new GlobalResourceIdFactoryProvider(ncServiceContext).createResourceIdFactory();
persistedResourceRegistry = ncServiceContext.getPersistedResourceRegistry();
+ cacheManager = new CacheManager();
}
@Override
@@ -543,4 +547,9 @@
public IReceptionist getReceptionist() {
return receptionist;
}
+
+ @Override
+ public ICacheManager getCacheManager() {
+ return cacheManager;
+ }
}
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java
index c6e7439..a18ff93 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/INcApplicationContext.java
@@ -40,6 +40,7 @@
import org.apache.hyracks.storage.common.ILocalResourceRepository;
import org.apache.hyracks.storage.common.buffercache.IBufferCache;
import org.apache.hyracks.storage.common.file.IResourceIdFactory;
+import org.apache.hyracks.util.cache.ICacheManager;
public interface INcApplicationContext extends IApplicationContext {
@@ -125,4 +126,11 @@
long getMaxTxnId();
IPersistedResourceRegistry getPersistedResourceRegistry();
+
+ /**
+ * Gets the cache manager of this {@link INcApplicationContext}
+ *
+ * @return the cache manager
+ */
+ ICacheManager getCacheManager();
}
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/CacheManager.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/CacheManager.java
new file mode 100644
index 0000000..6dc2aac
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/CacheManager.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.util.cache;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.hyracks.util.annotations.ThreadSafe;
+
+@ThreadSafe
+public class CacheManager implements ICacheManager {
+
+ private final Map<String, ICacheableValue> registry = new ConcurrentHashMap<>();
+
+ @Override
+ public void put(String key, ICacheableValue value) {
+ registry.put(key, value);
+ value.cache();
+ }
+
+ @Override
+ public Object get(String key) {
+ final ICacheableValue value = registry.get(key);
+ if (value == null) {
+ return null;
+ }
+ synchronized (value) {
+ if (value.getPolicy().expired()) {
+ value.cache();
+ }
+ return value.get();
+ }
+ }
+
+ @Override
+ public void invalidate(String key) {
+ registry.remove(key);
+ }
+}
\ No newline at end of file
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/CacheableValue.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/CacheableValue.java
new file mode 100644
index 0000000..7da8d50
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/CacheableValue.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.util.cache;
+
+import java.util.function.Supplier;
+
+public class CacheableValue<T> implements ICacheableValue<T> {
+
+ private final ICachePolicy policy;
+ private final Supplier<T> supplier;
+ private T value;
+
+ public CacheableValue(ICachePolicy policy, Supplier<T> supplier) {
+ this.policy = policy;
+ this.supplier = supplier;
+ }
+
+ @Override
+ public ICachePolicy getPolicy() {
+ return policy;
+ }
+
+ @Override
+ public void cache() {
+ value = supplier.get();
+ policy.cached();
+ }
+
+ @Override
+ public T get() {
+ return value;
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICacheManager.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICacheManager.java
new file mode 100644
index 0000000..bb9f485
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICacheManager.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.util.cache;
+
+public interface ICacheManager {
+
+ /**
+ * Puts the key and value in the cache and evaluates the value at the time it is put
+ * in the cache.
+ *
+ * @param key
+ * @param value
+ */
+ void put(String key, ICacheableValue value);
+
+ /**
+ * Gets the cached value associated with {@code key}
+ *
+ * @param key
+ * @return
+ */
+ Object get(String key);
+
+ /**
+ * Invalidates the cached value associated with {@code key}
+ *
+ * @param key
+ */
+ void invalidate(String key);
+}
\ No newline at end of file
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICachePolicy.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICachePolicy.java
new file mode 100644
index 0000000..fd9a68c
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICachePolicy.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.util.cache;
+
+public interface ICachePolicy {
+
+ /**
+ * A flag indicating whether a cached value has expired according to this policy
+ *
+ * @return whether the value expired or not
+ */
+ boolean expired();
+
+ /**
+ * Notify this cache policy that a value associated with this policy has been cached
+ */
+ void cached();
+}
\ No newline at end of file
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICacheableValue.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICacheableValue.java
new file mode 100644
index 0000000..42c5c66
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/ICacheableValue.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.util.cache;
+
+public interface ICacheableValue<T> {
+
+ /**
+ * Gets the cache policy
+ *
+ * @return the cache policy
+ */
+ ICachePolicy getPolicy();
+
+ /**
+ * Caches this value by evaluating its current value
+ */
+ void cache();
+
+ /**
+ * Gets the last evaluated value of this cache value
+ *
+ * @return the value
+ */
+ T get();
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/TimeBasedCachePolicy.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/TimeBasedCachePolicy.java
new file mode 100644
index 0000000..ddc46e5
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/cache/TimeBasedCachePolicy.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.util.cache;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hyracks.util.annotations.ThreadSafe;
+
+@ThreadSafe
+public class TimeBasedCachePolicy implements ICachePolicy {
+
+ private final long expiryNanos;
+ private long lastCacheTime;
+
+ private TimeBasedCachePolicy(long expiryNanos) {
+ this.expiryNanos = expiryNanos;
+ }
+
+ public static TimeBasedCachePolicy of(long value, TimeUnit unit) {
+ return new TimeBasedCachePolicy(unit.toNanos(value));
+ }
+
+ @Override
+ public synchronized boolean expired() {
+ return System.nanoTime() - lastCacheTime >= expiryNanos;
+ }
+
+ @Override
+ public synchronized void cached() {
+ lastCacheTime = System.nanoTime();
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/test/java/org/apache/hyracks/util/cache/CacheManagerTest.java b/hyracks-fullstack/hyracks/hyracks-util/src/test/java/org/apache/hyracks/util/cache/CacheManagerTest.java
new file mode 100644
index 0000000..4181084
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/test/java/org/apache/hyracks/util/cache/CacheManagerTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.util.cache;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CacheManagerTest {
+
+ @Test
+ public void expiryTest() throws Exception {
+ CacheManager cacheManager = new CacheManager();
+ String key = "someKey";
+ AtomicInteger realValue = new AtomicInteger(100);
+ final TimeBasedCachePolicy policy = TimeBasedCachePolicy.of(5, TimeUnit.SECONDS);
+ cacheManager.put(key, new CacheableValue<>(policy, realValue::get));
+ realValue.set(200);
+ Object cachedValue = null;
+ for (int i = 0; i < 10; i++) {
+ cachedValue = cacheManager.get(key);
+ if ((int) cachedValue == realValue.get()) {
+ break;
+ }
+ TimeUnit.SECONDS.sleep(1);
+ }
+ Assert.assertEquals((int) cachedValue, realValue.get());
+ }
+}