Example #1
0
 /**
  * A non-null file name indicates that recording be enabled. The file must also be present and
  * have the appropriate permissions.
  *
  * @param file
  */
 public void record(final File file) {
   if (file == null) {
     majorLogger.info("no recorder file specified");
     return;
   }
   if (file.exists()) {
     majorLogger.warn("the recorder file is being overwritten", file);
     if (!file.canWrite()) {
       majorLogger.warn("the recorder file path provided is not writable: {}", file);
       return;
     }
   }
   final SyntheticData.Recorder old = this.recorder.getAndSet(new SyntheticData.Recorder(file));
   if (old != null) {
     old.stopRecording();
   }
 }
Example #2
0
  /**
   * Send the data to all channels except the incoming channel.
   *
   * <p>Write the message to the recorder file for later study and playback. This involves
   * converting the binary payload to a textual representation.
   *
   * <p>If the inbound message is an INTEREST message then it is not sent. Instead it is responded
   * to in a way indicated by the ?.
   *
   * @param sourceCtx
   * @param originalMsg
   */
  public void distribute(ChannelHandlerContext sourceCtx, final MetaLinkMsg.Edit originalMsg) {
    majorLogger.trace(
        "incoming message to distribute(): {}\n {}",
        sourceCtx.channel().remoteAddress(),
        originalMsg);
    if (originalMsg == null) {
      majorLogger.warn("attempt to distribute null message");
      return;
    }
    try {
      final SyntheticData.Recorder recorder = this.recorder.get();

      final MetaLinkMsg.Edit.Builder editBuilder = originalMsg.toBuilder();
      final MetaLinkMsg.Edit msg;
      if (originalMsg.getModeCount() < 1) {
        if (originalMsg.hasEditMode()) {
          editBuilder.addMode(originalMsg.getEditMode());
          msg = editBuilder.build();
        } else {
          majorLogger.warn("no edit mode provided, assuming POST");
          editBuilder.addMode(MetaLinkMsg.Edit.EditMode.POST);
          editBuilder.setEditMode(MetaLinkMsg.Edit.EditMode.POST);
          msg = editBuilder.build();
        }
      } else {
        if (originalMsg.hasEditMode()) {
          if (originalMsg.getEditMode() == originalMsg.getMode(originalMsg.getModeCount() - 1)) {
            msg = editBuilder.build();
          } else {
            majorLogger.info("edit mode mismatch, set the last mode");
            editBuilder.addMode(originalMsg.getEditMode());
            msg = editBuilder.build();
          }
        } else {
          majorLogger.info("edit mode provided, using the last mode");
          editBuilder.setEditMode(originalMsg.getMode(originalMsg.getModeCount() - 1));
          msg = editBuilder.build();
        }
      }

      if (null != recorder) {
        recorder.record(sourceCtx, msg);
      }
      final String trackingGuid =
          msg.hasGuid() ? msg.getGuid().toString() : UUID.randomUUID().toString();
      final String origin = (msg.getOriginCount() > 0) ? msg.getOrigin(0) : "";

      switch (msg.getEditMode()) {
        case NOTICE:
          {
            final Interest topic = new Interest(msg.getTopicList());
            final Interest.InterestedChannelSet channelSet = this.interestedChannelMap.get(topic);
            if (channelSet == null) {
              majorLogger.warn("no interested channel set");
              editBuilder
                  .addMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                  .setEditMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                  .addOrigin(METALINK_BRIDGE_NAME)
                  .setSequence(sequenceNumber.incrementAndGet());

              final MetaLinkMsg.Notice.Builder noticeBuilder =
                  MetaLinkMsg.Notice.newBuilder()
                      .setNoticeMode(MetaLinkMsg.Notice.NoticeMode.ACK)
                      .setCode(NO_INTEREST_PRESENT)
                      .setMsg("no interest in topic")
                      .setId(msg.getGuid());
              editBuilder.addNotices(noticeBuilder);

              final MetaLinkMsg.Edit updatedEdit = editBuilder.build();
              majorLogger.trace(
                  "notice no-interest notice {} to {}",
                  trackingGuid,
                  sourceCtx.channel().remoteAddress());
              sourceCtx.write(updatedEdit);
              sourceCtx.flush();
              detailLogger.info("update edit\n{}", updatedEdit);

              if (null != recorder) {
                recorder.record(sourceCtx, updatedEdit);
              }
              break;
            }
            majorLogger.trace("posting notice to all interested channels except source");
            boolean anyInterest = false;
            for (final ChannelHandlerContext ctx : channelSet.getContextSet()) {
              if (isSameChannel(ctx, sourceCtx)) {
                continue;
              }
              anyInterest = true;
              majorLogger.trace(
                  "notice forward {} to {}", trackingGuid, ctx.channel().remoteAddress());
              ctx.write(msg);
              ctx.flush();
              detailLogger.info("message sent:\n{}", msg);
            }

            if (!anyInterest) {
              editBuilder
                  .addMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                  .setEditMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                  .addOrigin(METALINK_BRIDGE_NAME)
                  .setSequence(sequenceNumber.incrementAndGet());

              final MetaLinkMsg.Notice.Builder noticeBuilder =
                  MetaLinkMsg.Notice.newBuilder()
                      .setNoticeMode(MetaLinkMsg.Notice.NoticeMode.ACK)
                      .setCode(NO_INTEREST_PRESENT)
                      .setMsg("no pending interest for topic")
                      .setId(msg.getGuid());
              editBuilder.addNotices(noticeBuilder);

              final MetaLinkMsg.Edit updatedEdit = editBuilder.build();
              majorLogger.trace(
                  "notice no interest {} to {}", trackingGuid, sourceCtx.channel().remoteAddress());
              sourceCtx.write(updatedEdit);
              sourceCtx.flush();
              detailLogger.info("message sent:\n{}", updatedEdit);

              majorLogger.trace("cannot post, no other interest \n{}", updatedEdit);
              if (null != recorder) {
                recorder.record(sourceCtx, updatedEdit);
              }
            }

            break;
          }
        case POST:
          {
            final Interest topic = new Interest(msg.getTopicList());
            final Interest.InterestedChannelSet channelSet = this.interestedChannelMap.get(topic);
            if (channelSet == null || channelSet.size() == 0) {
              majorLogger.warn("no interested channel set");
              editBuilder
                  .addMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                  .setEditMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                  .addOrigin(METALINK_BRIDGE_NAME)
                  .setSequence(sequenceNumber.incrementAndGet());

              final MetaLinkMsg.Notice.Builder noticeBuilder =
                  MetaLinkMsg.Notice.newBuilder()
                      .setNoticeMode(MetaLinkMsg.Notice.NoticeMode.ACK)
                      .setCode(NO_INTEREST_PRESENT)
                      .setMsg("no interest in the posted topic")
                      .setId(msg.getGuid());
              editBuilder.addNotices(noticeBuilder);

              final MetaLinkMsg.Edit updatedEdit = editBuilder.build();
              majorLogger.trace(
                  "post no-interest {} to {}", trackingGuid, sourceCtx.channel().remoteAddress());
              sourceCtx.write(updatedEdit);
              sourceCtx.flush();
              detailLogger.info("message sent:\n{}", updatedEdit);

              if (null != recorder) {
                recorder.record(sourceCtx, updatedEdit);
              }
              break;
            } else {
              majorLogger.trace("posting edit to all interested channels except source");
              for (final ChannelHandlerContext ctx : channelSet.getContextSet()) {
                if (isSameChannel(ctx, sourceCtx)) {
                  continue;
                }
                majorLogger.trace("post all {} to {}", trackingGuid, ctx.channel().remoteAddress());
                ctx.write(msg);
                ctx.flush();
                detailLogger.info("message sent:\n{}", msg);
              }
            }
            /*
                                if (! anyInterest) {
                                    editBuilder
                                            .addMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                                            .setEditMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                                            .addOrigin(METALINK_BRIDGE_NAME)
                                            .setSequence(sequenceNumber.incrementAndGet());

                                    final MetaLinkMsg.Notice.Builder noticeBuilder = MetaLinkMsg.Notice.newBuilder()
                                            .setNoticeMode(MetaLinkMsg.Notice.NoticeMode.ACK)
                                            .setCode(NO_INTEREST_PRESENT)
                                            .setMsg("no pending interest for topic")
                                            .setId(msg.getGuid());
                                    editBuilder.addNotices(noticeBuilder);

                                    final MetaLinkMsg.Edit updatedEdit = editBuilder.build();
                                    majorLogger.trace("post no interest {} to {}",
                                            trackingGuid, sourceCtx.channel().remoteAddress());
                                    sourceCtx.write(updatedEdit);
                                    sourceCtx.flush();
                                    detailLogger.info("message sent:\n{}", updatedEdit);

                                    majorLogger.trace("cannot post, no other interest \n{}", updatedEdit);
                                    if (null != recorder) {
                                        recorder.record(sourceCtx, updatedEdit);
                                    }
                                }
            */
            break;
          }
        case INTEREST:
          {
            final Interest interest = new Interest(msg.getTopicList());
            playback(sourceCtx, interest);

            majorLogger.trace("determine if there is a client which already is interested?");
            final Interest.InterestedChannelSet ics = this.interestedChannelMap.get(interest);
            boolean anyInterest = false;
            if (ics != null) {
              for (final ChannelHandlerContext ctx : ics.getContextSet()) {
                if (isSameChannel(ctx, sourceCtx)) {
                  continue;
                }
                anyInterest = true;
                majorLogger.trace(
                    "interest in {} from {} to {}",
                    trackingGuid,
                    ctx.channel().remoteAddress(),
                    sourceCtx.channel().remoteAddress());
                sourceCtx.write(msg);
                sourceCtx.flush();
                detailLogger.info("message sent:\n{}", msg);
              }
            }
            if (!anyInterest) {
              editBuilder
                  .addMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                  .setEditMode(MetaLinkMsg.Edit.EditMode.NOTICE)
                  .addOrigin(METALINK_BRIDGE_NAME)
                  .setSequence(sequenceNumber.incrementAndGet());

              final MetaLinkMsg.Notice.Builder noticeBuilder =
                  MetaLinkMsg.Notice.newBuilder()
                      .setNoticeMode(MetaLinkMsg.Notice.NoticeMode.ACK)
                      .setCode(NO_INTEREST_PRESENT)
                      .setMsg("no pending interest for topic")
                      .setId(msg.getGuid());
              editBuilder.addNotices(noticeBuilder);

              final MetaLinkMsg.Edit updatedEdit = editBuilder.build();
              majorLogger.trace(
                  "interest notice {} to {}", trackingGuid, sourceCtx.channel().remoteAddress());
              sourceCtx.write(updatedEdit);
              sourceCtx.flush();
              detailLogger.info("message sent:\n{}", updatedEdit);

              majorLogger.trace("no other interest");
              if (null != recorder) {
                recorder.record(sourceCtx, updatedEdit);
              }
            }
            setInterest(sourceCtx, interest);
            majorLogger.trace("interest recorded");

            majorLogger.trace("expressing interest to all channels except source");
            for (final Map.Entry<SocketAddress, Interest.ChannelInterestSet> entry :
                this.channelInterestMap.entrySet()) {
              final ChannelHandlerContext ctx = entry.getValue().context;
              if (isSameChannel(ctx, sourceCtx)) {
                continue;
              }
              majorLogger.trace("interest {} to {}", trackingGuid, ctx.channel().remoteAddress());
              ctx.write(msg);
              ctx.flush();
              detailLogger.info("message sent:\n{}", msg);
            }
            break;
          }
        case DISINTEREST:
          {
            final Interest interest = new Interest(msg.getTopicList());

            majorLogger.trace("expressing disinterest to all channels except source");
            for (final Map.Entry<SocketAddress, Interest.ChannelInterestSet> entry :
                this.channelInterestMap.entrySet()) {
              final ChannelHandlerContext ctx = entry.getValue().context;
              if (isSameChannel(ctx, sourceCtx)) {
                continue;
              }
              majorLogger.trace(
                  "disinterest {} to {}", trackingGuid, ctx.channel().remoteAddress());
              ctx.write(msg);
              ctx.flush();
              detailLogger.info("message sent:\n{}", msg);
            }
            setDisinterest(sourceCtx, interest);
          }
      }
    } catch (Exception ex) {
      majorLogger.warn("problem distributing message", ex);
    }
    majorLogger.info("MESSAGE PROCESSED");
  }