Merge "Issue #2968 improve efficiency by only compressing/serializing persisted objects once" into development
Former-commit-id:e7aed56884
[formerlye7aed56884
[formerly e2cd80cc4e2fbaaca7a8b34b6657a818d35cee4d]] Former-commit-id:e44d1143c0
Former-commit-id:c1e383f8bf
This commit is contained in:
commit
cfe82eb2c5
4 changed files with 104 additions and 55 deletions
|
@ -68,6 +68,7 @@ import com.raytheon.viz.ui.input.InputAdapter;
|
|||
* Feb 19, 2014 2751 bclement added check for closed session
|
||||
* Mar 05, 2014 2843 bsteffen Prevent exceptions on dispose.
|
||||
* Mar 06, 2014 2848 bclement only send to venue if non empty
|
||||
* Apr 08, 2014 2968 njensen Only serialize/compress persisted objects once
|
||||
*
|
||||
*
|
||||
* </pre>
|
||||
|
@ -213,24 +214,34 @@ public class CollaborationDispatcher extends Dispatcher {
|
|||
// when they close the view.
|
||||
return;
|
||||
}
|
||||
boolean immediateSend = true;
|
||||
if (eventObject instanceof ICreationEvent == false) {
|
||||
// Not a creation event, check event size. All creation events
|
||||
// are sent immediately to avoid false negatives
|
||||
try {
|
||||
byte[] data = CompressionUtil.compress(SerializationUtil
|
||||
.transformToThrift(eventObject));
|
||||
if (data.length > IMMEDIATE_SEND_SIZE) {
|
||||
immediateSend = false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Activator.statusHandler.handle(Priority.PROBLEM,
|
||||
"Error determing size of eventObject: "
|
||||
+ eventObject, e);
|
||||
}
|
||||
|
||||
boolean immediateSend = false;
|
||||
byte[] data = null;
|
||||
try {
|
||||
data = CompressionUtil.compress(SerializationUtil
|
||||
.transformToThrift(eventObject));
|
||||
} catch (Exception e) {
|
||||
Activator.statusHandler.handle(Priority.PROBLEM,
|
||||
"Error serializing eventObject: " + eventObject, e);
|
||||
return;
|
||||
}
|
||||
if (eventObject instanceof ICreationEvent
|
||||
|| data.length <= IMMEDIATE_SEND_SIZE) {
|
||||
/*
|
||||
* All creation events are sent immediately to avoid false
|
||||
* negatives. All events under a set size are also sent
|
||||
* immediately for optimal performance.
|
||||
*/
|
||||
immediateSend = true;
|
||||
}
|
||||
|
||||
final byte[] compressedEvent = data;
|
||||
final AbstractDispatchingObjectEvent toPersist = (AbstractDispatchingObjectEvent) eventObject;
|
||||
final boolean[] sendPersisted = new boolean[] { !immediateSend };
|
||||
/*
|
||||
* we will always persist events to the data service for clients
|
||||
* that join late
|
||||
*/
|
||||
persistPool.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -238,8 +249,12 @@ public class CollaborationDispatcher extends Dispatcher {
|
|||
synchronized (persistance) {
|
||||
if (!disposed) {
|
||||
IPersistedEvent event = persistance
|
||||
.persistEvent(toPersist);
|
||||
// If was no immediateSend, send now
|
||||
.persistEvent(toPersist,
|
||||
compressedEvent);
|
||||
/*
|
||||
* If it was not immediately sent, send
|
||||
* notification now that it's persisted
|
||||
*/
|
||||
if (sendPersisted[0]) {
|
||||
send(event);
|
||||
}
|
||||
|
@ -251,8 +266,14 @@ public class CollaborationDispatcher extends Dispatcher {
|
|||
}
|
||||
}
|
||||
});
|
||||
// Need to immediately send eventObject
|
||||
|
||||
if (immediateSend) {
|
||||
/*
|
||||
* Need to immediately send eventObject to get fast behavior on
|
||||
* connected clients. It will go through serialization again and
|
||||
* not be compressed, but since it's only small objects we don't
|
||||
* care.
|
||||
*/
|
||||
try {
|
||||
send(eventObject);
|
||||
} catch (RuntimeException e) {
|
||||
|
|
|
@ -79,6 +79,7 @@ import com.raytheon.uf.viz.remote.graphics.events.ICreationEvent;
|
|||
* Feb 25, 2014 2751 bclement fixed provider id path for webDAV
|
||||
* Feb 28, 2014 2756 bclement added auth, moved response code checks to response object
|
||||
* Mar 06, 2014 2826 njensen Fix spelling mistake
|
||||
* Apr 08, 2014 2968 njensen PersistedObject serialization efficiency improvement
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -178,8 +179,8 @@ public class CollaborationObjectEventStorage implements
|
|||
* (com.raytheon.uf.viz.remote.graphics.AbstractRemoteGraphicsEvent)
|
||||
*/
|
||||
@Override
|
||||
public IPersistedEvent persistEvent(AbstractDispatchingObjectEvent event)
|
||||
throws CollaborationException {
|
||||
public IPersistedEvent persistEvent(AbstractDispatchingObjectEvent event,
|
||||
byte[] eventData) throws CollaborationException {
|
||||
if (event instanceof ICreationEvent) {
|
||||
// TODO this is for pre 14.3 compatibility
|
||||
createFolder(String.valueOf(event.getObjectId()));
|
||||
|
@ -202,12 +203,18 @@ public class CollaborationObjectEventStorage implements
|
|||
+ event.getClass().getName() + ".obj";
|
||||
String eventObjectURL = sessionDataURL + objectPath;
|
||||
|
||||
/*
|
||||
* We will not set the event or compress the byte[] because the
|
||||
* underlying event has already been serialized and compressed by
|
||||
* the CollaborationDispatcher.
|
||||
*/
|
||||
CollaborationHttpPersistedObject persistObject = new CollaborationHttpPersistedObject();
|
||||
persistObject.persistTime = System.currentTimeMillis();
|
||||
persistObject.event = event;
|
||||
byte[] toPersist = CompressionUtil.compress(SerializationUtil
|
||||
.transformToThrift(persistObject));
|
||||
persistObject.setPersistTime(System.currentTimeMillis());
|
||||
persistObject.setEventAsCompressedBytes(eventData);
|
||||
byte[] toPersist = SerializationUtil
|
||||
.transformToThrift(persistObject);
|
||||
stats.log(event.getClass().getSimpleName(), toPersist.length, 0);
|
||||
|
||||
HttpPut put = createPut(eventObjectURL, toPersist);
|
||||
HttpClientResponse response = executeRequest(put);
|
||||
if (response.isSuccess() == false) {
|
||||
|
@ -284,10 +291,10 @@ public class CollaborationObjectEventStorage implements
|
|||
if (object == null) {
|
||||
// No object available
|
||||
return null;
|
||||
} else if (object.event != null) {
|
||||
stats.log(object.event.getClass().getSimpleName(), 0,
|
||||
} else if (object.getEvent() != null) {
|
||||
stats.log(object.getEvent().getClass().getSimpleName(), 0,
|
||||
object.dataSize);
|
||||
return object.event;
|
||||
return object.getEvent();
|
||||
} else {
|
||||
throw new CollaborationException(
|
||||
"Unable to deserialize persisted event into event object");
|
||||
|
@ -318,7 +325,7 @@ public class CollaborationObjectEventStorage implements
|
|||
CollaborationHttpPersistedObject dataObject = SerializationUtil
|
||||
.transformFromThrift(
|
||||
CollaborationHttpPersistedObject.class,
|
||||
CompressionUtil.uncompress(response.data));
|
||||
response.data);
|
||||
if (dataObject != null) {
|
||||
dataObject.dataSize = response.data.length;
|
||||
}
|
||||
|
@ -388,7 +395,7 @@ public class CollaborationObjectEventStorage implements
|
|||
.size()];
|
||||
int i = 0;
|
||||
for (CollaborationHttpPersistedObject object : objectEvents) {
|
||||
events[i++] = object.event;
|
||||
events[i++] = object.getEvent();
|
||||
}
|
||||
|
||||
return events;
|
||||
|
@ -570,7 +577,15 @@ public class CollaborationObjectEventStorage implements
|
|||
@DynamicSerializeElement
|
||||
private long persistTime;
|
||||
|
||||
/**
|
||||
* This will be serialized instead of the event. Provides better
|
||||
* efficiency than serializing the event itself since
|
||||
* CollaborationDispatcher is already handling the serialization and
|
||||
* compression.
|
||||
*/
|
||||
@DynamicSerializeElement
|
||||
private byte[] eventAsCompressedBytes;
|
||||
|
||||
private AbstractDispatchingObjectEvent event;
|
||||
|
||||
private long dataSize;
|
||||
|
@ -592,17 +607,32 @@ public class CollaborationObjectEventStorage implements
|
|||
|
||||
/**
|
||||
* @return the event
|
||||
* @throws CollaborationException
|
||||
* @throws SerializationException
|
||||
*/
|
||||
public AbstractDispatchingObjectEvent getEvent() {
|
||||
public AbstractDispatchingObjectEvent getEvent()
|
||||
throws CollaborationException {
|
||||
if (event == null && eventAsCompressedBytes != null) {
|
||||
try {
|
||||
event = SerializationUtil.transformFromThrift(
|
||||
AbstractDispatchingObjectEvent.class,
|
||||
CompressionUtil.uncompress(eventAsCompressedBytes));
|
||||
eventAsCompressedBytes = null;
|
||||
} catch (SerializationException e) {
|
||||
throw new CollaborationException(
|
||||
"Error deserializing event retrieved from collaboration data service",
|
||||
e);
|
||||
}
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param event
|
||||
* the event to set
|
||||
*/
|
||||
public void setEvent(AbstractDispatchingObjectEvent event) {
|
||||
this.event = event;
|
||||
public byte[] getEventAsCompressedBytes() {
|
||||
return eventAsCompressedBytes;
|
||||
}
|
||||
|
||||
public void setEventAsCompressedBytes(byte[] eventAsCompressedBytes) {
|
||||
this.eventAsCompressedBytes = eventAsCompressedBytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.raytheon.uf.viz.remote.graphics.events.AbstractDispatchingObjectEvent
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 20, 2012 mschenke Initial creation
|
||||
* Apr 08, 2014 2968 njensen Added byte[] data arg to persistEvent
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -41,8 +42,18 @@ import com.raytheon.uf.viz.remote.graphics.events.AbstractDispatchingObjectEvent
|
|||
|
||||
public interface IObjectEventPersistance {
|
||||
|
||||
public IPersistedEvent persistEvent(AbstractDispatchingObjectEvent event)
|
||||
throws CollaborationException;
|
||||
/**
|
||||
* Persists an event to the remote service
|
||||
*
|
||||
* @param event
|
||||
* the event to persist
|
||||
* @param data
|
||||
* the event transformed to bytes
|
||||
* @return an IPersistedEvent that references the remotely persisted event
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
public IPersistedEvent persistEvent(AbstractDispatchingObjectEvent event,
|
||||
byte[] data) throws CollaborationException;
|
||||
|
||||
public void dispose() throws CollaborationException;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ import java.nio.FloatBuffer;
|
|||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import com.raytheon.uf.common.util.BufferUtil;
|
||||
|
||||
/**
|
||||
* Slices a subset of a Buffer object
|
||||
*
|
||||
|
@ -38,6 +40,7 @@ import java.nio.ShortBuffer;
|
|||
* Nov 22, 2011 mschenke Initial creation
|
||||
* Jun 20, 2013 2122 mschenke Made work with slicing from data with
|
||||
* bounds not starting at 0,0
|
||||
* Apr 08, 2014 2968 njensen Use BufferUtil for duplicate()
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -67,7 +70,7 @@ public class BufferSlicer {
|
|||
"Data bounds defines region outside of buffer's total bounds");
|
||||
}
|
||||
|
||||
data = duplicate(data);
|
||||
data = BufferUtil.duplicate(data);
|
||||
int dataSize = dataBounds.width * dataBounds.height;
|
||||
if (dataSize == totalBounds.width * totalBounds.height) {
|
||||
return data;
|
||||
|
@ -87,22 +90,6 @@ public class BufferSlicer {
|
|||
}
|
||||
}
|
||||
|
||||
private static Buffer duplicate(Buffer data) {
|
||||
if (data instanceof ByteBuffer) {
|
||||
return ((ByteBuffer) data).duplicate();
|
||||
} else if (data instanceof ShortBuffer) {
|
||||
return ((ShortBuffer) data).duplicate();
|
||||
} else if (data instanceof IntBuffer) {
|
||||
return ((IntBuffer) data).duplicate();
|
||||
} else if (data instanceof FloatBuffer) {
|
||||
return ((FloatBuffer) data).duplicate();
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Unhandled buffer passed in: " + data != null ? data
|
||||
.getClass().getSimpleName() : null);
|
||||
}
|
||||
}
|
||||
|
||||
private static ByteBuffer slice(ByteBuffer data, Rectangle dataBounds,
|
||||
Rectangle totalBounds, int dataSize) {
|
||||
ByteBuffer newData = null;
|
||||
|
|
Loading…
Add table
Reference in a new issue