You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2014/03/13 10:06:54 UTC
[1/9] git commit: WICKET-5527 Inefficient
DefaultPageStore.SerializedPagesCache
Repository: wicket
Updated Branches:
refs/heads/master 3a44d2e4a -> 0d277e299
WICKET-5527 Inefficient DefaultPageStore.SerializedPagesCache
Replace the ArrayList with ConcurrentLinkedDeque.
Remove the synchronization on it
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/8908b8f2
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/8908b8f2
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/8908b8f2
Branch: refs/heads/master
Commit: 8908b8f23d6a3e62eed021cac669d65cf9d0bf66
Parents: d269534
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Thu Mar 6 16:26:52 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Thu Mar 6 16:26:52 2014 +0200
----------------------------------------------------------------------
.../wicket/pageStore/DefaultPageStore.java | 93 ++++++++------------
1 file changed, 39 insertions(+), 54 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/8908b8f2/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
index 1e44ef0..96d4ff0 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
@@ -18,9 +18,8 @@ package org.apache.wicket.pageStore;
import java.io.Serializable;
import java.lang.ref.SoftReference;
-import java.util.ArrayList;
import java.util.Iterator;
-import java.util.List;
+import java.util.concurrent.ConcurrentLinkedDeque;
import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.serialize.ISerializer;
@@ -411,7 +410,7 @@ public class DefaultPageStore implements IPageStore
{
private final int size;
- private final List<SoftReference<SerializedPage>> cache;
+ private final ConcurrentLinkedDeque<SoftReference<SerializedPage>> cache;
/**
* Construct.
@@ -421,7 +420,7 @@ public class DefaultPageStore implements IPageStore
public SerializedPagesCache(final int size)
{
this.size = size;
- cache = new ArrayList<>(size);
+ cache = new ConcurrentLinkedDeque<>();
}
/**
@@ -436,18 +435,15 @@ public class DefaultPageStore implements IPageStore
if (size > 0)
{
- synchronized (cache)
+ for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
- for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
+ SoftReference<SerializedPage> ref = i.next();
+ SerializedPage entry = ref.get();
+ if (entry != null && entry.getPageId() == id &&
+ entry.getSessionId().equals(sessionId))
{
- SoftReference<SerializedPage> ref = i.next();
- SerializedPage entry = ref.get();
- if (entry != null && entry.getPageId() == id &&
- entry.getSessionId().equals(sessionId))
- {
- i.remove();
- return entry;
- }
+ i.remove();
+ return entry;
}
}
}
@@ -466,16 +462,13 @@ public class DefaultPageStore implements IPageStore
if (size > 0)
{
- synchronized (cache)
+ for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
- for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
+ SoftReference<SerializedPage> ref = i.next();
+ SerializedPage entry = ref.get();
+ if (entry != null && entry.getSessionId().equals(sessionId))
{
- SoftReference<SerializedPage> ref = i.next();
- SerializedPage entry = ref.get();
- if (entry != null && entry.getSessionId().equals(sessionId))
- {
- i.remove();
- }
+ i.remove();
}
}
}
@@ -497,26 +490,23 @@ public class DefaultPageStore implements IPageStore
SerializedPage result = null;
if (size > 0)
{
- synchronized (cache)
+ for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
- for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
+ SoftReference<SerializedPage> ref = i.next();
+ SerializedPage entry = ref.get();
+ if (entry != null && entry.getPageId() == pageId &&
+ entry.getSessionId().equals(sessionId))
{
- SoftReference<SerializedPage> ref = i.next();
- SerializedPage entry = ref.get();
- if (entry != null && entry.getPageId() == pageId &&
- entry.getSessionId().equals(sessionId))
- {
- i.remove();
- result = entry;
- break;
- }
+ i.remove();
+ result = entry;
+ break;
}
+ }
- if (result != null)
- {
- // move to top
- storePage(result);
- }
+ if (result != null)
+ {
+ // move to top
+ storePage(result);
}
}
return result;
@@ -530,28 +520,23 @@ public class DefaultPageStore implements IPageStore
*/
void storePage(SerializedPage page)
{
- SoftReference<SerializedPage> ref = new SoftReference<SerializedPage>(page);
-
if (size > 0)
{
- synchronized (cache)
+ for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
- for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
+ SoftReference<SerializedPage> r = i.next();
+ SerializedPage entry = r.get();
+ if (entry != null && entry.equals(page))
{
- SoftReference<SerializedPage> r = i.next();
- SerializedPage entry = r.get();
- if (entry != null && entry.equals(page))
- {
- i.remove();
- break;
- }
+ i.remove();
+ break;
}
+ }
- cache.add(ref);
- if (cache.size() > size)
- {
- cache.remove(0);
- }
+ cache.add(new SoftReference<>(page));
+ if (cache.size() > size)
+ {
+ cache.remove(0);
}
}
}
[3/9] git commit: WICKET-5527 Inefficient
DefaultPageStore.SerializedPagesCache
Posted by mg...@apache.org.
WICKET-5527 Inefficient DefaultPageStore.SerializedPagesCache
Extract AbstractCachingPageStore - an AbstractPageStore that uses SecondLevelPageCache to manage the caching
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/583e03cf
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/583e03cf
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/583e03cf
Branch: refs/heads/master
Commit: 583e03cf8f282c6c02d21c614594eaf1eecc15ae
Parents: 65bd82f
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Mon Mar 10 17:45:16 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Mon Mar 10 17:45:16 2014 +0200
----------------------------------------------------------------------
.../pageStore/AbstractCachingPageStore.java | 105 +++++++++++++++++++
.../wicket/pageStore/AbstractPageStore.java | 4 +-
.../wicket/pageStore/DefaultPageStore.java | 61 +++--------
.../wicket/pageStore/PerSessionPageStore.java | 58 ++--------
.../wicket/pageStore/SecondLevelPageCache.java | 2 +
5 files changed, 135 insertions(+), 95 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/583e03cf/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractCachingPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractCachingPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractCachingPageStore.java
new file mode 100644
index 0000000..86b8d82
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractCachingPageStore.java
@@ -0,0 +1,105 @@
+/*
+ * 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.wicket.pageStore;
+
+import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.serialize.ISerializer;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * An abstract {@link org.apache.wicket.pageStore.IPageStore} that uses
+ * {@link org.apache.wicket.pageStore.SecondLevelPageCache} to cache the stored pages in memory
+ *
+ * @param <P>
+ * The type of the page to be stored
+ */
+public abstract class AbstractCachingPageStore<P> extends AbstractPageStore
+{
+ /**
+ * The cache implementation
+ */
+ protected final SecondLevelPageCache<String, Integer, P> pagesCache;
+
+ /**
+ * Constructor.
+ *
+ * @param pageSerializer
+ * The serializer that will convert pages to/from byte[]
+ * @param dataStore
+ * The third level page cache
+ * @param pagesCache
+ * The cache to use as a second level store
+ */
+ protected AbstractCachingPageStore(ISerializer pageSerializer, IDataStore dataStore,
+ SecondLevelPageCache<String, Integer, P> pagesCache)
+ {
+ super(pageSerializer, dataStore);
+
+ this.pagesCache = Args.notNull(pagesCache, "pagesCache");
+ }
+
+ @Override
+ public IManageablePage getPage(final String sessionId, final int pageId)
+ {
+ P fromCache = pagesCache.getPage(sessionId, pageId);
+ if (fromCache != null)
+ {
+ return convertToPage(fromCache);
+ }
+
+ byte[] data = getPageData(sessionId, pageId);
+ if (data != null)
+ {
+ return deserializePage(data);
+ }
+ return null;
+ }
+
+ @Override
+ public void removePage(final String sessionId, final int pageId)
+ {
+ pagesCache.removePage(sessionId, pageId);
+ removePageData(sessionId, pageId);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void storePage(final String sessionId, final IManageablePage page)
+ {
+ byte[] data = serializePage(page);
+ if (data != null)
+ {
+ int pageId = page.getPageId();
+ pagesCache.storePage(sessionId, pageId, (P) page);
+ storePageData(sessionId, pageId, data);
+ }
+ }
+
+ @Override
+ public void unbind(final String sessionId)
+ {
+ removePageData(sessionId);
+ pagesCache.removePages(sessionId);
+ }
+
+ @Override
+ public void destroy()
+ {
+ super.destroy();
+ pagesCache.destroy();
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/583e03cf/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
index 16b1cbc..07f97d5 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
@@ -41,7 +41,7 @@ public abstract class AbstractPageStore implements IPageStore
protected AbstractPageStore(final ISerializer pageSerializer, final IDataStore dataStore)
{
Args.notNull(pageSerializer, "pageSerializer");
- Args.notNull(dataStore, "DataStore");
+ Args.notNull(dataStore, "dataStore");
this.pageSerializer = pageSerializer;
this.dataStore = dataStore;
@@ -149,6 +149,6 @@ public abstract class AbstractPageStore implements IPageStore
{
Args.notNull(data, "data");
- return (IManageablePage)pageSerializer.deserialize(data);
+ return (IManageablePage) pageSerializer.deserialize(data);
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/583e03cf/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
index b27e04f..393fac3 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
@@ -34,12 +34,10 @@ import org.slf4j.LoggerFactory;
* direction when loading {@link SerializedPage} from the data store.
*
*/
-public class DefaultPageStore extends AbstractPageStore
+public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.SerializedPage>
{
private static final Logger LOG = LoggerFactory.getLogger(DefaultPageStore.class);
- private final SerializedPagesCache serializedPagesCache;
-
/**
* Construct.
*
@@ -54,53 +52,22 @@ public class DefaultPageStore extends AbstractPageStore
public DefaultPageStore(final ISerializer pageSerializer, final IDataStore dataStore,
final int cacheSize)
{
- super(pageSerializer, dataStore);
- serializedPagesCache = new SerializedPagesCache(cacheSize);
- }
-
- @Override
- public IManageablePage getPage(final String sessionId, final int id)
- {
- SerializedPage fromCache = serializedPagesCache.getPage(sessionId, id);
- if (fromCache != null && fromCache.data != null)
- {
- return deserializePage(fromCache.data);
- }
-
- byte[] data = getPageData(sessionId, id);
- if (data != null)
- {
- return deserializePage(data);
- }
- return null;
- }
-
- @Override
- public void removePage(final String sessionId, final int id)
- {
- serializedPagesCache.removePage(sessionId, id);
- removePageData(sessionId, id);
+ super(pageSerializer, dataStore, new SerializedPagesCache(cacheSize));
}
@Override
public void storePage(final String sessionId, final IManageablePage page)
{
- SerializedPage serialized = serializePage(sessionId, page);
+ SerializedPage serialized = createSerializedPage(sessionId, page);
if (serialized != null)
{
- serializedPagesCache.storePage(sessionId, page.getPageId(), serialized);
- storePageData(sessionId, serialized.getPageId(), serialized.getData());
+ int pageId = page.getPageId();
+ pagesCache.storePage(sessionId, pageId, serialized);
+ storePageData(sessionId, pageId, serialized.getData());
}
}
@Override
- public void unbind(final String sessionId)
- {
- removePageData(sessionId);
- serializedPagesCache.removePages(sessionId);
- }
-
- @Override
public IManageablePage convertToPage(final Object object)
{
if (object == null)
@@ -140,7 +107,7 @@ public class DefaultPageStore extends AbstractPageStore
*/
private SerializedPage restoreStrippedSerializedPage(final SerializedPage serializedPage)
{
- SerializedPage result = serializedPagesCache.getPage(serializedPage.getSessionId(),
+ SerializedPage result = pagesCache.getPage(serializedPage.getSessionId(),
serializedPage.getPageId());
if (result != null)
{
@@ -164,13 +131,13 @@ public class DefaultPageStore extends AbstractPageStore
if (page instanceof IManageablePage)
{
IManageablePage _page = (IManageablePage)page;
- result = serializedPagesCache.getPage(sessionId, _page.getPageId());
+ result = pagesCache.getPage(sessionId, _page.getPageId());
if (result == null)
{
- result = serializePage(sessionId, _page);
+ result = createSerializedPage(sessionId, _page);
if (result != null)
{
- serializedPagesCache.storePage(sessionId, _page.getPageId(), result);
+ pagesCache.storePage(sessionId, _page.getPageId(), result);
}
}
}
@@ -304,7 +271,7 @@ public class DefaultPageStore extends AbstractPageStore
* @param page
* @return the serialized page information
*/
- protected SerializedPage serializePage(final String sessionId, final IManageablePage page)
+ protected SerializedPage createSerializedPage(final String sessionId, final IManageablePage page)
{
Args.notNull(sessionId, "sessionId");
Args.notNull(page, "page");
@@ -478,5 +445,11 @@ public class DefaultPageStore extends AbstractPageStore
}
}
}
+
+ @Override
+ public void destroy()
+ {
+ cache.clear();
+ }
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/583e03cf/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
index ac57ab9..f1d5d9a 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
@@ -25,16 +25,13 @@ import java.util.concurrent.ConcurrentSkipListMap;
import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.serialize.ISerializer;
import org.apache.wicket.util.lang.Args;
-import org.apache.wicket.util.lang.Objects;
import org.apache.wicket.util.time.Time;
/**
*
*/
-public class PerSessionPageStore extends AbstractPageStore
+public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePage>
{
- private final SecondLevelPageCache<String, Integer, IManageablePage> pagesCache;
-
/**
* Construct.
*
@@ -49,50 +46,7 @@ public class PerSessionPageStore extends AbstractPageStore
public PerSessionPageStore(final ISerializer pageSerializer, final IDataStore dataStore,
final int cacheSize)
{
- super(pageSerializer, dataStore);
- this.pagesCache = new PagesCache(cacheSize);
- }
-
- @Override
- public IManageablePage getPage(final String sessionId, final int id)
- {
- IManageablePage fromCache = pagesCache.getPage(sessionId, id);
- if (fromCache != null)
- {
- return fromCache;
- }
-
- byte[] data = getPageData(sessionId, id);
- if (data != null)
- {
- return deserializePage(data);
- }
- return null;
- }
-
- @Override
- public void removePage(final String sessionId, final int id)
- {
- pagesCache.removePage(sessionId, id);
- removePageData(sessionId, id);
- }
-
- @Override
- public void storePage(final String sessionId, final IManageablePage page)
- {
- byte[] data = serializePage(page);
- if (data != null)
- {
- pagesCache.storePage(sessionId, page.getPageId(), page);
- storePageData(sessionId, page.getPageId(), data);
- }
- }
-
- @Override
- public void unbind(final String sessionId)
- {
- removePageData(sessionId);
- pagesCache.removePages(sessionId);
+ super(pageSerializer, dataStore, new PagesCache(cacheSize));
}
@Override
@@ -166,7 +120,7 @@ public class PerSessionPageStore extends AbstractPageStore
@Override
public int compare(PageValue p1, PageValue p2)
{
- return Objects.compareWithConversion(p1.accessTime, p2.accessTime);
+ return p1.accessTime.compareTo(p2.accessTime);
}
}
@@ -333,5 +287,11 @@ public class PerSessionPageStore extends AbstractPageStore
}
}
}
+
+ @Override
+ public void destroy()
+ {
+ cache.clear();
+ }
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/583e03cf/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
index 656827e..3d30857 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
@@ -37,4 +37,6 @@ public interface SecondLevelPageCache<S, PI, P>
P getPage(S session, PI pageId);
void storePage(S session, PI pageId, P page);
+
+ void destroy();
}
[4/9] git commit: WICKET-5527 Inefficient
DefaultPageStore.SerializedPagesCache
Posted by mg...@apache.org.
WICKET-5527 Inefficient DefaultPageStore.SerializedPagesCache
Clean up and javadoc
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/25016d10
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/25016d10
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/25016d10
Branch: refs/heads/master
Commit: 25016d10b9762682d783252b0ded2697def9e870
Parents: 583e03c
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Mon Mar 10 17:55:05 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Mon Mar 10 17:55:05 2014 +0200
----------------------------------------------------------------------
.../org/apache/wicket/DefaultPageManagerProvider.java | 7 ++++---
.../java/org/apache/wicket/page/AbstractPageManager.java | 4 ----
.../org/apache/wicket/pageStore/PerSessionPageStore.java | 11 ++++++++++-
3 files changed, 14 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/25016d10/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
index 3ce5f8c..bb1640e 100644
--- a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
+++ b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
@@ -26,9 +26,9 @@ import org.apache.wicket.pageStore.DefaultPageStore;
import org.apache.wicket.pageStore.DiskDataStore;
import org.apache.wicket.pageStore.IDataStore;
import org.apache.wicket.pageStore.IPageStore;
-import org.apache.wicket.pageStore.PerSessionPageStore;
import org.apache.wicket.serialize.ISerializer;
import org.apache.wicket.settings.StoreSettings;
+import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.lang.Bytes;
/**
@@ -40,13 +40,14 @@ public class DefaultPageManagerProvider implements IPageManagerProvider
protected final Application application;
/**
- * Construct.
+ * Constructor.
*
* @param application
+ * The application instance
*/
public DefaultPageManagerProvider(Application application)
{
- this.application = application;
+ this.application = Args.notNull(application, "application");
}
@Override
http://git-wip-us.apache.org/repos/asf/wicket/blob/25016d10/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java b/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
index 21eb1f1..ca1cfe3 100644
--- a/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
+++ b/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
@@ -17,8 +17,6 @@
package org.apache.wicket.page;
import org.apache.wicket.util.lang.Args;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Convenience class for {@link IPageManager} implementations. Subclass should extend
@@ -29,8 +27,6 @@ import org.slf4j.LoggerFactory;
*/
public abstract class AbstractPageManager implements IPageManager
{
- private static final Logger log = LoggerFactory.getLogger(AbstractPageManager.class);
-
private final IPageManagerContext context;
/**
http://git-wip-us.apache.org/repos/asf/wicket/blob/25016d10/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
index f1d5d9a..8d0c631 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
@@ -28,12 +28,21 @@ import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.time.Time;
/**
+ * A page store that uses a SecondLevelPageCache with the last N used page instances
+ * per session.
*
+ * <strong>Note</strong>: the size of the cache depends on the {@code cacheSize} constructor
+ * parameter multiplied by the number of the active http sessions.
+ *
+ * It depends on the application use cases but usually a reasonable value of
+ * {@code cacheSize} would be just a few pages (2-3). If the application don't expect many
+ * active http sessions and the work flow involves usage of the browser/application history
+ * then the {@code cacheSize} value may be increased to a bigger value.
*/
public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePage>
{
/**
- * Construct.
+ * Constructor.
*
* @param pageSerializer
* the {@link org.apache.wicket.serialize.ISerializer} that will be used to convert pages from/to byte arrays
[6/9] git commit: Fix the name of the JavaSerializer
Posted by mg...@apache.org.
Fix the name of the JavaSerializer
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/4ae0fb16
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/4ae0fb16
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/4ae0fb16
Branch: refs/heads/master
Commit: 4ae0fb16b61d9979d2b11c7a75fe2d284a9501c3
Parents: 1c31627
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Tue Mar 11 12:21:38 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Tue Mar 11 12:21:38 2014 +0200
----------------------------------------------------------------------
.../java/org/apache/wicket/pageStore/AbstractPageStoreTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/4ae0fb16/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
index 42cce39..0ab35fd 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
@@ -28,7 +28,7 @@ public abstract class AbstractPageStoreTest extends Assert
{
protected final String sessionId = "1234567890";
protected final int pageId = 123;
- protected final ISerializer serializer = new JavaSerializer(DefaultPageStore.class.getName());
+ protected final ISerializer serializer = new JavaSerializer(getClass().getName());
protected final IDataStore dataStore = new NoopDataStore();
protected int maxEntries = 1;
protected IPageStore pageStore = null;
[2/9] git commit: WICKET-5527 Inefficient
DefaultPageStore.SerializedPagesCache
Posted by mg...@apache.org.
WICKET-5527 Inefficient DefaultPageStore.SerializedPagesCache
Introduce PerSessionPageStore.
Extract the common logic between DefaultPageStore and PerSessionPageStore into AbstractPageStore.
Extract interface for SecondLevelPageCache implementations
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/65bd82fe
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/65bd82fe
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/65bd82fe
Branch: refs/heads/master
Commit: 65bd82fe9754d30ed103eba52aa1dc1e07f71bc0
Parents: 8908b8f2
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Mon Mar 10 15:20:36 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Mon Mar 10 15:20:36 2014 +0200
----------------------------------------------------------------------
.../wicket/DefaultPageManagerProvider.java | 2 +
.../apache/wicket/page/AbstractPageManager.java | 23 +-
.../apache/wicket/page/PageStoreManager.java | 2 +-
.../wicket/pageStore/AbstractPageStore.java | 154 +++++++++
.../wicket/pageStore/DefaultPageStore.java | 144 +++-----
.../org/apache/wicket/pageStore/IPageStore.java | 2 +-
.../wicket/pageStore/PerSessionPageStore.java | 337 +++++++++++++++++++
.../wicket/pageStore/SecondLevelPageCache.java | 40 +++
.../wicket/protocol/http/WebApplication.java | 1 -
.../wicket/versioning/InMemoryPageStore.java | 6 +-
10 files changed, 580 insertions(+), 131 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
index 4d8adcb..3ce5f8c 100644
--- a/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
+++ b/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java
@@ -26,6 +26,7 @@ import org.apache.wicket.pageStore.DefaultPageStore;
import org.apache.wicket.pageStore.DiskDataStore;
import org.apache.wicket.pageStore.IDataStore;
import org.apache.wicket.pageStore.IPageStore;
+import org.apache.wicket.pageStore.PerSessionPageStore;
import org.apache.wicket.serialize.ISerializer;
import org.apache.wicket.settings.StoreSettings;
import org.apache.wicket.util.lang.Bytes;
@@ -71,6 +72,7 @@ public class DefaultPageManagerProvider implements IPageManagerProvider
int inmemoryCacheSize = getStoreSettings().getInmemoryCacheSize();
ISerializer pageSerializer = application.getFrameworkSettings().getSerializer();
return new DefaultPageStore(pageSerializer, dataStore, inmemoryCacheSize);
+// return new PerSessionPageStore(pageSerializer, dataStore, inmemoryCacheSize);
}
protected IDataStore newDataStore()
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java b/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
index da259e4..21eb1f1 100644
--- a/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
+++ b/wicket-core/src/main/java/org/apache/wicket/page/AbstractPageManager.java
@@ -50,17 +50,9 @@ public abstract class AbstractPageManager implements IPageManager
*/
protected abstract RequestAdapter newRequestAdapter(IPageManagerContext context);
- /**
- *
- * @see org.apache.wicket.page.IPageManager#supportsVersioning()
- */
@Override
public abstract boolean supportsVersioning();
- /**
- *
- * @see org.apache.wicket.page.IPageManager#sessionExpired(java.lang.String)
- */
@Override
public abstract void sessionExpired(String sessionId);
@@ -75,7 +67,6 @@ public abstract class AbstractPageManager implements IPageManager
/**
* @see #newRequestAdapter(IPageManagerContext)
- *
* @return the request adapter
*/
protected RequestAdapter getRequestAdapter()
@@ -89,41 +80,29 @@ public abstract class AbstractPageManager implements IPageManager
return adapter;
}
- /**
- * @see org.apache.wicket.page.IPageManager#commitRequest()
- */
@Override
public void commitRequest()
{
getRequestAdapter().commitRequest();
}
- /**
- * @see org.apache.wicket.page.IPageManager#getPage(int)
- */
@Override
public IManageablePage getPage(int id)
{
IManageablePage page = getRequestAdapter().getPage(id);
if (page != null)
{
- getRequestAdapter().touch(page);
+ touchPage(page);
}
return page;
}
- /**
- * @see org.apache.wicket.page.IPageManager#newSessionCreated()
- */
@Override
public void newSessionCreated()
{
getRequestAdapter().newSessionCreated();
}
- /**
- * @see org.apache.wicket.page.IPageManager#touchPage(org.apache.wicket.page.IManageablePage)
- */
@Override
public void touchPage(IManageablePage page)
{
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java b/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java
index c13eaee..2149773 100644
--- a/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java
+++ b/wicket-core/src/main/java/org/apache/wicket/page/PageStoreManager.java
@@ -269,7 +269,7 @@ public class PageStoreManager extends AbstractPageManager
{
s.defaultReadObject();
- afterReadObject = new ArrayList<Object>();
+ afterReadObject = new ArrayList<>();
List<Serializable> l = (List<Serializable>)s.readObject();
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
new file mode 100644
index 0000000..16b1cbc
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPageStore.java
@@ -0,0 +1,154 @@
+/*
+ * 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.wicket.pageStore;
+
+import java.io.Serializable;
+
+import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.serialize.ISerializer;
+import org.apache.wicket.util.lang.Args;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public abstract class AbstractPageStore implements IPageStore
+{
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractPageStore.class);
+
+ protected final IDataStore dataStore;
+
+ /**
+ * The {@link org.apache.wicket.serialize.ISerializer} that will be used to convert pages from/to byte arrays
+ */
+ protected final ISerializer pageSerializer;
+
+ protected AbstractPageStore(final ISerializer pageSerializer, final IDataStore dataStore)
+ {
+ Args.notNull(pageSerializer, "pageSerializer");
+ Args.notNull(dataStore, "DataStore");
+
+ this.pageSerializer = pageSerializer;
+ this.dataStore = dataStore;
+ }
+
+ @Override
+ public void destroy()
+ {
+ dataStore.destroy();
+ }
+
+ @Override
+ public Serializable prepareForSerialization(final String sessionId, final Serializable page)
+ {
+ if (dataStore.isReplicated())
+ {
+ return null;
+ }
+
+ return page;
+ }
+
+ @Override
+ public Object restoreAfterSerialization(final Serializable serializable)
+ {
+ return serializable;
+ }
+
+ /**
+ * @param sessionId
+ * The id of the http session
+ * @param pageId
+ * The id of page which serialized data should be got
+ * @return page data
+ * @see org.apache.wicket.pageStore.IDataStore#getData(String, int)
+ */
+ protected byte[] getPageData(final String sessionId, final int pageId)
+ {
+ return dataStore.getData(sessionId, pageId);
+ }
+
+ /**
+ * @param sessionId
+ * The id of the http session
+ * @param pageId
+ * The id of page which serialized data should be removed
+ * @see org.apache.wicket.pageStore.IDataStore#removeData(String, int)
+ */
+ protected void removePageData(final String sessionId, final int pageId)
+ {
+ dataStore.removeData(sessionId, pageId);
+ }
+
+ /**
+ * @param sessionId
+ * The id of the http session for which all data should be removed
+ * @see org.apache.wicket.pageStore.IDataStore#removeData(String)
+ */
+ protected void removePageData(final String sessionId)
+ {
+ dataStore.removeData(sessionId);
+ }
+
+ /**
+ * @param sessionId
+ * The id of the http session
+ * @param pageId
+ * The id of the page to store
+ * @param data
+ * The serialized view of the page
+ * @see org.apache.wicket.pageStore.IDataStore#storeData(String, int, byte[])
+ */
+ protected void storePageData(final String sessionId, final int pageId, final byte[] data)
+ {
+ dataStore.storeData(sessionId, pageId, data);
+ }
+
+ /**
+ * Serializes the passed page to byte[]
+ *
+ * @param page
+ * The page to serialize
+ * @return the serialized view of the passed page
+ */
+ protected byte[] serializePage(final IManageablePage page)
+ {
+ Args.notNull(page, "page");
+
+ byte[] data = pageSerializer.serialize(page);
+
+ if (data == null && LOG.isWarnEnabled())
+ {
+ LOG.warn("Page {} cannot be serialized. See previous logs for possible reasons.", page);
+ }
+ return data;
+ }
+
+ /**
+ *
+ * @param data
+ * The serialized view of the page
+ * @return page data deserialized
+ */
+ protected IManageablePage deserializePage(final byte[] data)
+ {
+ Args.notNull(data, "data");
+
+ return (IManageablePage)pageSerializer.deserialize(data);
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
index 96d4ff0..b27e04f 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
@@ -34,19 +34,12 @@ import org.slf4j.LoggerFactory;
* direction when loading {@link SerializedPage} from the data store.
*
*/
-public class DefaultPageStore implements IPageStore
+public class DefaultPageStore extends AbstractPageStore
{
private static final Logger LOG = LoggerFactory.getLogger(DefaultPageStore.class);
private final SerializedPagesCache serializedPagesCache;
- private final IDataStore pageDataStore;
-
- /**
- * The {@link ISerializer} that will be used to convert pages from/to byte arrays
- */
- private final ISerializer pageSerializer;
-
/**
* Construct.
*
@@ -61,64 +54,10 @@ public class DefaultPageStore implements IPageStore
public DefaultPageStore(final ISerializer pageSerializer, final IDataStore dataStore,
final int cacheSize)
{
- Args.notNull(pageSerializer, "pageSerializer");
- Args.notNull(dataStore, "DataStore");
-
- this.pageSerializer = pageSerializer;
- pageDataStore = dataStore;
+ super(pageSerializer, dataStore);
serializedPagesCache = new SerializedPagesCache(cacheSize);
}
- /**
- * @see org.apache.wicket.pageStore.IPageStore#destroy()
- */
- @Override
- public void destroy()
- {
- pageDataStore.destroy();
- }
-
- /**
- * @param sessionId
- * @param pageId
- * @return page data
- * @see IDataStore#getData(String, int)
- */
- protected byte[] getPageData(final String sessionId, final int pageId)
- {
- return pageDataStore.getData(sessionId, pageId);
- }
-
- /**
- * @param sessionId
- * @param pageId
- * @see IDataStore#removeData(String, int)
- */
- protected void removePageData(final String sessionId, final int pageId)
- {
- pageDataStore.removeData(sessionId, pageId);
- }
-
- /**
- * @param sessionId
- * @see IDataStore#removeData(String)
- */
- protected void removePageData(final String sessionId)
- {
- pageDataStore.removeData(sessionId);
- }
-
- /**
- * @param sessionId
- * @param pageId
- * @param data
- * @see IDataStore#storeData(String, int, byte[])
- */
- protected void storePageData(final String sessionId, final int pageId, final byte[] data)
- {
- pageDataStore.storeData(sessionId, pageId, data);
- }
-
@Override
public IManageablePage getPage(final String sessionId, final int id)
{
@@ -149,7 +88,7 @@ public class DefaultPageStore implements IPageStore
SerializedPage serialized = serializePage(sessionId, page);
if (serialized != null)
{
- serializedPagesCache.storePage(serialized);
+ serializedPagesCache.storePage(sessionId, page.getPageId(), serialized);
storePageData(sessionId, serialized.getPageId(), serialized.getData());
}
}
@@ -213,38 +152,38 @@ public class DefaultPageStore implements IPageStore
}
@Override
- public Serializable prepareForSerialization(final String sessionId, final Object object)
+ public Serializable prepareForSerialization(final String sessionId, final Serializable page)
{
- if (pageDataStore.isReplicated())
+ if (dataStore.isReplicated())
{
return null;
}
SerializedPage result = null;
- if (object instanceof IManageablePage)
+ if (page instanceof IManageablePage)
{
- IManageablePage page = (IManageablePage)object;
- result = serializedPagesCache.getPage(sessionId, page.getPageId());
+ IManageablePage _page = (IManageablePage)page;
+ result = serializedPagesCache.getPage(sessionId, _page.getPageId());
if (result == null)
{
- result = serializePage(sessionId, page);
+ result = serializePage(sessionId, _page);
if (result != null)
{
- serializedPagesCache.storePage(result);
+ serializedPagesCache.storePage(sessionId, _page.getPageId(), result);
}
}
}
- else if (object instanceof SerializedPage)
+ else if (page instanceof SerializedPage)
{
- SerializedPage page = (SerializedPage)object;
- if (page.getData() == null)
+ SerializedPage _page = (SerializedPage)page;
+ if (_page.getData() == null)
{
- result = restoreStrippedSerializedPage(page);
+ result = restoreStrippedSerializedPage(_page);
}
else
{
- result = page;
+ result = _page;
}
}
@@ -252,7 +191,7 @@ public class DefaultPageStore implements IPageStore
{
return result;
}
- return (Serializable)object;
+ return page;
}
/**
@@ -372,7 +311,7 @@ public class DefaultPageStore implements IPageStore
SerializedPage serializedPage = null;
- byte[] data = pageSerializer.serialize(page);
+ byte[] data = serializePage(page);
if (data != null)
{
@@ -386,17 +325,6 @@ public class DefaultPageStore implements IPageStore
}
/**
- *
- * @param data
- * @return page data deserialized
- */
- protected IManageablePage deserializePage(final byte[] data)
- {
- IManageablePage page = (IManageablePage)pageSerializer.deserialize(data);
- return page;
- }
-
- /**
* Cache that stores serialized pages. This is important to make sure that a single page is not
* serialized twice or more when not necessary.
* <p>
@@ -406,7 +334,7 @@ public class DefaultPageStore implements IPageStore
*
* @author Matej Knopp
*/
- static class SerializedPagesCache
+ static class SerializedPagesCache implements SecondLevelPageCache<String, Integer, SerializedPage>
{
private final int size;
@@ -426,20 +354,22 @@ public class DefaultPageStore implements IPageStore
/**
*
* @param sessionId
- * @param id
+ * @param pageId
* @return the removed {@link SerializedPage} or <code>null</code> - otherwise
*/
- public SerializedPage removePage(final String sessionId, final int id)
+ @Override
+ public SerializedPage removePage(final String sessionId, final Integer pageId)
{
- Args.notNull(sessionId, "sessionId");
-
if (size > 0)
{
+ Args.notNull(sessionId, "sessionId");
+ Args.notNull(pageId, "pageId");
+
for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
SoftReference<SerializedPage> ref = i.next();
SerializedPage entry = ref.get();
- if (entry != null && entry.getPageId() == id &&
+ if (entry != null && entry.getPageId() == pageId &&
entry.getSessionId().equals(sessionId))
{
i.remove();
@@ -456,12 +386,13 @@ public class DefaultPageStore implements IPageStore
*
* @param sessionId
*/
+ @Override
public void removePages(String sessionId)
{
- Args.notNull(sessionId, "sessionId");
-
if (size > 0)
{
+ Args.notNull(sessionId, "sessionId");
+
for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
SoftReference<SerializedPage> ref = i.next();
@@ -483,13 +414,15 @@ public class DefaultPageStore implements IPageStore
* @param pageId
* @return the found serialized page or <code>null</code> when not found
*/
- public SerializedPage getPage(String sessionId, int pageId)
+ @Override
+ public SerializedPage getPage(String sessionId, Integer pageId)
{
- Args.notNull(sessionId, "sessionId");
-
SerializedPage result = null;
if (size > 0)
{
+ Args.notNull(sessionId, "sessionId");
+ Args.notNull(pageId, "pageId");
+
for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
SoftReference<SerializedPage> ref = i.next();
@@ -506,7 +439,7 @@ public class DefaultPageStore implements IPageStore
if (result != null)
{
// move to top
- storePage(result);
+ storePage(sessionId, pageId, result);
}
}
return result;
@@ -518,10 +451,15 @@ public class DefaultPageStore implements IPageStore
* @param page
* the data to serialize (page id, session id, bytes)
*/
- void storePage(SerializedPage page)
+ @Override
+ public void storePage(String sessionId, Integer pageId, SerializedPage page)
{
if (size > 0)
{
+ Args.notNull(sessionId, "sessionId");
+ Args.notNull(pageId, "pageId");
+ Args.notNull(page, "page");
+
for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
SoftReference<SerializedPage> r = i.next();
@@ -534,7 +472,7 @@ public class DefaultPageStore implements IPageStore
}
cache.add(new SoftReference<>(page));
- if (cache.size() > size)
+ while (cache.size() > size)
{
cache.remove(0);
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java
index 5fe3cf6..470536a 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageStore.java
@@ -84,7 +84,7 @@ public interface IPageStore
* @param page
* @return The Page itself or a SerializedContainer for that page
*/
- Serializable prepareForSerialization(String sessionId, Object page);
+ Serializable prepareForSerialization(String sessionId, Serializable page);
/**
* This method should restore the serialized page to intermediate object that can be converted
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
new file mode 100644
index 0000000..ac57ab9
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
@@ -0,0 +1,337 @@
+/*
+ * 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.wicket.pageStore;
+
+import java.lang.ref.SoftReference;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.serialize.ISerializer;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Objects;
+import org.apache.wicket.util.time.Time;
+
+/**
+ *
+ */
+public class PerSessionPageStore extends AbstractPageStore
+{
+ private final SecondLevelPageCache<String, Integer, IManageablePage> pagesCache;
+
+ /**
+ * Construct.
+ *
+ * @param pageSerializer
+ * the {@link org.apache.wicket.serialize.ISerializer} that will be used to convert pages from/to byte arrays
+ * @param dataStore
+ * the {@link org.apache.wicket.pageStore.IDataStore} that actually stores the pages
+ * @param cacheSize
+ * the number of pages to cache in memory before passing them to
+ * {@link org.apache.wicket.pageStore.IDataStore#storeData(String, int, byte[])}
+ */
+ public PerSessionPageStore(final ISerializer pageSerializer, final IDataStore dataStore,
+ final int cacheSize)
+ {
+ super(pageSerializer, dataStore);
+ this.pagesCache = new PagesCache(cacheSize);
+ }
+
+ @Override
+ public IManageablePage getPage(final String sessionId, final int id)
+ {
+ IManageablePage fromCache = pagesCache.getPage(sessionId, id);
+ if (fromCache != null)
+ {
+ return fromCache;
+ }
+
+ byte[] data = getPageData(sessionId, id);
+ if (data != null)
+ {
+ return deserializePage(data);
+ }
+ return null;
+ }
+
+ @Override
+ public void removePage(final String sessionId, final int id)
+ {
+ pagesCache.removePage(sessionId, id);
+ removePageData(sessionId, id);
+ }
+
+ @Override
+ public void storePage(final String sessionId, final IManageablePage page)
+ {
+ byte[] data = serializePage(page);
+ if (data != null)
+ {
+ pagesCache.storePage(sessionId, page.getPageId(), page);
+ storePageData(sessionId, page.getPageId(), data);
+ }
+ }
+
+ @Override
+ public void unbind(final String sessionId)
+ {
+ removePageData(sessionId);
+ pagesCache.removePages(sessionId);
+ }
+
+ @Override
+ public IManageablePage convertToPage(final Object object)
+ {
+ if (object == null)
+ {
+ return null;
+ }
+ else if (object instanceof IManageablePage)
+ {
+ return (IManageablePage)object;
+ }
+
+ String type = object.getClass().getName();
+ throw new IllegalArgumentException("Unknown object type: " + type);
+ }
+
+ /**
+ */
+ protected static class PagesCache implements SecondLevelPageCache<String, Integer, IManageablePage>
+ {
+ /**
+ * Helper class used to compare the page entries in the cache by their
+ * access time
+ */
+ private static class PageValue
+ {
+ /**
+ * The id of the cached page
+ */
+ private final int pageId;
+
+ /**
+ * The last time this page has been used/accessed.
+ */
+ private Time accessTime;
+
+ private PageValue(IManageablePage page)
+ {
+ this(page.getPageId());
+ }
+
+ private PageValue(int pageId)
+ {
+ this.pageId = pageId;
+ this.accessTime = Time.now();
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ PageValue pageValue = (PageValue) o;
+
+ return pageId == pageValue.pageId;
+
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return pageId;
+ }
+ }
+
+ private static class PageComparator implements Comparator<PageValue>
+ {
+ @Override
+ public int compare(PageValue p1, PageValue p2)
+ {
+ return Objects.compareWithConversion(p1.accessTime, p2.accessTime);
+ }
+ }
+
+ private final int maxEntriesPerSession;
+
+ private final ConcurrentSkipListMap<String, SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>>> cache;
+
+ /**
+ * Constructor.
+ *
+ * @param maxEntriesPerSession
+ * The number of cache entries per session
+ */
+ public PagesCache(final int maxEntriesPerSession)
+ {
+ this.maxEntriesPerSession = maxEntriesPerSession;
+ cache = new ConcurrentSkipListMap<>();
+ }
+
+ /**
+ *
+ * @param sessionId
+ * The id of the http session
+ * @param pageId
+ * The id of the page to remove from the cache
+ * @return the removed {@link org.apache.wicket.page.IManageablePage} or <code>null</code> - otherwise
+ */
+ @Override
+ public IManageablePage removePage(final String sessionId, final Integer pageId)
+ {
+ IManageablePage result = null;
+
+ if (maxEntriesPerSession > 0)
+ {
+ Args.notNull(sessionId, "sessionId");
+ Args.notNull(pageId, "pageId");
+
+ SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> pagesPerSession = cache.get(sessionId);
+ if (pagesPerSession != null)
+ {
+ ConcurrentMap<PageValue, IManageablePage> pages = pagesPerSession.get();
+ if (pages != null)
+ {
+ PageValue pv = new PageValue(pageId);
+ IManageablePage page = pages.remove(pv);
+ if (page != null)
+ {
+ result = page;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Removes all {@link org.apache.wicket.page.IManageablePage}s for the session
+ * with <code>sessionId</code> from the cache.
+ *
+ * @param sessionId
+ * The id of the expired http session
+ */
+ @Override
+ public void removePages(String sessionId)
+ {
+ Args.notNull(sessionId, "sessionId");
+
+ if (maxEntriesPerSession > 0)
+ {
+ cache.remove(sessionId);
+ }
+ }
+
+ /**
+ * Returns a {@link org.apache.wicket.page.IManageablePage} by looking it up by <code>sessionId</code> and
+ * <code>pageId</code>. If there is a match then it is <i>touched</i>, i.e. it is moved at
+ * the top of the cache.
+ *
+ * @param sessionId
+ * The id of the http session
+ * @param pageId
+ * The id of the page to find
+ * @return the found serialized page or <code>null</code> when not found
+ */
+ @Override
+ public IManageablePage getPage(String sessionId, Integer pageId)
+ {
+ IManageablePage result = null;
+
+ if (maxEntriesPerSession > 0)
+ {
+ Args.notNull(sessionId, "sessionId");
+ Args.notNull(pageId, "pageId");
+
+ SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> pagesPerSession = cache.get(sessionId);
+ if (pagesPerSession != null)
+ {
+ ConcurrentSkipListMap<PageValue, IManageablePage> pages = pagesPerSession.get();
+ if (pages != null)
+ {
+ PageValue pv = new PageValue(pageId);
+ Map.Entry<PageValue, IManageablePage> entry = pages.ceilingEntry(pv);
+
+ if (entry != null)
+ {
+ // touch the entry
+ entry.getKey().accessTime = Time.now();
+ result = entry.getValue();
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Store the serialized page in cache
+ *
+ * @param page
+ * the data to serialize (page id, session id, bytes)
+ */
+ @Override
+ public void storePage(String sessionId, Integer pageId, IManageablePage page)
+ {
+ if (maxEntriesPerSession > 0)
+ {
+ Args.notNull(sessionId, "sessionId");
+ Args.notNull(pageId, "pageId");
+
+ SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> pagesPerSession = cache.get(sessionId);
+ if (pagesPerSession == null)
+ {
+ ConcurrentSkipListMap<PageValue, IManageablePage> pages = new ConcurrentSkipListMap<>(new PageComparator());
+ pagesPerSession = new SoftReference<>(pages);
+ SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> old = cache.putIfAbsent(sessionId, pagesPerSession);
+ if (old != null)
+ {
+ pagesPerSession = old;
+ }
+ }
+
+ ConcurrentSkipListMap<PageValue, IManageablePage> pages = pagesPerSession.get();
+ if (pages == null)
+ {
+ pages = new ConcurrentSkipListMap<>();
+ pagesPerSession = new SoftReference<>(pages);
+ SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>> old = cache.putIfAbsent(sessionId, pagesPerSession);
+ if (old != null)
+ {
+ pages = old.get();
+ }
+ }
+
+ if (pages != null)
+ {
+ while (pages.size() > maxEntriesPerSession)
+ {
+ pages.pollFirstEntry();
+ }
+
+ PageValue pv = new PageValue(page);
+ pages.put(pv, page);
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
new file mode 100644
index 0000000..656827e
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/SecondLevelPageCache.java
@@ -0,0 +1,40 @@
+/*
+ * 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.wicket.pageStore;
+
+/**
+ * An application scoped cache that holds the last N used pages in the application.
+ * Acts as a second level cache between the Http Session (first level) and the
+ * disk (third level cache).
+ *
+ * @param <S>
+ * The type of the session identifier
+ * @param <PI>
+ * The type of the page identifier
+ * @param <P>
+ * The type of the stored page
+ */
+public interface SecondLevelPageCache<S, PI, P>
+{
+ P removePage(S session, PI pageId);
+
+ void removePages(S session);
+
+ P getPage(S session, PI pageId);
+
+ void storePage(S session, PI pageId, P page);
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
index 6c30bd1..988243a 100644
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
@@ -66,7 +66,6 @@ import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.resource.bundles.ReplacementResourceBundleReference;
-import org.apache.wicket.resource.bundles.ResourceBundleReference;
import org.apache.wicket.session.HttpSessionStore;
import org.apache.wicket.session.ISessionStore;
import org.apache.wicket.util.IContextProvider;
http://git-wip-us.apache.org/repos/asf/wicket/blob/65bd82fe/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java b/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java
index ca1399a..f69a918 100644
--- a/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java
+++ b/wicket-core/src/test/java/org/apache/wicket/versioning/InMemoryPageStore.java
@@ -40,7 +40,7 @@ public class InMemoryPageStore implements IDataStore
*/
public InMemoryPageStore()
{
- store = new ConcurrentHashMap<String, Map<Integer, byte[]>> ();
+ store = new ConcurrentHashMap<> ();
}
@Override
@@ -97,7 +97,7 @@ public class InMemoryPageStore implements IDataStore
Map<Integer, byte[]> sessionPages = store.get(sessionId);
if (sessionPages == null)
{
- sessionPages = new ConcurrentHashMap<Integer, byte[]>();
+ sessionPages = new ConcurrentHashMap<>();
Map<Integer, byte[]> tmpSessionPages = store.putIfAbsent(sessionId, sessionPages);
if (tmpSessionPages != null)
{
@@ -123,4 +123,4 @@ public class InMemoryPageStore implements IDataStore
return false;
}
-}
\ No newline at end of file
+}
[8/9] git commit: WICKET-5527 Inefficient
DefaultPageStore.SerializedPagesCache
Posted by mg...@apache.org.
WICKET-5527 Inefficient DefaultPageStore.SerializedPagesCache
Use ConcurrentHashMap for the sessions. There is no need to track their age so no need to use ConcurrentSkipListMap.
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/961e46ae
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/961e46ae
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/961e46ae
Branch: refs/heads/master
Commit: 961e46ae67ecda7c11fb1c58c2cfa98b06f98693
Parents: 2380d65
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Wed Mar 12 11:14:55 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Wed Mar 12 11:14:55 2014 +0200
----------------------------------------------------------------------
.../java/org/apache/wicket/pageStore/PerSessionPageStore.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/961e46ae/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
index 632cea9..fdfe92d 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
@@ -20,6 +20,7 @@ import java.lang.ref.SoftReference;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
@@ -144,7 +145,7 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
private final int maxEntriesPerSession;
- private final ConcurrentSkipListMap<String, SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>>> cache;
+ private final ConcurrentMap<String, SoftReference<ConcurrentSkipListMap<PageValue, IManageablePage>>> cache;
/**
* Constructor.
@@ -155,7 +156,7 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
public PagesCache(final int maxEntriesPerSession)
{
this.maxEntriesPerSession = maxEntriesPerSession;
- cache = new ConcurrentSkipListMap<>();
+ cache = new ConcurrentHashMap<>();
}
/**
[5/9] git commit: WICKET-5527 Inefficient
DefaultPageStore.SerializedPagesCache
Posted by mg...@apache.org.
WICKET-5527 Inefficient DefaultPageStore.SerializedPagesCache
Add tests and fix bugs in the new PerSessionPageStore impl
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/1c31627e
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/1c31627e
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/1c31627e
Branch: refs/heads/master
Commit: 1c31627e4bfc167bc6e2e29bd642991d6b5a1dcb
Parents: 25016d1
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Tue Mar 11 12:17:55 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Tue Mar 11 12:17:55 2014 +0200
----------------------------------------------------------------------
.../wicket/pageStore/DefaultPageStore.java | 46 ++++---
.../wicket/pageStore/PerSessionPageStore.java | 52 +++++---
.../wicket/pageStore/AbstractPageStoreTest.java | 131 +++++++++++++++++++
.../wicket/pageStore/DefaultPageStoreTest.java | 31 +++++
.../apache/wicket/pageStore/NoopDataStore.java | 61 +++++++++
.../pageStore/PerSessionPageStoreTest.java | 53 ++++++++
6 files changed, 336 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/1c31627e/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
index 393fac3..e574f37 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageStore.java
@@ -303,18 +303,19 @@ public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.
*/
static class SerializedPagesCache implements SecondLevelPageCache<String, Integer, SerializedPage>
{
- private final int size;
+ private final int maxSize;
private final ConcurrentLinkedDeque<SoftReference<SerializedPage>> cache;
/**
- * Construct.
+ * Constructor.
*
- * @param size
+ * @param maxSize
+ * The maximum number of entries to cache
*/
- public SerializedPagesCache(final int size)
+ public SerializedPagesCache(final int maxSize)
{
- this.size = size;
+ this.maxSize = maxSize;
cache = new ConcurrentLinkedDeque<>();
}
@@ -327,17 +328,18 @@ public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.
@Override
public SerializedPage removePage(final String sessionId, final Integer pageId)
{
- if (size > 0)
+ if (maxSize > 0)
{
Args.notNull(sessionId, "sessionId");
Args.notNull(pageId, "pageId");
+ SerializedPage sample = new SerializedPage(sessionId, pageId, null);
+
for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
SoftReference<SerializedPage> ref = i.next();
SerializedPage entry = ref.get();
- if (entry != null && entry.getPageId() == pageId &&
- entry.getSessionId().equals(sessionId))
+ if (sample.equals(entry))
{
i.remove();
return entry;
@@ -356,7 +358,7 @@ public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.
@Override
public void removePages(String sessionId)
{
- if (size > 0)
+ if (maxSize > 0)
{
Args.notNull(sessionId, "sessionId");
@@ -385,17 +387,18 @@ public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.
public SerializedPage getPage(String sessionId, Integer pageId)
{
SerializedPage result = null;
- if (size > 0)
+ if (maxSize > 0)
{
Args.notNull(sessionId, "sessionId");
Args.notNull(pageId, "pageId");
+ SerializedPage sample = new SerializedPage(sessionId, pageId, null);
+
for (Iterator<SoftReference<SerializedPage>> i = cache.iterator(); i.hasNext();)
{
SoftReference<SerializedPage> ref = i.next();
SerializedPage entry = ref.get();
- if (entry != null && entry.getPageId() == pageId &&
- entry.getSessionId().equals(sessionId))
+ if (sample.equals(entry))
{
i.remove();
result = entry;
@@ -406,7 +409,7 @@ public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.
if (result != null)
{
// move to top
- storePage(sessionId, pageId, result);
+ internalStore(result);
}
}
return result;
@@ -421,7 +424,7 @@ public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.
@Override
public void storePage(String sessionId, Integer pageId, SerializedPage page)
{
- if (size > 0)
+ if (maxSize > 0)
{
Args.notNull(sessionId, "sessionId");
Args.notNull(pageId, "pageId");
@@ -438,11 +441,16 @@ public class DefaultPageStore extends AbstractCachingPageStore<DefaultPageStore.
}
}
- cache.add(new SoftReference<>(page));
- while (cache.size() > size)
- {
- cache.remove(0);
- }
+ internalStore(page);
+ }
+ }
+
+ private void internalStore(SerializedPage page)
+ {
+ cache.push(new SoftReference<>(page));
+ while (cache.size() > maxSize)
+ {
+ cache.pollLast();
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/1c31627e/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
index 8d0c631..eaff550 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
@@ -18,6 +18,7 @@ package org.apache.wicket.pageStore;
import java.lang.ref.SoftReference;
import java.util.Comparator;
+import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
@@ -25,7 +26,6 @@ import java.util.concurrent.ConcurrentSkipListMap;
import org.apache.wicket.page.IManageablePage;
import org.apache.wicket.serialize.ISerializer;
import org.apache.wicket.util.lang.Args;
-import org.apache.wicket.util.time.Time;
/**
* A page store that uses a SecondLevelPageCache with the last N used page instances
@@ -75,6 +75,8 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
}
/**
+ * An implementation of SecondLevelPageCache that stores the last used N live page instances
+ * per http session.
*/
protected static class PagesCache implements SecondLevelPageCache<String, Integer, IManageablePage>
{
@@ -92,7 +94,7 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
/**
* The last time this page has been used/accessed.
*/
- private Time accessTime;
+ private long accessTime;
private PageValue(IManageablePage page)
{
@@ -102,7 +104,7 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
private PageValue(int pageId)
{
this.pageId = pageId;
- this.accessTime = Time.now();
+ this.accessTime = System.nanoTime();
}
@Override
@@ -114,7 +116,6 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
PageValue pageValue = (PageValue) o;
return pageId == pageValue.pageId;
-
}
@Override
@@ -129,7 +130,7 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
@Override
public int compare(PageValue p1, PageValue p2)
{
- return p1.accessTime.compareTo(p2.accessTime);
+ return Long.valueOf(p1.accessTime).compareTo(p2.accessTime);
}
}
@@ -173,11 +174,17 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
ConcurrentMap<PageValue, IManageablePage> pages = pagesPerSession.get();
if (pages != null)
{
- PageValue pv = new PageValue(pageId);
- IManageablePage page = pages.remove(pv);
- if (page != null)
+ PageValue sample = new PageValue(pageId);
+ Iterator<Map.Entry<PageValue, IManageablePage>> iterator = pages.entrySet().iterator();
+ while (iterator.hasNext())
{
- result = page;
+ Map.Entry<PageValue, IManageablePage> entry = iterator.next();
+ if (sample.equals(entry.getKey()))
+ {
+ result = entry.getValue();
+ iterator.remove();
+ break;
+ }
}
}
}
@@ -231,14 +238,19 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
ConcurrentSkipListMap<PageValue, IManageablePage> pages = pagesPerSession.get();
if (pages != null)
{
- PageValue pv = new PageValue(pageId);
- Map.Entry<PageValue, IManageablePage> entry = pages.ceilingEntry(pv);
-
- if (entry != null)
+ PageValue sample = new PageValue(pageId);
+ Iterator<Map.Entry<PageValue,IManageablePage>> iterator = pages.entrySet().iterator();
+ while (iterator.hasNext())
{
- // touch the entry
- entry.getKey().accessTime = Time.now();
- result = entry.getValue();
+ Map.Entry<PageValue, IManageablePage> entry = iterator.next();
+
+ if (sample.equals(entry.getKey()))
+ {
+ // touch the entry
+ entry.getKey().accessTime = System.nanoTime();
+ result = entry.getValue();
+ break;
+ }
}
}
}
@@ -286,13 +298,15 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
if (pages != null)
{
+ removePage(sessionId, pageId);
+
+ PageValue pv = new PageValue(page);
+ pages.put(pv, page);
+
while (pages.size() > maxEntriesPerSession)
{
pages.pollFirstEntry();
}
-
- PageValue pv = new PageValue(page);
- pages.put(pv, page);
}
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/1c31627e/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
new file mode 100644
index 0000000..42cce39
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.wicket.pageStore;
+
+import org.apache.wicket.MockPage;
+import org.apache.wicket.serialize.ISerializer;
+import org.apache.wicket.serialize.java.JavaSerializer;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public abstract class AbstractPageStoreTest extends Assert
+{
+ protected final String sessionId = "1234567890";
+ protected final int pageId = 123;
+ protected final ISerializer serializer = new JavaSerializer(DefaultPageStore.class.getName());
+ protected final IDataStore dataStore = new NoopDataStore();
+ protected int maxEntries = 1;
+ protected IPageStore pageStore = null;
+
+ @Before
+ public void before()
+ {
+ pageStore = createPageStore(serializer, dataStore, maxEntries);
+ }
+
+ protected abstract IPageStore createPageStore(ISerializer serializer, IDataStore dataStore, int maxEntries);
+
+ @After
+ public void after()
+ {
+ if (pageStore != null)
+ {
+ pageStore.destroy();
+ pageStore = null;
+ }
+ }
+
+ /**
+ * Assert that a stored page is available to be read
+ */
+ @Test
+ public void storePage()
+ {
+ pageStore.storePage(sessionId, new MockPage(pageId));
+
+ assertNotNull(pageStore.getPage(sessionId, pageId));
+ }
+
+ /**
+ * Assert that storing a page twice won't keep two entries
+ */
+ @Test
+ public void storePage2()
+ {
+ int maxEntries = 10;
+
+ pageStore = createPageStore(serializer, dataStore, maxEntries);
+
+ pageStore.storePage(sessionId, new MockPage(pageId));
+ pageStore.storePage(sessionId, new MockPage(pageId));
+
+ assertNotNull(pageStore.getPage(sessionId, pageId));
+
+ pageStore.removePage(sessionId, pageId);
+
+ assertNull(pageStore.getPage(sessionId, pageId));
+ }
+
+ @Test
+ public void removePage()
+ {
+ pageStore.storePage(sessionId, new MockPage(pageId));
+
+ assertNotNull(pageStore.getPage(sessionId, pageId));
+
+ pageStore.removePage(sessionId, pageId);
+
+ assertNull(pageStore.getPage(sessionId, pageId));
+ }
+
+ /**
+ * Verify that at most {@code maxEntries} per session can be put in the cache
+ */
+ @Test
+ public void maxSizeSameSession()
+ {
+ pageStore.storePage(sessionId, new MockPage(pageId));
+
+ assertNotNull(pageStore.getPage(sessionId, pageId));
+
+ int pageId2 = 234;
+ pageStore.storePage(sessionId, new MockPage(pageId2));
+ assertNull(pageStore.getPage(sessionId, pageId));
+ assertNotNull(pageStore.getPage(sessionId, pageId2));
+ }
+
+ /**
+ * Verify that it is OK to store more pages than {@code maxEntries}
+ * if they are in different sessions
+ */
+ @Test
+ public void maxSizeDifferentSessions()
+ {
+ String sessionId2 = "0987654321";
+
+ pageStore.storePage(sessionId, new MockPage(pageId));
+
+ assertNotNull(pageStore.getPage(sessionId, pageId));
+
+ pageStore.storePage(sessionId2, new MockPage(pageId));
+
+ assertNull(pageStore.getPage(sessionId, pageId));
+ assertNotNull(pageStore.getPage(sessionId2, pageId));
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/1c31627e/wicket-core/src/test/java/org/apache/wicket/pageStore/DefaultPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/DefaultPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/DefaultPageStoreTest.java
new file mode 100644
index 0000000..2ffa376
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/DefaultPageStoreTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.wicket.pageStore;
+
+import org.apache.wicket.serialize.ISerializer;
+
+/**
+ * Tests for DefaultPageStore
+ */
+public class DefaultPageStoreTest extends AbstractPageStoreTest
+{
+ @Override
+ protected IPageStore createPageStore(ISerializer serializer, IDataStore dataStore, int maxEntries)
+ {
+ return new DefaultPageStore(serializer, dataStore, maxEntries);
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/1c31627e/wicket-core/src/test/java/org/apache/wicket/pageStore/NoopDataStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/NoopDataStore.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/NoopDataStore.java
new file mode 100644
index 0000000..0cadaee
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/NoopDataStore.java
@@ -0,0 +1,61 @@
+/*
+ * 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.wicket.pageStore;
+
+/**
+ * An implementation of IDataStore that does nothing
+ */
+public class NoopDataStore implements IDataStore
+{
+ @Override
+ public byte[] getData(String sessionId, int id)
+ {
+ return null;
+ }
+
+ @Override
+ public void removeData(String sessionId, int id)
+ {
+ }
+
+ @Override
+ public void removeData(String sessionId)
+ {
+ }
+
+ @Override
+ public void storeData(String sessionId, int id, byte[] data)
+ {
+ }
+
+ @Override
+ public void destroy()
+ {
+ }
+
+ @Override
+ public boolean isReplicated()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean canBeAsynchronous()
+ {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/1c31627e/wicket-core/src/test/java/org/apache/wicket/pageStore/PerSessionPageStoreTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/PerSessionPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/PerSessionPageStoreTest.java
new file mode 100644
index 0000000..0cd4a2a
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/PerSessionPageStoreTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.wicket.pageStore;
+
+import org.apache.wicket.MockPage;
+import org.apache.wicket.serialize.ISerializer;
+import org.junit.Test;
+
+/**
+ * Tests for PerSessionPageStore
+ */
+public class PerSessionPageStoreTest extends AbstractPageStoreTest
+{
+ @Override
+ protected IPageStore createPageStore(ISerializer serializer, IDataStore dataStore, int maxEntries)
+ {
+ return new PerSessionPageStore(serializer, dataStore, maxEntries);
+ }
+
+ /**
+ * Verify that it is OK to store more pages than {@code maxEntries}
+ * if they are in different sessions
+ */
+ @Test
+ @Override
+ public void maxSizeDifferentSessions()
+ {
+ String sessionId2 = "0987654321";
+
+ pageStore.storePage(sessionId, new MockPage(pageId));
+
+ assertNotNull(pageStore.getPage(sessionId, pageId));
+
+ pageStore.storePage(sessionId2, new MockPage(pageId));
+
+ assertNotNull(pageStore.getPage(sessionId, pageId));
+ assertNotNull(pageStore.getPage(sessionId2, pageId));
+ }
+}
[9/9] git commit: Merge branch '5527-inefficient-DefaultDataStore'
Posted by mg...@apache.org.
Merge branch '5527-inefficient-DefaultDataStore'
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/0d277e29
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/0d277e29
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/0d277e29
Branch: refs/heads/master
Commit: 0d277e299109cb1a17a75e98eddd00b444149aa3
Parents: 3a44d2e 961e46a
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Thu Mar 13 11:04:42 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Thu Mar 13 11:04:42 2014 +0200
----------------------------------------------------------------------
.../wicket/DefaultPageManagerProvider.java | 7 +-
.../apache/wicket/page/AbstractPageManager.java | 27 +-
.../apache/wicket/page/PageStoreManager.java | 2 +-
.../pageStore/AbstractCachingPageStore.java | 105 ++++++
.../wicket/pageStore/AbstractPageStore.java | 154 +++++++++
.../wicket/pageStore/DefaultPageStore.java | 308 ++++++------------
.../org/apache/wicket/pageStore/IPageStore.java | 2 +-
.../wicket/pageStore/PerSessionPageStore.java | 326 +++++++++++++++++++
.../wicket/pageStore/SecondLevelPageCache.java | 42 +++
.../wicket/protocol/http/WebApplication.java | 1 -
.../wicket/pageStore/AbstractPageStoreTest.java | 131 ++++++++
.../wicket/pageStore/DefaultPageStoreTest.java | 31 ++
.../apache/wicket/pageStore/NoopDataStore.java | 61 ++++
.../pageStore/PerSessionPageStoreTest.java | 53 +++
.../wicket/versioning/InMemoryPageStore.java | 6 +-
15 files changed, 1020 insertions(+), 236 deletions(-)
----------------------------------------------------------------------
[7/9] git commit: WICKET-5527 Inefficient
DefaultPageStore.SerializedPagesCache
Posted by mg...@apache.org.
WICKET-5527 Inefficient DefaultPageStore.SerializedPagesCache
Move the logic for updating PageValue's access time in its own #touch() method
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/2380d65b
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/2380d65b
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/2380d65b
Branch: refs/heads/master
Commit: 2380d65b813143073dafdc57eb66270f087966af
Parents: 4ae0fb1
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Tue Mar 11 14:52:11 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Tue Mar 11 14:52:11 2014 +0200
----------------------------------------------------------------------
.../wicket/pageStore/PerSessionPageStore.java | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/2380d65b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
index eaff550..632cea9 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/PerSessionPageStore.java
@@ -104,7 +104,15 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
private PageValue(int pageId)
{
this.pageId = pageId;
- this.accessTime = System.nanoTime();
+ touch();
+ }
+
+ /**
+ * Updates the access time with the current time
+ */
+ private void touch()
+ {
+ accessTime = System.nanoTime();
}
@Override
@@ -239,15 +247,12 @@ public class PerSessionPageStore extends AbstractCachingPageStore<IManageablePag
if (pages != null)
{
PageValue sample = new PageValue(pageId);
- Iterator<Map.Entry<PageValue,IManageablePage>> iterator = pages.entrySet().iterator();
- while (iterator.hasNext())
+ for (Map.Entry<PageValue, IManageablePage> entry : pages.entrySet())
{
- Map.Entry<PageValue, IManageablePage> entry = iterator.next();
-
if (sample.equals(entry.getKey()))
{
// touch the entry
- entry.getKey().accessTime = System.nanoTime();
+ entry.getKey().touch();
result = entry.getValue();
break;
}