Search in sources :

Example 1 with BroadcastMessage

use of org.atmosphere.cache.BroadcastMessage in project atmosphere by Atmosphere.

the class DefaultBroadcaster method deliverPush.

protected void deliverPush(Deliver deliver, boolean rec) {
    recentActivity.set(true);
    String prevMessage = deliver.message.toString();
    if (rec && !delayedBroadcast.isEmpty()) {
        Iterator<Deliver> i = delayedBroadcast.iterator();
        StringBuilder b = new StringBuilder();
        while (i.hasNext()) {
            Deliver e = i.next();
            e.future.cancel(true);
            try {
                // Append so we do a single flush
                if (e.message instanceof String && deliver.message instanceof String) {
                    b.append(e.message);
                } else {
                    deliverPush(e, false);
                }
            } finally {
                i.remove();
            }
        }
        if (b.length() > 0) {
            deliver.message = b.append(deliver.message).toString();
        }
    }
    Object finalMsg = callable(deliver.message);
    if (finalMsg == null) {
        logger.error("Callable exception. Please catch all exceptions from your callable. Message {} will be lost and all AtmosphereResource " + "associated with this Broadcaster resumed.", deliver.message);
        entryDone(deliver.future);
        switch(deliver.type) {
            case ALL:
                synchronized (resources) {
                    for (AtmosphereResource r : resources) {
                        if (Utils.resumableTransport(r.transport()))
                            try {
                                r.resume();
                            } catch (Throwable t) {
                                logger.trace("resumeAll", t);
                            }
                    }
                }
                break;
            case RESOURCE:
                deliver.resource.resume();
                break;
            case SET:
                for (AtmosphereResource r : deliver.resources) {
                    r.resume();
                }
                break;
        }
        return;
    }
    notifyOnMessage(deliver);
    Object prevM = deliver.originalMessage;
    deliver.originalMessage = (deliver.originalMessage != deliver.message ? callable(deliver.originalMessage) : finalMsg);
    if (deliver.originalMessage == null) {
        logger.trace("Broadcasted message was null {}", prevM);
        entryDone(deliver.future);
        return;
    }
    deliver.message = finalMsg;
    Map<String, CacheMessage> cacheForSet = deliver.type == Deliver.TYPE.SET ? new HashMap<String, CacheMessage>() : null;
    // We cache first, and if the broadcast succeed, we will remove it.
    switch(deliver.type) {
        case ALL:
            deliver.cache = bc.getBroadcasterCache().addToCache(getID(), BroadcasterCache.NULL, new BroadcastMessage(deliver.originalMessage));
            break;
        case RESOURCE:
            deliver.cache = bc.getBroadcasterCache().addToCache(getID(), deliver.resource.uuid(), new BroadcastMessage(deliver.originalMessage));
            break;
        case SET:
            for (AtmosphereResource r : deliver.resources) {
                cacheForSet.put(r.uuid(), bc.getBroadcasterCache().addToCache(getID(), r.uuid(), new BroadcastMessage(deliver.originalMessage)));
            }
            break;
    }
    if (resources.isEmpty()) {
        logger.trace("No resource available for {} and message {}", getID(), finalMsg);
        entryDone(deliver.future);
        if (cacheForSet != null) {
            cacheForSet.clear();
        }
        return;
    }
    try {
        if (logger.isTraceEnabled()) {
            for (AtmosphereResource r : resources) {
                logger.trace("AtmosphereResource {} available for {}", r.uuid(), deliver.message);
            }
        }
        boolean hasFilters = bc.hasPerRequestFilters();
        Object beforeProcessingMessage = deliver.message;
        switch(deliver.type) {
            case ALL:
                AtomicInteger count = new AtomicInteger(resources.size());
                for (AtmosphereResource r : resources) {
                    deliver.message = beforeProcessingMessage;
                    boolean deliverMessage = perRequestFilter(r, deliver);
                    if (endBroadcast(deliver, r, deliver.cache, deliverMessage))
                        continue;
                    if (deliver.writeLocally) {
                        queueWriteIO(r, hasFilters ? new Deliver(r, deliver) : deliver, count);
                    }
                }
                break;
            case RESOURCE:
                boolean deliverMessage = perRequestFilter(deliver.resource, deliver);
                if (endBroadcast(deliver, deliver.resource, deliver.cache, deliverMessage))
                    return;
                if (deliver.writeLocally) {
                    queueWriteIO(deliver.resource, deliver, new AtomicInteger(1));
                }
                break;
            case SET:
                count = new AtomicInteger(deliver.resources.size());
                for (AtmosphereResource r : deliver.resources) {
                    deliver.message = beforeProcessingMessage;
                    deliverMessage = perRequestFilter(r, deliver);
                    CacheMessage cacheMsg = cacheForSet.remove(r.uuid());
                    if (endBroadcast(deliver, r, cacheMsg, deliverMessage))
                        continue;
                    if (deliver.writeLocally) {
                        queueWriteIO(r, new Deliver(r, deliver, cacheMsg), count);
                    }
                }
                break;
        }
        deliver.message = prevMessage;
    } catch (InterruptedException ex) {
        logger.debug(ex.getMessage(), ex);
        if (cacheForSet != null) {
            cacheForSet.clear();
        }
    }
}
Also used : CacheMessage(org.atmosphere.cache.CacheMessage) BroadcastMessage(org.atmosphere.cache.BroadcastMessage) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Example 2 with BroadcastMessage

use of org.atmosphere.cache.BroadcastMessage in project atmosphere by Atmosphere.

the class BroadcasterCacheTest method testCache.

@Test
public void testCache() throws ExecutionException, InterruptedException, ServletException {
    broadcaster.getBroadcasterConfig().setBroadcasterCache(new AbstractBroadcasterCache() {

        @Override
        public CacheMessage addToCache(String id, String uuid, BroadcastMessage e) {
            CacheMessage c = put(e, System.nanoTime(), uuid, broadcaster.getID());
            cachedMessage.set(messages);
            return c;
        }

        @Override
        public List<Object> retrieveFromCache(String id, String uuid) {
            return Collections.<Object>emptyList();
        }
    }).getBroadcasterCache().inspector(new BroadcasterCacheInspector() {

        @Override
        public boolean inspect(BroadcastMessage message) {
            return true;
        }
    });
    broadcaster.broadcast("foo", ar).get();
    assertEquals(cachedMessage.get().size(), 0);
}
Also used : CacheMessage(org.atmosphere.cache.CacheMessage) AbstractBroadcasterCache(org.atmosphere.cache.AbstractBroadcasterCache) BroadcastMessage(org.atmosphere.cache.BroadcastMessage) List(java.util.List) BroadcasterCacheInspector(org.atmosphere.cache.BroadcasterCacheInspector) Test(org.testng.annotations.Test)

Example 3 with BroadcastMessage

use of org.atmosphere.cache.BroadcastMessage in project atmosphere by Atmosphere.

the class BroadcasterCacheTest method testEmptyCache.

@Test
public void testEmptyCache() throws ExecutionException, InterruptedException, ServletException {
    final CountDownLatch latch = new CountDownLatch(1);
    broadcaster.getBroadcasterConfig().setBroadcasterCache(new AbstractBroadcasterCache() {

        @Override
        public CacheMessage addToCache(String id, String uuid, BroadcastMessage e) {
            CacheMessage c = put(e, System.nanoTime(), uuid, broadcaster.getID());
            cachedMessage.set(messages);
            latch.countDown();
            return c;
        }

        @Override
        public List<Object> retrieveFromCache(String id, String uuid) {
            return Collections.<Object>emptyList();
        }
    }).getBroadcasterCache().inspector(new BroadcasterCacheInspector() {

        @Override
        public boolean inspect(BroadcastMessage message) {
            return true;
        }
    });
    broadcaster.broadcast("foo", ar);
    latch.await(10, TimeUnit.SECONDS);
    assertEquals(cachedMessage.get().size(), 1);
}
Also used : CacheMessage(org.atmosphere.cache.CacheMessage) AbstractBroadcasterCache(org.atmosphere.cache.AbstractBroadcasterCache) BroadcastMessage(org.atmosphere.cache.BroadcastMessage) List(java.util.List) CountDownLatch(java.util.concurrent.CountDownLatch) BroadcasterCacheInspector(org.atmosphere.cache.BroadcasterCacheInspector) Test(org.testng.annotations.Test)

Example 4 with BroadcastMessage

use of org.atmosphere.cache.BroadcastMessage in project atmosphere by Atmosphere.

the class DefaultBroadcaster method checkCachedAndPush.

protected boolean checkCachedAndPush(final AtmosphereResource r, final AtmosphereResourceEvent e) {
    boolean cache = retrieveTrackedBroadcast(r, e);
    if (!cache)
        return false;
    if (!((List) e.getMessage()).isEmpty()) {
        logger.debug("Sending cached message {} to {}", e.getMessage(), r.uuid());
        List<Object> cacheMessages = (List) e.getMessage();
        BroadcasterFuture<Object> f = new BroadcasterFuture<Object>(e.getMessage(), 1);
        LinkedList<Object> filteredMessage = new LinkedList<Object>();
        LinkedList<Object> filteredMessageClone = null;
        Deliver deliver;
        Object newMessage;
        for (Object o : cacheMessages) {
            newMessage = filter(o);
            if (newMessage == null) {
                continue;
            }
            deliver = new Deliver(newMessage, r, f, o);
            // Can be aborted by a Filter
            if (!perRequestFilter(r, deliver)) {
                continue;
            }
            if (deliver.message != null) {
                filteredMessage.addLast(deliver.message);
            }
        }
        if (filteredMessage.isEmpty()) {
            return false;
        }
        e.setMessage(filteredMessage);
        final boolean willBeResumed = Utils.resumableTransport(r.transport());
        if (willBeResumed) {
            filteredMessageClone = (LinkedList<Object>) filteredMessage.clone();
        }
        List<AtmosphereResourceEventListener> listeners = willBeResumed ? new ArrayList() : EMPTY_LISTENERS;
        AtmosphereResourceImpl rImpl = AtmosphereResourceImpl.class.cast(r);
        if (willBeResumed && !rImpl.atmosphereResourceEventListener().isEmpty()) {
            listeners.addAll(rImpl.atmosphereResourceEventListener());
        }
        // Must make sure execute only one thread
        synchronized (rImpl) {
            try {
                rImpl.getRequest().setAttribute(CACHED, "true");
                prepareInvokeOnStateChange(r, e);
            } catch (Throwable t) {
                // An exception occurred
                logger.error("Unable to write cached message {} for {}", e.getMessage(), r.uuid());
                logger.error("", t);
                for (Object o : cacheMessages) {
                    bc.getBroadcasterCache().addToCache(getID(), r != null ? r.uuid() : BroadcasterCache.NULL, new BroadcastMessage(o));
                }
                return true;
            }
            // If long-polling or JSONP is used we need to set the messages for the event again, because onResume() have cleared them
            if (willBeResumed) {
                e.setMessage(filteredMessageClone);
            }
            for (AtmosphereResourceEventListener l : willBeResumed ? listeners : rImpl.atmosphereResourceEventListener()) {
                l.onBroadcast(e);
            }
            switch(r.transport()) {
                case UNDEFINED:
                case JSONP:
                case AJAX:
                case LONG_POLLING:
                    return true;
                case SSE:
                    break;
                default:
                    try {
                        r.getResponse().flushBuffer();
                    } catch (IOException ioe) {
                        logger.trace("", ioe);
                        AtmosphereResourceImpl.class.cast(r)._destroy();
                    }
                    break;
            }
        }
    }
    return false;
}
Also used : ArrayList(java.util.ArrayList) IOException(java.io.IOException) LinkedList(java.util.LinkedList) BroadcastMessage(org.atmosphere.cache.BroadcastMessage) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List)

Example 5 with BroadcastMessage

use of org.atmosphere.cache.BroadcastMessage in project atmosphere by Atmosphere.

the class DefaultBroadcaster method cacheLostMessage.

/**
     * Cache the message because an unexpected exception occurred.
     *
     * @param r {@link AtmosphereResource}
     */
public void cacheLostMessage(AtmosphereResource r, AsyncWriteToken token, boolean force) {
    if (!force) {
        return;
    }
    try {
        if (token != null && token.originalMessage != null) {
            bc.getBroadcasterCache().addToCache(getID(), r != null ? r.uuid() : BroadcasterCache.NULL, new BroadcastMessage(String.valueOf(token.future.hashCode()), token.originalMessage));
            logger.trace("Lost message cached {}", token.originalMessage);
        }
    } catch (Throwable t2) {
        logger.error("Unable to cache message {} for AtmosphereResource {}", token.originalMessage, r != null ? r.uuid() : "");
        logger.error("Unable to cache message", t2);
    }
}
Also used : BroadcastMessage(org.atmosphere.cache.BroadcastMessage)

Aggregations

BroadcastMessage (org.atmosphere.cache.BroadcastMessage)8 List (java.util.List)6 CacheMessage (org.atmosphere.cache.CacheMessage)6 AbstractBroadcasterCache (org.atmosphere.cache.AbstractBroadcasterCache)5 Test (org.testng.annotations.Test)5 BroadcasterCacheInspector (org.atmosphere.cache.BroadcasterCacheInspector)4 ArrayList (java.util.ArrayList)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 IOException (java.io.IOException)1 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 ExecutionException (java.util.concurrent.ExecutionException)1 ExecutorService (java.util.concurrent.ExecutorService)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 Servlet30CometSupport (org.atmosphere.container.Servlet30CometSupport)1 AR (org.atmosphere.runtime.BroadcasterCacheTest.AR)1