diff --git a/memcache/pom.xml b/memcache/pom.xml new file mode 100644 index 00000000000..7ec220830a4 --- /dev/null +++ b/memcache/pom.xml @@ -0,0 +1,92 @@ + + + + 4.0.0 + war + 1.0-SNAPSHOT + + com.google.appengine.samples.memcache + memcache + + + 1 + 1.9.18 + UTF-8 + + + + 3.1.0 + + + + + + com.google.appengine + appengine-api-1.0-sdk + ${appengine.version} + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.codehaus.mojo + versions-maven-plugin + 2.1 + + + compile + + display-dependency-updates + display-plugin-updates + + + + + + org.apache.maven.plugins + 3.1 + maven-compiler-plugin + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + true + + + + ${basedir}/src/main/webapp/WEB-INF + true + WEB-INF + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.15 + + + checkstyle + validate + + check + + + true + + + + + + + diff --git a/memcache/src/main/java/com/google/appengine/samples/memcache/AsyncMemcache.java b/memcache/src/main/java/com/google/appengine/samples/memcache/AsyncMemcache.java new file mode 100644 index 00000000000..f5b42b08641 --- /dev/null +++ b/memcache/src/main/java/com/google/appengine/samples/memcache/AsyncMemcache.java @@ -0,0 +1,93 @@ +/* Copyright 2015 Google Inc. + + Licensed 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 com.google.appengine.samples.memcache; + +import com.google.appengine.api.memcache.AsyncMemcacheService; +import com.google.appengine.api.memcache.ErrorHandlers; +import com.google.appengine.api.memcache.MemcacheServiceFactory; +import com.google.appengine.api.utils.FutureWrapper; + +import java.util.Map; +import java.util.concurrent.Future; +import java.util.logging.Level; + +/** + * Example asynchronous usage of App Engine Memcache. + * AsyncMemcache wraps a "slow" map with the memcache service. + */ +public class AsyncMemcache { + + /** + * the backing map for the memcache. + */ + private Map map; + + /** + * Singleton App Engine Memcache service. + */ + private static AsyncMemcacheService asyncCache = null; + + /** + * a Lock to ensure that asyncCache is a threadsafe singleton. + */ + private static final Object MEMCACHE_LOCK = new Object(); + + /** + * @param slowMap a Map for which retrieval is quite expensive + */ + public AsyncMemcache(final Map slowMap) { + this.map = slowMap; + } + + /** + * @param key the String key used for lookup + * @return a Future which can be used to retrieve the value + **/ + public final Future get(final String key) { + return new FutureWrapper(asyncCache.get(key)) { + + @Override + protected Throwable convertException(final Throwable arg0) { + return arg0; + } + + @Override + protected byte[] wrap(final Object arg0) throws Exception { + byte[] value = (byte[]) arg0; + if (arg0 == null) { + value = map.get(key); + asyncCache.put(key, arg0); + } + return value; + } + }; + } + /** + * @return this instances singleton asyncCache service. + */ + public final AsyncMemcacheService getService() { + if (asyncCache == null) { + synchronized (MEMCACHE_LOCK) { + if (asyncCache == null) { + asyncCache = MemcacheServiceFactory.getAsyncMemcacheService(); + asyncCache.setErrorHandler( + ErrorHandlers.getConsistentLogAndContinue(Level.INFO)); + } + } + } + return asyncCache; + } +} diff --git a/memcache/src/main/java/com/google/appengine/samples/memcache/SyncMemcache.java b/memcache/src/main/java/com/google/appengine/samples/memcache/SyncMemcache.java new file mode 100644 index 00000000000..a712b04836a --- /dev/null +++ b/memcache/src/main/java/com/google/appengine/samples/memcache/SyncMemcache.java @@ -0,0 +1,85 @@ +/* Copyright 2015 Google Inc. + + Licensed 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 com.google.appengine.samples.memcache; + +import com.google.appengine.api.memcache.ErrorHandlers; +import com.google.appengine.api.memcache.MemcacheService; +import com.google.appengine.api.memcache.MemcacheServiceFactory; + +import java.util.Map; +import java.util.logging.Level; + +/** + * Example synchronous usage of App Engine Memcache. + * SyncMemcache wraps a "slow" map with the memcache service. + */ +public class SyncMemcache { + + /** + * the backing map for the memcache. + */ + private Map map; + + /** + * Singleton App Engine Memcache service. + */ + private static MemcacheService syncCache = null; + + /** + * a Lock to ensure that syncCache is a threadsafe singleton. + */ + private static final Object MEMCACHE_LOCK = new Object(); + + /** + * @param slowMap a Map for which retrieval is quite expensive + */ + + /** + * @param slowMap a Map for which retrieval is quite expensive + */ + public SyncMemcache(final Map slowMap) { + this.map = slowMap; + } + + /** + * @param key the String key used for lookup + * @return a byte[] representing the stored value + **/ + public final byte[] get(final String key) { + byte[] value = (byte[]) syncCache.get(key); + if (value == null) { + value = map.get(key); + syncCache.put(key, value); + } + return value; + } + + /** + * @return this instances singleton syncCache service. + */ + public final MemcacheService getService() { + if (syncCache == null) { + synchronized (MEMCACHE_LOCK) { + if (syncCache == null) { + syncCache = MemcacheServiceFactory.getMemcacheService(); + syncCache.setErrorHandler( + ErrorHandlers.getConsistentLogAndContinue(Level.INFO)); + } + } + } + return syncCache; + } +} diff --git a/memcache/src/main/java/com/google/appengine/samples/memcache/ThreadsafeMemcacheUpdater.java b/memcache/src/main/java/com/google/appengine/samples/memcache/ThreadsafeMemcacheUpdater.java new file mode 100644 index 00000000000..9ea32c2a5a2 --- /dev/null +++ b/memcache/src/main/java/com/google/appengine/samples/memcache/ThreadsafeMemcacheUpdater.java @@ -0,0 +1,92 @@ +/* Copyright 2015 Google Inc. + + Licensed 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 com.google.appengine.samples.memcache; + +import com.google.appengine.api.memcache.ErrorHandlers; +import com.google.appengine.api.memcache.MemcacheService; +import com.google.appengine.api.memcache.MemcacheServiceFactory; + +import java.util.logging.Level; + +/** + * Example synchronous usage of App Engine Memcache. + * SyncMemcache wraps a "slow" map with the memcache service. + */ +public class ThreadsafeMemcacheUpdater { + + /** + * class wrapper for byte[] -> byte[] update function. + */ + public abstract class Updater { + + /** + * @param value byte[] the old value + * @return byte[] the new value + */ + public abstract byte[] update(byte[] value); + + } + + /** + * Singleton App Engine Memcache service. + */ + private static MemcacheService syncCache = null; + + /** + * a Lock to ensure that syncCache is a threadsafe singleton. + */ + private static final Object MEMCACHE_LOCK = new Object(); + + /** + * Empty constructor. + */ + public ThreadsafeMemcacheUpdater() { + } + + /** + * @param key the String identifying which value to update + * @param update an Update wrapper which represents the function to apply + * @return boolean indicating if the value was successfully updated + */ + public final boolean update(final String key, final Updater update) { + MemcacheService.IdentifiableValue oldValue = syncCache.getIdentifiable(key); + if (oldValue == null) { + syncCache.put(key, update.update(null)); + return true; + } else { + return syncCache.putIfUntouched(key, + oldValue, + update.update((byte[]) oldValue.getValue())); + } + } + + + /** + * @return this instances singleton syncCache service. + */ + public final MemcacheService getService() { + if (syncCache == null) { + synchronized (MEMCACHE_LOCK) { + if (syncCache == null) { + syncCache = MemcacheServiceFactory.getMemcacheService(); + syncCache.setErrorHandler( + ErrorHandlers.getConsistentLogAndContinue(Level.INFO)); + } + } + } + return syncCache; + } +} diff --git a/memcache/src/main/java/com/google/appengine/samples/memcache/package-info.java b/memcache/src/main/java/com/google/appengine/samples/memcache/package-info.java new file mode 100644 index 00000000000..26dd9b5567c --- /dev/null +++ b/memcache/src/main/java/com/google/appengine/samples/memcache/package-info.java @@ -0,0 +1,5 @@ + +/** + * Sample usage of the App Engine Memcache service. + */ +package com.google.appengine.samples.memcache; diff --git a/memcache/src/main/webapp/WEB-INF/appengine-web.xml b/memcache/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..538db0d0fee --- /dev/null +++ b/memcache/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,31 @@ + + + + 1 + + + true + + + + + + + + + diff --git a/unittests/src/main/webapp/WEB-INF/appengine-web.xml b/unittests/src/main/webapp/WEB-INF/appengine-web.xml index 8bf645d1013..7c82396201c 100644 --- a/unittests/src/main/webapp/WEB-INF/appengine-web.xml +++ b/unittests/src/main/webapp/WEB-INF/appengine-web.xml @@ -1,7 +1,7 @@ your-app-id - ${appengine.app.version} + 1 true