Integrate Upstream r 1862/63: purge all purgable caches from Cache Table Browser
git-svn-id: https://svn.libreccm.org/ccm/trunk@142 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
1ef9fee384
commit
40428d8a99
|
|
@ -25,7 +25,9 @@ import com.arsdigita.bebop.util.Traversal;
|
||||||
import com.arsdigita.dispatcher.DispatcherHelper;
|
import com.arsdigita.dispatcher.DispatcherHelper;
|
||||||
import com.arsdigita.developersupport.DeveloperSupport;
|
import com.arsdigita.developersupport.DeveloperSupport;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.util.Assert;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
import com.arsdigita.web.ParameterMap;
|
import com.arsdigita.web.ParameterMap;
|
||||||
|
import com.arsdigita.web.RedirectSignal;
|
||||||
import com.arsdigita.web.URL;
|
import com.arsdigita.web.URL;
|
||||||
import com.arsdigita.web.Web;
|
import com.arsdigita.web.Web;
|
||||||
import com.arsdigita.xml.Element;
|
import com.arsdigita.xml.Element;
|
||||||
|
|
@ -406,16 +408,6 @@ public class PageState {
|
||||||
return m_response;
|
return m_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the page component with index i from the page model.
|
|
||||||
*
|
|
||||||
* @pre (i>=0) && (i < size())
|
|
||||||
* @post return != null
|
|
||||||
*/
|
|
||||||
private Component getComponent(int i) {
|
|
||||||
return m_page.getComponent(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The index of a component in the page model
|
* The index of a component in the page model
|
||||||
*
|
*
|
||||||
|
|
@ -496,7 +488,7 @@ public class PageState {
|
||||||
*/
|
*/
|
||||||
public void setVisible(final Component c, final boolean v) {
|
public void setVisible(final Component c, final boolean v) {
|
||||||
if (Assert.isEnabled()) {
|
if (Assert.isEnabled()) {
|
||||||
Assert.truth(getPage().stateContains(c),
|
Assert.isTrue(getPage().stateContains(c),
|
||||||
"Component" + c + " is not registered on Page " +
|
"Component" + c + " is not registered on Page " +
|
||||||
getPage());
|
getPage());
|
||||||
}
|
}
|
||||||
|
|
@ -703,7 +695,7 @@ public class PageState {
|
||||||
* @pre c == null || getPage().stateContains(c)
|
* @pre c == null || getPage().stateContains(c)
|
||||||
*/
|
*/
|
||||||
public void setControlEvent(Component c, String name, String value) {
|
public void setControlEvent(Component c, String name, String value) {
|
||||||
Assert.assertTrue(c == null || getPage().stateContains(c),
|
Assert.isTrue(c == null || getPage().stateContains(c),
|
||||||
"c == null || getPage().stateContains(c)");
|
"c == null || getPage().stateContains(c)");
|
||||||
if ( m_grabbingComponent != null && m_grabbingComponent != c ) {
|
if ( m_grabbingComponent != null && m_grabbingComponent != c ) {
|
||||||
throw new IllegalStateException
|
throw new IllegalStateException
|
||||||
|
|
@ -1070,4 +1062,22 @@ public class PageState {
|
||||||
+ "}";
|
+ "}";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the control event then redirect to the new page state.
|
||||||
|
*
|
||||||
|
* @param isCommitRequested indicates if a commit required before the redirect
|
||||||
|
*
|
||||||
|
* @throws RedirectSignal to the new page state
|
||||||
|
*
|
||||||
|
* @see RedirectSignal#RedirectSignal(String, boolean)
|
||||||
|
*/
|
||||||
|
public void redirectWithoutControlEvent(boolean isCommitRequested) {
|
||||||
|
clearControlEvent();
|
||||||
|
try {
|
||||||
|
throw new RedirectSignal(stateAsURL(), true);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new UncheckedWrapperException(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ public class CacheServlet extends HttpServlet {
|
||||||
private static final String ID = "id";
|
private static final String ID = "id";
|
||||||
private static final String KEY = "key";
|
private static final String KEY = "key";
|
||||||
private static final String HASH = "hash";
|
private static final String HASH = "hash";
|
||||||
|
private static final String REMOVEALL = "removeAll";
|
||||||
|
|
||||||
// If you change this, make sure that web.xml is changed as well
|
// If you change this, make sure that web.xml is changed as well
|
||||||
static final String SERVLET_URL = "/expireCache";
|
static final String SERVLET_URL = "/expireCache";
|
||||||
|
|
@ -74,15 +75,42 @@ public class CacheServlet extends HttpServlet {
|
||||||
protected void doGet( HttpServletRequest req, HttpServletResponse res ) {
|
protected void doGet( HttpServletRequest req, HttpServletResponse res ) {
|
||||||
String id = req.getParameter( ID );
|
String id = req.getParameter( ID );
|
||||||
String key = req.getParameter( KEY );
|
String key = req.getParameter( KEY );
|
||||||
|
String removeAll = req.getParameter( REMOVEALL );
|
||||||
|
|
||||||
if (s_log.isInfoEnabled()) {
|
if (s_log.isInfoEnabled()) {
|
||||||
s_log.info("Got remove request from " + req.getRemoteHost());
|
s_log.info("Got remove request from " + req.getRemoteHost());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == null || key == null) {
|
if (id != null && key != null){
|
||||||
return;
|
//normal expire cache entry request
|
||||||
|
if (s_log.isInfoEnabled()) {
|
||||||
|
s_log.info("Got remove request from " + req.getRemoteHost());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String hash = req.getParameter( HASH );
|
||||||
|
expireCacheEntry(id, key, hash);
|
||||||
|
} else if (id != null && key == null && removeAll != null) {
|
||||||
|
//purge a single cache request
|
||||||
|
if (s_log.isInfoEnabled()) {
|
||||||
|
s_log.info("Got remove all entries request from " + req.getRemoteHost());
|
||||||
|
}
|
||||||
|
if(removeAll.equals("true")){
|
||||||
|
removeCacheEntries(id);
|
||||||
|
}
|
||||||
|
} else if (id == null && key == null && removeAll != null) {
|
||||||
|
//purge all caches request
|
||||||
|
if (s_log.isInfoEnabled()) {
|
||||||
|
s_log.info("Got remove all cache request from " + req.getRemoteHost());
|
||||||
|
}
|
||||||
|
if(removeAll.equals("true")){
|
||||||
|
removeAllCache();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s_log.error("Got an invalid cache request from " + req.getRemoteHost());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void expireCacheEntry(String id, String key, String hash) {
|
||||||
id = URLDecoder.decode(id);
|
id = URLDecoder.decode(id);
|
||||||
key = URLDecoder.decode(key);
|
key = URLDecoder.decode(key);
|
||||||
|
|
||||||
|
|
@ -94,7 +122,6 @@ public class CacheServlet extends HttpServlet {
|
||||||
|
|
||||||
s_log.debug("Removing " + key + " from cache " + id);
|
s_log.debug("Removing " + key + " from cache " + id);
|
||||||
|
|
||||||
final String hash = req.getParameter( HASH );
|
|
||||||
final Integer hashCode = getHashCode(hash);
|
final Integer hashCode = getHashCode(hash);
|
||||||
if (hashCode == null) {
|
if (hashCode == null) {
|
||||||
// unconditionally remove
|
// unconditionally remove
|
||||||
|
|
@ -104,6 +131,25 @@ public class CacheServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void removeCacheEntries(String id) {
|
||||||
|
id = URLDecoder.decode(id);
|
||||||
|
final CacheTable cache = CacheTable.getCache( id );
|
||||||
|
if (cache == null) {
|
||||||
|
s_log.debug("No cache with id " + id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_log.debug("Removing all entries from cache " + id);
|
||||||
|
// unconditionally remove
|
||||||
|
cache.removeAllEntriesLocally();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeAllCache() {
|
||||||
|
s_log.debug("Removing all Cache tables");
|
||||||
|
// unconditionally remove all
|
||||||
|
CacheTable.removeAllCacheTablesLocally();
|
||||||
|
}
|
||||||
|
|
||||||
private Integer getHashCode(final String hash) {
|
private Integer getHashCode(final String hash) {
|
||||||
if (hash == null) {
|
if (hash == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -135,6 +181,32 @@ public class CacheServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remote all entries from all purge-able tables in the peer's.
|
||||||
|
*
|
||||||
|
* The fact that there is no ID parameter tells the
|
||||||
|
* peers to purge all cache tables.
|
||||||
|
*/
|
||||||
|
static void removeAllFromPeers() {
|
||||||
|
final ParameterMap params = new ParameterMap();
|
||||||
|
params.setParameter(REMOVEALL, "true");
|
||||||
|
|
||||||
|
notifyPeers(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remote all entries from the peer's cache table with an id of cacheID.
|
||||||
|
*
|
||||||
|
* @param cacheID id of the cache table to purge
|
||||||
|
*/
|
||||||
|
static void removeAllEntriesFromPeersTable(String cacheID) {
|
||||||
|
final ParameterMap params = new ParameterMap();
|
||||||
|
params.setParameter(ID, cacheID);
|
||||||
|
params.setParameter(REMOVEALL, "true");
|
||||||
|
|
||||||
|
notifyPeers(params);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sometimes we need to remove entries only from peer webservers.
|
* Sometimes we need to remove entries only from peer webservers.
|
||||||
*/
|
*/
|
||||||
|
|
@ -159,6 +231,10 @@ public class CacheServlet extends HttpServlet {
|
||||||
private static void notifyPeers(final String id,
|
private static void notifyPeers(final String id,
|
||||||
final String key,
|
final String key,
|
||||||
final String hash) {
|
final String hash) {
|
||||||
|
notifyPeers(makeParameterMap(id, key, hash));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void notifyPeers(ParameterMap params) {
|
||||||
if (!Web.getConfig().getDeactivateCacheHostNotifications()) {
|
if (!Web.getConfig().getDeactivateCacheHostNotifications()) {
|
||||||
s_log.debug("about to notify peers");
|
s_log.debug("about to notify peers");
|
||||||
final Session session = SessionManager.getSession();
|
final Session session = SessionManager.getSession();
|
||||||
|
|
@ -174,7 +250,7 @@ public class CacheServlet extends HttpServlet {
|
||||||
f.set("currPort", new Integer(current.getPort()));
|
f.set("currPort", new Integer(current.getPort()));
|
||||||
while (hosts.next()) {
|
while (hosts.next()) {
|
||||||
final Host host = (Host) hosts.getDomainObject();
|
final Host host = (Host) hosts.getDomainObject();
|
||||||
notifyPeer(host, makeParameterMap(id, key, hash));
|
notifyPeer(host, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -237,11 +238,6 @@ public class CacheTable {
|
||||||
return purgeAllowed;
|
return purgeAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeLRUEntry() {
|
|
||||||
m_list.removeLRUEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A convenience wrapper around {@link #put(String, Object)}.
|
* A convenience wrapper around {@link #put(String, Object)}.
|
||||||
*
|
*
|
||||||
|
|
@ -425,6 +421,39 @@ public class CacheTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void removeAllEntriesLocally() {
|
||||||
|
m_list.clear();
|
||||||
|
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("removed all entries from cache table " + m_cacheID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeAllCacheTables() {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("remove all entries from all purge-able cache tables");
|
||||||
|
}
|
||||||
|
removeAllCacheTablesLocally();
|
||||||
|
CacheServlet.removeAllFromPeers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator over all CacheTables in the cache
|
||||||
|
* and clear all purge-able ones
|
||||||
|
*/
|
||||||
|
public static synchronized void removeAllCacheTablesLocally() {
|
||||||
|
for(Iterator it = s_caches.values().iterator(); it.hasNext(); ) {
|
||||||
|
CacheTable ct = (CacheTable)it.next();
|
||||||
|
if (ct.isPurgeAllowed()) {
|
||||||
|
ct.removeAll();
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("removed all entries from cache table " + ct.m_cacheID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p> Retrieves the object stored in cache. If no object by the
|
* <p> Retrieves the object stored in cache. If no object by the
|
||||||
* passed key can be found in cache (maybe because it's expired or
|
* passed key can be found in cache (maybe because it's expired or
|
||||||
|
|
@ -468,6 +497,7 @@ public class CacheTable {
|
||||||
String isShared(String tableID);
|
String isShared(String tableID);
|
||||||
boolean isPurgeAllowed(String tableID);
|
boolean isPurgeAllowed(String tableID);
|
||||||
void purge(String tableID);
|
void purge(String tableID);
|
||||||
|
void purgeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BrowserImpl implements Browser {
|
private static class BrowserImpl implements Browser {
|
||||||
|
|
@ -510,6 +540,10 @@ public class CacheTable {
|
||||||
table.removeAll();
|
table.removeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void purgeAll() {
|
||||||
|
CacheTable.removeAllCacheTables();
|
||||||
|
}
|
||||||
|
|
||||||
private static CacheTable getCacheTable(String tableID) {
|
private static CacheTable getCacheTable(String tableID) {
|
||||||
if ( tableID==null ) { throw new NullPointerException(); }
|
if ( tableID==null ) { throw new NullPointerException(); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,19 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.webdevsupport;
|
package com.arsdigita.webdevsupport;
|
||||||
|
|
||||||
import com.arsdigita.bebop.ControlLink;
|
|
||||||
import com.arsdigita.bebop.Label;
|
|
||||||
import com.arsdigita.bebop.PageState;
|
|
||||||
import com.arsdigita.bebop.SimpleContainer;
|
|
||||||
import com.arsdigita.bebop.Table;
|
|
||||||
import com.arsdigita.bebop.event.TableActionEvent;
|
|
||||||
import com.arsdigita.bebop.event.TableActionListener;
|
|
||||||
import com.arsdigita.bebop.table.TableModel;
|
|
||||||
import com.arsdigita.bebop.table.TableModelBuilder;
|
|
||||||
import com.arsdigita.caching.CacheTable;
|
|
||||||
import com.arsdigita.caching.CacheTable.TimestampedEntry;
|
|
||||||
import com.arsdigita.util.LockableImpl;
|
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -40,6 +27,23 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.ActionLink;
|
||||||
|
import com.arsdigita.bebop.ControlLink;
|
||||||
|
import com.arsdigita.bebop.Label;
|
||||||
|
import com.arsdigita.bebop.ListPanel;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.SimpleContainer;
|
||||||
|
import com.arsdigita.bebop.Table;
|
||||||
|
import com.arsdigita.bebop.event.ActionEvent;
|
||||||
|
import com.arsdigita.bebop.event.ActionListener;
|
||||||
|
import com.arsdigita.bebop.event.TableActionEvent;
|
||||||
|
import com.arsdigita.bebop.event.TableActionListener;
|
||||||
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
|
import com.arsdigita.bebop.table.TableModelBuilder;
|
||||||
|
import com.arsdigita.caching.CacheTable;
|
||||||
|
import com.arsdigita.caching.CacheTable.TimestampedEntry;
|
||||||
|
import com.arsdigita.util.LockableImpl;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vadim Nasardinov (vadimn@redhat.com)
|
* @author Vadim Nasardinov (vadimn@redhat.com)
|
||||||
|
|
@ -64,15 +68,27 @@ final class CacheTableBrowser extends SimpleContainer {
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
CacheTable.BROWSER.purge((String) ev.getRowKey());
|
CacheTable.BROWSER.purge((String) ev.getRowKey());
|
||||||
break;
|
ev.getPageState().redirectWithoutControlEvent(false);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void headSelected(TableActionEvent e) { }
|
public void headSelected(TableActionEvent e) {
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ActionLink purgeAllLink = new ActionLink("Purge all caches");
|
||||||
|
purgeAllLink.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
CacheTable.BROWSER.purgeAll();
|
||||||
|
e.getPageState().redirectWithoutControlEvent(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ListPanel container = new ListPanel(false);
|
||||||
|
container.add(purgeAllLink);
|
||||||
|
add(container);
|
||||||
|
|
||||||
add(m_listOfTables);
|
add(m_listOfTables);
|
||||||
add(m_tableContents);
|
add(m_tableContents);
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +153,11 @@ final class CacheTableBrowser extends SimpleContainer {
|
||||||
return String.valueOf(CacheTable.BROWSER.isShared(m_key));
|
return String.valueOf(CacheTable.BROWSER.isShared(m_key));
|
||||||
case 5:
|
case 5:
|
||||||
if (CacheTable.BROWSER.isPurgeAllowed(m_key)) {
|
if (CacheTable.BROWSER.isPurgeAllowed(m_key)) {
|
||||||
|
if (CacheTable.BROWSER.getCurrentSize(m_key) > 0) {
|
||||||
return new ControlLink(new Label("purge"));
|
return new ControlLink(new Label("purge"));
|
||||||
|
} else {
|
||||||
|
return new Label("(empty)");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return new Label("can't be purged");
|
return new Label("can't be purged");
|
||||||
}
|
}
|
||||||
|
|
@ -161,8 +181,6 @@ final class CacheTableBrowser extends SimpleContainer {
|
||||||
private final static String TABLE_ID_ATTR =
|
private final static String TABLE_ID_ATTR =
|
||||||
CacheTableContents.class.getName();
|
CacheTableContents.class.getName();
|
||||||
|
|
||||||
private String m_tableID;
|
|
||||||
|
|
||||||
public CacheTableContents() {
|
public CacheTableContents() {
|
||||||
super(new ModelBuilder(),
|
super(new ModelBuilder(),
|
||||||
new String[] { "Key", "Class", "Value", "Hits", "Hash code", "Timestamp" });
|
new String[] { "Key", "Class", "Value", "Hits", "Hash code", "Timestamp" });
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue