r7317 - in dumbhippo/trunk: openfire/src/plugins/hippo/src/java/com/dumbhippo/jive server/src/com/dumbhippo/dm server/src/com/dumbhippo/dm/fetch server/src/com/dumbhippo/dm/store server/tests/com/dumbhippo/dm



Author: otaylor
Date: 2008-02-15 13:39:02 -0600 (Fri, 15 Feb 2008)
New Revision: 7317

Modified:
   dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/XmppFetchVisitor.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/ChangeNotification.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/ChangeNotificationSet.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/ClientNotification.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/ClientNotificationSet.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/DMClient.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/ReadWriteSession.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/fetch/FetchVisitor.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/store/DMStore.java
   dumbhippo/trunk/server/src/com/dumbhippo/dm/store/StoreClient.java
   dumbhippo/trunk/server/tests/com/dumbhippo/dm/FetchResultVisitor.java
Log:
DMClient FetchVisitor FetchResultVisitor XmppFetchVisitor StoreClient:
 Send out deletions over XMPP so that clients can know to stop using
 a deleted resource.

ReadWriteSession ChangeNotificationSet ChangeNotification: Rename
 'removed' to 'deleted', maybe a bit clearer, and consistent with
 the choice for the wire protocol.


Modified: dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/XmppFetchVisitor.java
===================================================================
--- dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/XmppFetchVisitor.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/XmppFetchVisitor.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -30,6 +30,8 @@
 	private static final QName RESOURCE_ID_QNAME = QName.get("resourceId", SYSTEM_NAMESPACE);
 	private static final QName FETCH_QNAME = QName.get("fetch", SYSTEM_NAMESPACE);
 	private static final QName INDIRECT_QNAME = QName.get("indirect", SYSTEM_NAMESPACE);
+	private static final QName EVICTED_QNAME = QName.get("evicted", SYSTEM_NAMESPACE);
+	private static final QName DELETED_QNAME = QName.get("deleted", SYSTEM_NAMESPACE);
 	private static final QName TS_QNAME = QName.get("ts", SYSTEM_NAMESPACE);
 	private static final QName TYPE_QNAME = QName.get("type", SYSTEM_NAMESPACE);
 	private static final QName DEFAULT_CHILDREN_QNAME = QName.get("defaultChildren", SYSTEM_NAMESPACE);
@@ -137,4 +139,16 @@
 		element.addAttribute(UPDATE_QNAME, "clear");
 		element.addAttribute(TYPE_QNAME, propertyHolder.getTypeString());
 	}
+		
+	public <K, T extends DMObject<K>> void evictedResource(DMClassHolder<K, T> classHolder, K key) {
+		Element element = rootElement.addElement(createQName("resource", classHolder.getClassId()));
+		element.addAttribute(RESOURCE_ID_QNAME, classHolder.makeRelativeId(key));
+		element.addAttribute(EVICTED_QNAME, "true");
+	}
+
+	public <K, T extends DMObject<K>> void deletedResource(DMClassHolder<K, T> classHolder, K key) {
+		Element element = rootElement.addElement(createQName("resource", classHolder.getClassId()));
+		element.addAttribute(RESOURCE_ID_QNAME, classHolder.makeRelativeId(key));
+		element.addAttribute(DELETED_QNAME, "true");
+	}
 }

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/ChangeNotification.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/ChangeNotification.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/ChangeNotification.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -31,7 +31,7 @@
 	
 	private long[] feedTimestamps;
 	
-	private boolean removed;
+	private boolean deleted;
 
 	/**
 	 * DO NOT USE THIS CONSTRUCTOR DIRECTLY. Instead use model.makeChangeNotification(),
@@ -122,16 +122,16 @@
 		}
 	}
 
-	public void removed() {
-		removed = true;
+	public void deleted() {
+		deleted = true;
 	}
 	
 	public void resolveNotifications(DataModel model, ClientNotificationSet result) {
 		@SuppressWarnings("unchecked")
 		DMClassHolder<K,T> classHolder = (DMClassHolder<K,T>)model.getClassHolder(clazz);
 
-		if (removed)
-			model.getStore().evict(classHolder, key);			
+		if (deleted)
+			model.getStore().delete(classHolder, key, result);			
 		else
 			model.getStore().resolveNotifications(classHolder, key, propertyMask, result, matcher);
 	}

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/ChangeNotificationSet.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/ChangeNotificationSet.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/ChangeNotificationSet.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -74,9 +74,9 @@
 		notification.addFeedProperty(model, propertyName, itemTimestamp);
 	}
 
-	public <K, T extends DMObject<K>> void removed(DataModel model, Class<T> clazz, K key) {
+	public <K, T extends DMObject<K>> void deleted(DataModel model, Class<T> clazz, K key) {
 		ChangeNotification<K,T> notification = getNotification(model, clazz, key, null);
-		notification.removed();
+		notification.deleted();
 	}
 
 	public void setTimestamp(long timestamp) {

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/ClientNotification.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/ClientNotification.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/ClientNotification.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -38,6 +38,10 @@
 		notifications.add(new ObjectNotification<K,T>(key, fetch, propertyMask, childFetches, maxes));
 	}
 	
+	public <K, T extends DMObject<K>> void addDeletion(StoreKey<K,T> key) {
+		notifications.add(new ObjectNotification<K,T>(key));
+	}
+	
 	public StoreClient getClient() {
 		return client;
 	}
@@ -54,6 +58,7 @@
 
 	private static class ObjectNotification<K,T extends DMObject<K>> {
 		private StoreKey<K,T> key;
+		private boolean deleted;
 		private BoundFetch<K, ? super T> fetch;
 		private long propertyMask;
 		private BoundFetch<?,?>[] childFetches;
@@ -67,6 +72,11 @@
 			this.maxes = maxes;
 		}
 		
+		public ObjectNotification(StoreKey<K, T> key) {
+			this.key = key;
+			this.deleted = true;
+		}
+
 		private int getMax(FeedPropertyHolder<K,T,?,?> property, int propertyIndex) {
 			int max = -1;
 			if (maxes != null)
@@ -79,6 +89,11 @@
 		}
 		
 		public void visitNotification(DMSession session, FetchVisitor visitor) {
+			if (deleted) {
+				visitor.deletedResource(key.getClassHolder(), key.getKey());
+				return;
+			}
+			
 			T object;
 			try {
 				object = session.find(key);

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/ClientNotificationSet.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/ClientNotificationSet.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/ClientNotificationSet.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -24,8 +24,8 @@
 	static final private Logger logger = GlobalSetup.getLogger(ClientNotificationSet.class);
 	
 	private Map<StoreClient, ClientNotification> notifications;
-	
-	public <K, T extends DMObject<K>> void addNotification(StoreClient client, StoreKey<K,T> key, BoundFetch<K,? super T> fetch, long propertyMask, BoundFetch<?,?>[] childFetches, int[] maxes) {
+
+	private ClientNotification getNotification(StoreClient client) {
 		ClientNotification notification = null;
 		
 		if (notifications == null)
@@ -37,10 +37,20 @@
 			notification = new ClientNotification(client);
 			notifications.put(client, notification);
 		}
-		
+
+		return notification;
+	}
+	
+	public <K, T extends DMObject<K>> void addNotification(StoreClient client, StoreKey<K,T> key, BoundFetch<K,? super T> fetch, long propertyMask, BoundFetch<?,?>[] childFetches, int[] maxes) {
+		ClientNotification notification = getNotification(client);
 		notification.addObjectProperties(key, fetch, propertyMask, childFetches, maxes);
 	}
 	
+	public <K, T extends DMObject<K>> void addDeletion(StoreClient client, StoreKey<K,T> key) {
+		ClientNotification notification = getNotification(client);
+		notification.addDeletion(key);
+	}
+	
 	public Collection<ClientNotification> getNotifications() {
 		if (notifications != null)
 			return notifications.values();

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/DMClient.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/DMClient.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/DMClient.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -1,7 +1,6 @@
 package com.dumbhippo.dm;
 
 import com.dumbhippo.dm.fetch.FetchVisitor;
-import com.dumbhippo.dm.schema.DMClassHolder;
 import com.dumbhippo.dm.store.StoreClient;
 
 /**
@@ -32,7 +31,5 @@
 	
 	void endNotification(FetchVisitor visitor, long serial);
 	
-	<K,T extends DMObject<K>> void notifyEviction(DMClassHolder<K,T> classHolder, K key, long serial);
-	
 	void nullNotification(long serial);
 }

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/ReadWriteSession.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/ReadWriteSession.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/ReadWriteSession.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -116,7 +116,7 @@
 	 * @param key the key of the resource that was deleted
 	 */
 	public <K, T extends DMObject<K>> void removed(Class<T> clazz, K key) {
-		notificationSet.removed(model, clazz, key);
+		notificationSet.deleted(model, clazz, key);
 	}
 
 	/**

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/fetch/FetchVisitor.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/fetch/FetchVisitor.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/fetch/FetchVisitor.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -15,4 +15,8 @@
 	<KP,TP extends DMObject<KP>> void feedProperty(ResourcePropertyHolder<?,?,KP,TP> propertyHolder, KP key, long timestamp, boolean incremental);
 	<K,T extends DMObject<K>> void emptyProperty(DMPropertyHolder<K,T,?> propertyHolder);
 	void endResource();
+	
+	// These are used only for notifications
+	<K,T extends DMObject<K>> void evictedResource(DMClassHolder<K,T> classHolder, K key);	
+	<K,T extends DMObject<K>> void deletedResource(DMClassHolder<K,T> classHolder, K key);	
 }

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/store/DMStore.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/store/DMStore.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/store/DMStore.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -15,6 +15,7 @@
 import com.dumbhippo.dm.DMObject;
 import com.dumbhippo.dm.NotCachedException;
 import com.dumbhippo.dm.fetch.BoundFetch;
+import com.dumbhippo.dm.fetch.FetchVisitor;
 import com.dumbhippo.dm.schema.DMClassHolder;
 
 public class DMStore {
@@ -228,7 +229,7 @@
 		}
 	}
 	
-	public <K, T extends DMObject<K>> void evict(DMClassHolder<K,T> classHolder, K key) {
+	private <K, T extends DMObject<K>> void evictOrDelete(DMClassHolder<K,T> classHolder, K key, ClientNotificationSet notifications, boolean isDeletion) {
 		StoreNode<K,T> node = getNode(classHolder, key);
 		if (node == null)
 			return;
@@ -243,28 +244,46 @@
 			
 			client.removeRegistration(registration);
 			
-			// Note that allocating the serial at this point can allow late 
-			// eviction notices to happen. 
-			//
-			// 1. Node is evicted
-			// 2. Node is resurrected by a different thread, serial allocated
-			// 3. Eviction notice is sent with a later serial
-			//
-			// Which will cause clients to think that their registration was
-			// evicted when it wasn't. That's pretty harmless though - if the 
-			// client recovers as if the eviction really happened, it will 
-			// be a no-op, and if the client choooses not to recover, it should
-			// be able to handle the unexpected notifications later... clients
-			// should never count on *not* getting notifications.
-			//
-			// Allocating the serial before the eviction is worse, since the
-			// eviction happens but the client doesn't get notified. And allocating
-			// serials for all the clients atomically with the eviction would
-			// require some earth-spanning reader-writer lock which we don't
-			// want.
-			
-			client.notifyEviction(classHolder, key, client.allocateSerial());
+			if (isDeletion) {
+				notifications.addDeletion(client, node);
+			} else {
+				// Note that allocating the serial at this point can allow late 
+				// eviction notices to happen. 
+				//
+				// 1. Node is evicted
+				// 2. Node is resurrected by a different thread, serial allocated
+				// 3. Eviction notice is sent with a later serial
+				//
+				// Which will cause clients to think that their registration was
+				// evicted when it wasn't. That's pretty harmless though - if the 
+				// client recovers as if the eviction really happened, it will 
+				// be a no-op, and if the client choooses not to recover, it should
+				// be able to handle the unexpected notifications later... clients
+				// should never count on *not* getting notifications.
+				//
+				// Allocating the serial before the eviction is worse, since the
+				// eviction happens but the client doesn't get notified. And allocating
+				// serials for all the clients atomically with the eviction would
+				// require some earth-spanning reader-writer lock which we don't
+				// want.
+				
+				FetchVisitor visitor = client.beginNotification();
+				visitor.evictedResource(classHolder, key);
+				client.endNotification(visitor, client.allocateSerial());
+			}
+	
 			registration.getClient().removeRegistration(registration);
 		}
 	}
+	
+	public <K, T extends DMObject<K>> void evict(DMClassHolder<K,T> classHolder, K key) {
+		evictOrDelete(classHolder, key, null, false);
+	}
+	
+	public <K, T extends DMObject<K>> void delete(DMClassHolder<K,T> classHolder, K key, ClientNotificationSet notifications) {
+		if (notifications == null)
+			throw new NullPointerException("ClientNotificationSet must be provided");
+		
+		evictOrDelete(classHolder, key, notifications, true);
+	}
 }

Modified: dumbhippo/trunk/server/src/com/dumbhippo/dm/store/StoreClient.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/dm/store/StoreClient.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/src/com/dumbhippo/dm/store/StoreClient.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -6,10 +6,8 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import com.dumbhippo.dm.DMClient;
-import com.dumbhippo.dm.DMObject;
 import com.dumbhippo.dm.DMViewpoint;
 import com.dumbhippo.dm.fetch.FetchVisitor;
-import com.dumbhippo.dm.schema.DMClassHolder;
 
 public class StoreClient implements DMClient {
 	private DMClient client;
@@ -75,10 +73,6 @@
 		client.endNotification(visitor, serial);
 	}
 
-	public <K, T extends DMObject<K>> void notifyEviction(DMClassHolder<K,T> classHolder, K key, long serial) {
-		client.notifyEviction(classHolder, key, serial);
-	}
-
 	public void nullNotification(long serial) {
 		client.nullNotification(serial);
 	}

Modified: dumbhippo/trunk/server/tests/com/dumbhippo/dm/FetchResultVisitor.java
===================================================================
--- dumbhippo/trunk/server/tests/com/dumbhippo/dm/FetchResultVisitor.java	2008-02-13 18:00:50 UTC (rev 7316)
+++ dumbhippo/trunk/server/tests/com/dumbhippo/dm/FetchResultVisitor.java	2008-02-15 19:39:02 UTC (rev 7317)
@@ -56,4 +56,12 @@
 	public void emptyProperty(DMPropertyHolder propertyHolder) {
 		// FIXME: test this
 	}
+	
+	public <K,T extends DMObject<K>> void evictedResource(DMClassHolder<K,T> classHolder, K key) {
+		// FIXME: test this
+	}
+
+	public <K,T extends DMObject<K>> void deletedResource(DMClassHolder<K,T> classHolder, K key) {
+		// FIXME: test this
+	}
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]