/** * @param request * @param connection * @return */ public LogicalNode handleSubscriberRequest( SubscribeRequestTuple request, AbstractLengthPrependerClient connection) { String identifier = request.getIdentifier(); String type = request.getStreamType(); String upstream_identifier = request.getUpstreamIdentifier(); // Check if there is a logical node of this type, if not create it. LogicalNode ln; if (subscriberGroups.containsKey(type)) { // logger.debug("adding to exiting group = {}", subscriberGroups.get(type)); /* * close previous connection with the same identifier which is guaranteed to be unique. */ AbstractLengthPrependerClient previous = subscriberChannels.put(identifier, connection); if (previous != null) { eventloop.disconnect(previous); } ln = subscriberGroups.get(type); ln.boot(eventloop); ln.addConnection(connection); } else { /* * if there is already a datalist registered for the type in which this client is interested, * then get a iterator on the data items of that data list. If the datalist is not registered, * then create one and register it. Hopefully this one would be used by future upstream nodes. */ DataList dl; if (publisherBuffers.containsKey(upstream_identifier)) { dl = publisherBuffers.get(upstream_identifier); // logger.debug("old list = {}", dl); } else { dl = Tuple.FAST_VERSION.equals(request.getVersion()) ? new FastDataList(upstream_identifier, blockSize, numberOfCacheBlocks) : new DataList(upstream_identifier, blockSize, numberOfCacheBlocks); publisherBuffers.put(upstream_identifier, dl); // logger.debug("new list = {}", dl); } long skipWindowId = (long) request.getBaseSeconds() << 32 | request.getWindowId(); ln = new LogicalNode( upstream_identifier, type, dl.newIterator(identifier, skipWindowId), skipWindowId); int mask = request.getMask(); if (mask != 0) { for (Integer bs : request.getPartitions()) { ln.addPartition(bs, mask); } } subscriberGroups.put(type, ln); ln.addConnection(connection); dl.addDataListener(ln); } return ln; }
@Override public void onMessage(byte[] buffer, int offset, int size) { if (ignore) { return; } Tuple request = Tuple.getTuple(buffer, offset, size); switch (request.getType()) { case PUBLISHER_REQUEST: /* * unregister the unidentified client since its job is done! */ unregistered(key); logger.info("Received publisher request: {}", request); PublishRequestTuple publisherRequest = (PublishRequestTuple) request; DataList dl = handlePublisherRequest(publisherRequest, this); dl.setAutoFlushExecutor(serverHelperExecutor); Publisher publisher; if (publisherRequest.getVersion().equals(Tuple.FAST_VERSION)) { publisher = new Publisher(dl, (long) request.getBaseSeconds() << 32 | request.getWindowId()) { @Override public int readSize() { if (writeOffset - readOffset < 2) { return -1; } short s = buffer[readOffset++]; return s | (buffer[readOffset++] << 8); } }; } else { publisher = new Publisher(dl, (long) request.getBaseSeconds() << 32 | request.getWindowId()); } key.attach(publisher); key.interestOps(SelectionKey.OP_READ); publisher.registered(key); int len = writeOffset - readOffset - size; if (len > 0) { publisher.transferBuffer(this.buffer, readOffset + size, len); } ignore = true; break; case SUBSCRIBER_REQUEST: /* * unregister the unidentified client since its job is done! */ unregistered(key); ignore = true; logger.info("Received subscriber request: {}", request); SubscribeRequestTuple subscriberRequest = (SubscribeRequestTuple) request; AbstractLengthPrependerClient subscriber; // /* for backward compatibility - set the buffer size to 16k - EXPERIMENTAL */ int bufferSize = subscriberRequest.getBufferSize(); // if (bufferSize == 0) { // bufferSize = 16 * 1024; // } if (subscriberRequest.getVersion().equals(Tuple.FAST_VERSION)) { subscriber = new Subscriber( subscriberRequest.getStreamType(), subscriberRequest.getMask(), subscriberRequest.getPartitions(), bufferSize); } else { subscriber = new Subscriber( subscriberRequest.getStreamType(), subscriberRequest.getMask(), subscriberRequest.getPartitions(), bufferSize) { @Override public int readSize() { if (writeOffset - readOffset < 2) { return -1; } short s = buffer[readOffset++]; return s | (buffer[readOffset++] << 8); } }; } key.attach(subscriber); key.interestOps(SelectionKey.OP_WRITE | SelectionKey.OP_READ); subscriber.registered(key); final LogicalNode logicalNode = handleSubscriberRequest(subscriberRequest, subscriber); serverHelperExecutor.submit( new Runnable() { @Override public void run() { logicalNode.catchUp(); } }); break; case PURGE_REQUEST: logger.info("Received purge request: {}", request); try { handlePurgeRequest((PurgeRequestTuple) request, this); } catch (IOException io) { throw new RuntimeException(io); } break; case RESET_REQUEST: logger.info("Received reset all request: {}", request); try { handleResetRequest((ResetRequestTuple) request, this); } catch (IOException io) { throw new RuntimeException(io); } break; default: throw new RuntimeException("unexpected message: " + request.toString()); } }