Skip to content

Instantly share code, notes, and snippets.

@benbai123
Created November 7, 2013 02:25
Show Gist options
  • Select an option

  • Save benbai123/7347907 to your computer and use it in GitHub Desktop.

Select an option

Save benbai123/7347907 to your computer and use it in GitHub Desktop.
desktop cache patch
package test;
import org.zkoss.zk.ui.WebApp;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.sys.SessionCtrl;
import org.zkoss.zk.ui.sys.DesktopCache;
import org.zkoss.zk.ui.sys.DesktopCacheProvider;
public class CustomSessionDesktopCacheProvider implements DesktopCacheProvider {
private WebApp _wapp;
//-- DesktopCacheProvider --//
public DesktopCache getDesktopCache(Session sess) {
final SessionCtrl sessCtrl = (SessionCtrl)sess;
DesktopCache dc = sessCtrl.getDesktopCache();
if (dc == null) {
synchronized (this) {
dc = sessCtrl.getDesktopCache();
if (dc == null) {
dc = new CustomSimpleDesktopCache(_wapp.getConfiguration());
sessCtrl.setDesktopCache(dc);
}
}
}
return dc;
}
public void sessionDestroyed(Session sess) {
final SessionCtrl sessCtrl = (SessionCtrl)sess;
final DesktopCache dc = sessCtrl.getDesktopCache();
if (dc != null) {
sessCtrl.setDesktopCache(null);
dc.stop();
}
}
/** Invokes {@link #getDesktopCache}'s {@link DesktopCache#sessionWillPassivate}.
*/
public void sessionWillPassivate(Session sess) {
final DesktopCache dc = ((SessionCtrl)sess).getDesktopCache();
if (dc != null) dc.sessionWillPassivate(sess);
}
/** Invokes {@link #getDesktopCache}'s {@link DesktopCache#sessionDidActivate}.
*/
public void sessionDidActivate(Session sess) {
final DesktopCache dc = ((SessionCtrl)sess).getDesktopCache();
if (dc != null) dc.sessionDidActivate(sess);
}
public void start(WebApp wapp) {
_wapp = wapp;
}
public void stop(WebApp wapp) {
_wapp = null;
}
}
package test;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import org.zkoss.util.CacheMap;
import org.zkoss.util.logging.Log;
import org.zkoss.zk.ui.WebApp;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.ComponentNotFoundException;
import org.zkoss.zk.ui.util.Configuration;
import org.zkoss.zk.ui.util.Monitor;
import org.zkoss.zk.ui.util.DesktopRecycle;
import org.zkoss.zk.ui.sys.DesktopCache;
import org.zkoss.zk.ui.sys.DesktopCtrl;
import org.zkoss.zk.ui.sys.WebAppCtrl;
public class CustomSimpleDesktopCache implements DesktopCache, java.io.Serializable {
private static final Log log = Log.lookup(CustomSimpleDesktopCache.class);
private static final long serialVersionUID = 20060622L;
/** Used to purge obsolete desktops. */
private final Cache _desktops;
/** The next available key. */
private int _nextKey;
//to reduce the chance that two browsers with the same desktop ID
//it is possible if we re-boot the server
public CustomSimpleDesktopCache(Configuration config) {
_desktops = new Cache(config);
if (!config.isRepeatUuid())
_nextKey = ((int)System.currentTimeMillis()) & 0xffff;
}
//-- DesktopCache --//
public int getNextKey() {
synchronized (this) {
return _nextKey++;
}
}
public Desktop getDesktopIfAny(String desktopId) {
synchronized (_desktops) {
final boolean old = _desktops.disableExpunge(true);
try {
return (Desktop)_desktops.get(desktopId);
} finally {
_desktops.disableExpunge(old);
}
}
}
public Desktop getDesktop(String desktopId) {
final Desktop desktop;
synchronized (_desktops) {
desktop = (Desktop)_desktops.get(desktopId);
}
if (desktop == null)
throw new ComponentNotFoundException("Desktop not found: "+desktopId);
return desktop;
}
public void addDesktop(Desktop desktop) {
final boolean added;
final Object old;
synchronized (_desktops) {
old = _desktops.put(desktop.getId(), desktop);
}
if (old != null) {
_desktops.put(((Desktop)old).getId(), old); //recover
log.warning(
desktop == old ? "Register a desktop twice: "+desktop:
"Replicated ID: "+desktop+"; already used by "+old);
}
//if (log.debugable()) log.debug("After added, desktops: "+_desktops);
}
public void removeDesktop(Desktop desktop) {
final boolean oldexp = _desktops.disableExpunge(true);
try {
final Object old;
synchronized (_desktops) {
old = _desktops.remove(desktop.getId());
}
if (old == null)
log.warning("Removing non-existent desktop: "+desktop);
else
desktopDestroyed(desktop);
} finally {
_desktops.disableExpunge(oldexp);
}
}
private static void desktopDestroyed(Desktop desktop) {
final Session sess = desktop.getSession();
final WebApp wapp = desktop.getWebApp();
((DesktopCtrl)desktop).invokeDesktopCleanups();
final Configuration config = wapp.getConfiguration();
config.invokeDesktopCleanups(desktop);
//Feature 1767347: call DesktopCleanup before desktopDestroyed
//such that app dev has a chance to manipulate the desktop
((WebAppCtrl)wapp).getUiEngine().desktopDestroyed(desktop);
final Monitor monitor = desktop.getWebApp().getConfiguration().getMonitor();
if (monitor != null) {
try {
monitor.desktopDestroyed(desktop);
} catch (Throwable ex) {
log.error(ex);
}
}
final DesktopRecycle dtrc = config.getDesktopRecycle();
if (dtrc != null) {
try {
dtrc.afterRemove(sess, desktop);
} catch (Throwable ex) {
log.error(ex);
}
}
}
/** Invokes {@link DesktopCtrl#sessionWillPassivate} for each
* desktops it cached.
*/
public void sessionWillPassivate(Session sess) {
synchronized (_desktops) {
final boolean old = _desktops.disableExpunge(true);
try {
for (Iterator it = _desktops.values().iterator(); it.hasNext();)
((DesktopCtrl)it.next()).sessionWillPassivate(sess);
} finally {
_desktops.disableExpunge(old);
}
}
}
/** Invokes {@link DesktopCtrl#sessionDidActivate} for each
* desktops it cached.
*/
public void sessionDidActivate(Session sess) {
synchronized (_desktops) {
final boolean old = _desktops.disableExpunge(true);
try {
for (Iterator it = _desktops.values().iterator(); it.hasNext();)
((DesktopCtrl)it.next()).sessionDidActivate(sess);
} finally {
_desktops.disableExpunge(old);
}
}
}
public void stop() {
synchronized (_desktops) {
if (log.debugable()) log.debug("Invalidated and remove: "+_desktops);
final boolean old = _desktops.disableExpunge(true);
try {
for (Iterator it = new ArrayList(_desktops.values()).iterator();
it.hasNext();) {
desktopDestroyed((Desktop)it.next());
}
_desktops.clear();
} finally {
_desktops.disableExpunge(old);
}
}
}
/** Holds desktops. */
private static class Cache extends CacheMap { //serializable
private static final long serialVersionUID = -4202264723649116880L;
private AtomicBoolean _expungeDisabled = new AtomicBoolean(false);
private Cache(Configuration config) {
super(16);
int v = config.getSessionMaxDesktops();
setMaxSize(v >= 0 ? v: Integer.MAX_VALUE / 4);
v = config.getDesktopMaxInactiveInterval();
setLifetime(v >= 0 ? v * 1000: Integer.MAX_VALUE / 4);
}
synchronized private boolean disableExpunge(boolean disable) {
return _expungeDisabled.getAndSet(disable);
}
protected boolean shallExpunge() {
return !_expungeDisabled.get()
&& (super.shallExpunge()
|| sizeWithoutExpunge() > (getMaxSize() << 2));
//1) disable expunge if serialization/activation
//2) to minimize memory use, expunge even if no GC
}
protected int canExpunge(Value v) {
if (((Desktop)v.getValue()).getExecution() != null)
return EXPUNGE_NO|EXPUNGE_CONTINUE;
return super.canExpunge(v);
}
protected void onExpunge(Value v) {
super.onExpunge(v);
desktopDestroyed((Desktop)v.getValue());
if (log.debugable()) log.debug("Expunge desktop: "+v.getValue());
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
final boolean old = _expungeDisabled.getAndSet(true);
try {
s.defaultReadObject();
} finally {
_expungeDisabled.getAndSet(old);
}
}
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
final boolean old = _expungeDisabled.getAndSet(true);
try {
s.defaultWriteObject();
} finally {
_expungeDisabled.getAndSet(old);
}
}
}
}
<zk>
<system-config>
<cache-provider-class>test.CustomSessionDesktopCacheProvider</cache-provider-class>
</system-config>
</zk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment