All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nstream.reflect.model.LinkStats Maven / Gradle / Ivy

The newest version!
// Copyright 2015-2024 Nstream, inc.
//
// Licensed under the Redis Source Available License 2.0 (RSALv2) Agreement;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://redis.com/legal/rsalv2-agreement/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package nstream.reflect.model;

import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import swim.recon.Recon;
import swim.structure.Form;
import swim.structure.Item;
import swim.structure.Kind;
import swim.structure.Record;
import swim.structure.Value;
import swim.system.LinkBinding;
import swim.warp.CommandMessage;
import swim.warp.Envelope;
import swim.warp.EventMessage;

@SuppressWarnings("checkstyle:VisibilityModifier")
public class LinkStats {
  public volatile long downLinkCount;
  public volatile long downMessageCount;
  public volatile long downEventCount;
  public volatile long downCommandCount;
  public volatile long downMessageRateMax;
  public volatile long upLinkCount;
  public volatile long upMessageCount;
  public volatile long upEventCount;
  public volatile long upCommandCount;
  public volatile long upCommandAvgSize;
  public volatile long upMessageRateMax;

  public LinkStats() {
    // nop
  }

  public void didOpenDownlink(LinkBinding link) {
    DOWN_LINK_COUNT.incrementAndGet(this);
  }

  public void didCloseDownlink(LinkBinding link) {
    DOWN_LINK_COUNT.decrementAndGet(this);
  }

  public void didOpenUplink(LinkBinding link) {
    UP_LINK_COUNT.incrementAndGet(this);
  }

  public void didCloseUplink(Value linkKey) {
    UP_LINK_COUNT.decrementAndGet(this);
  }

  public void didPushDown(Envelope envelope) {
    DOWN_MESSAGE_COUNT.incrementAndGet(this);
    if (envelope instanceof EventMessage) {
      DOWN_EVENT_COUNT.incrementAndGet(this);
    } else if (envelope instanceof CommandMessage) {
      DOWN_COMMAND_COUNT.incrementAndGet(this);
    }
  }

  public void didPushUp(Envelope envelope) {
    UP_MESSAGE_COUNT.incrementAndGet(this);
    if (envelope instanceof EventMessage) {
      UP_EVENT_COUNT.incrementAndGet(this);
    } else if (envelope instanceof CommandMessage) {
      long oldSize, oldCommandCount, delta, newSize;
      do {
        oldSize = this.upCommandAvgSize;
        oldCommandCount = this.upCommandCount;
        delta = Recon.sizeOf(envelope.body());
        newSize = ((oldSize * oldCommandCount) + delta) / Math.max(1, oldCommandCount + 1);
      } while (!UP_COMMAND_AVG_SIZE.compareAndSet(this, oldSize, newSize));
      UP_COMMAND_COUNT.incrementAndGet(this);
    }
  }

  public void accumulate(LinkStats stats) {
    DOWN_LINK_COUNT.addAndGet(this, stats.downLinkCount);
    DOWN_MESSAGE_COUNT.addAndGet(this, stats.downMessageCount);
    DOWN_EVENT_COUNT.addAndGet(this, stats.downEventCount);
    DOWN_COMMAND_COUNT.addAndGet(this, stats.downCommandCount);
    DOWN_MESSAGE_RATE_MAX.addAndGet(this, stats.downMessageRateMax);
    UP_LINK_COUNT.addAndGet(this, stats.upLinkCount);
    UP_MESSAGE_COUNT.addAndGet(this, stats.upMessageCount);
    UP_EVENT_COUNT.addAndGet(this, stats.upEventCount);
    long oldSize, oldCommandCount, newSize;
    do {
      oldSize = this.upCommandAvgSize;
      oldCommandCount = this.upCommandCount;
      newSize = ((oldSize * oldCommandCount) + (stats.upCommandAvgSize * stats.upCommandCount))
          / Math.max(1, oldCommandCount + stats.upCommandCount);
    } while (!UP_COMMAND_AVG_SIZE.compareAndSet(this, oldSize, newSize));
    UP_COMMAND_COUNT.addAndGet(this, stats.upCommandCount);
    UP_MESSAGE_RATE_MAX.addAndGet(this, stats.upMessageRateMax);
  }

  public void supersede(LinkStats total, LinkStats delta) {
    final long newDownLinkCount = this.downLinkCount;
    final long newDownMessageCount = this.downMessageCount;
    final long newDownEventCount = this.downEventCount;
    final long newDownCommandCount = this.downCommandCount;
    final long newDownMessageRateMax = this.downMessageRateMax;
    final long newUpLinkCount = this.upLinkCount;
    final long newUpMessageCount = this.upMessageCount;
    final long newUpEventCount = this.upEventCount;
    final long newUpCommandAvgSize = this.upCommandAvgSize;
    final long newUpCommandCount = this.upCommandCount;
    final long newUpMessageRateMax = this.upMessageRateMax;

    final long oldDownLinkCount = DOWN_LINK_COUNT.getAndSet(total, newDownLinkCount);
    final long oldDownMessageCount = DOWN_MESSAGE_COUNT.getAndSet(total, newDownMessageCount);
    final long oldDownEventCount = DOWN_EVENT_COUNT.getAndSet(total, newDownEventCount);
    final long oldDownCommandCount = DOWN_COMMAND_COUNT.getAndSet(total, newDownCommandCount);
    final long oldDownMessageRateMax = DOWN_MESSAGE_RATE_MAX.getAndSet(total, newDownMessageRateMax);
    final long oldUpLinkCount = UP_LINK_COUNT.getAndSet(total, newUpLinkCount);
    final long oldUpMessageCount = UP_MESSAGE_COUNT.getAndSet(total, newUpMessageCount);
    final long oldUpEventCount = UP_EVENT_COUNT.getAndSet(total, newUpEventCount);
    final long oldUpCommandAvgSize = UP_COMMAND_AVG_SIZE.getAndSet(total, newUpCommandAvgSize);
    final long oldUpCommandCount = UP_COMMAND_COUNT.getAndSet(total, newUpCommandCount);
    final long oldUpMessageRateMax = UP_MESSAGE_RATE_MAX.getAndSet(total, newUpMessageRateMax);

    DOWN_LINK_COUNT.addAndGet(delta, newDownLinkCount - oldDownLinkCount);
    DOWN_MESSAGE_COUNT.addAndGet(delta, newDownMessageCount - oldDownMessageCount);
    DOWN_EVENT_COUNT.addAndGet(delta, newDownEventCount - oldDownEventCount);
    DOWN_COMMAND_COUNT.addAndGet(delta, newDownCommandCount - oldDownCommandCount);
    DOWN_MESSAGE_RATE_MAX.addAndGet(delta, newDownMessageRateMax - oldDownMessageRateMax);
    UP_LINK_COUNT.addAndGet(delta, newUpLinkCount - oldUpLinkCount);
    UP_MESSAGE_COUNT.addAndGet(delta, newUpMessageCount - oldUpMessageCount);
    UP_EVENT_COUNT.addAndGet(delta, newUpEventCount - oldUpEventCount);
    UP_COMMAND_AVG_SIZE.addAndGet(delta, newUpCommandAvgSize - oldUpCommandAvgSize);
    UP_COMMAND_COUNT.addAndGet(delta, newUpCommandCount - oldUpCommandCount);
    UP_MESSAGE_RATE_MAX.addAndGet(delta, newUpMessageRateMax - oldUpMessageRateMax);
  }

  public LinkStats getAndReset() {
    final LinkStats stats = new LinkStats();
    stats.downLinkCount = DOWN_LINK_COUNT.getAndSet(this, 0L);
    stats.downMessageCount = DOWN_MESSAGE_COUNT.getAndSet(this, 0L);
    stats.downEventCount = DOWN_EVENT_COUNT.getAndSet(this, 0L);
    stats.downCommandCount = DOWN_COMMAND_COUNT.getAndSet(this, 0L);
    final long downMessageRateMax = this.downMessageRateMax;
    if (stats.downMessageCount > downMessageRateMax) {
      stats.downMessageRateMax = stats.downMessageCount - downMessageRateMax;
      DOWN_MESSAGE_RATE_MAX.set(this, stats.downMessageCount);
    }
    stats.upLinkCount = UP_LINK_COUNT.getAndSet(this, 0L);
    stats.upMessageCount = UP_MESSAGE_COUNT.getAndSet(this, 0L);
    stats.upEventCount = UP_EVENT_COUNT.getAndSet(this, 0L);
    stats.upCommandAvgSize = UP_COMMAND_AVG_SIZE.getAndSet(this, 0L);
    stats.upCommandCount = UP_COMMAND_COUNT.getAndSet(this, 0L);
    final long upMessageRateMax = this.upMessageRateMax;
    if (stats.upMessageCount > upMessageRateMax) {
      stats.upMessageRateMax = stats.upMessageCount - upMessageRateMax;
      UP_MESSAGE_RATE_MAX.set(this, stats.upMessageCount);
    }
    return stats;
  }

  public LinkStats get() {
    final LinkStats stats = new LinkStats();
    stats.downLinkCount = this.downLinkCount;
    stats.downMessageCount = this.downMessageCount;
    stats.downEventCount = this.downEventCount;
    stats.downCommandCount = this.downCommandCount;
    stats.downMessageRateMax = this.downMessageRateMax;
    stats.upLinkCount = this.upLinkCount;
    stats.upMessageCount = this.upMessageCount;
    stats.upEventCount = this.upEventCount;
    stats.upCommandCount = this.upCommandCount;
    stats.upCommandAvgSize = this.upCommandAvgSize;
    stats.upMessageRateMax = this.upMessageRateMax;
    return stats;
  }

  public Value toValue() {
    return form().mold(this).toValue();
  }

  static final AtomicLongFieldUpdater DOWN_LINK_COUNT =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "downLinkCount");
  static final AtomicLongFieldUpdater DOWN_MESSAGE_COUNT =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "downMessageCount");
  static final AtomicLongFieldUpdater DOWN_EVENT_COUNT =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "downEventCount");
  static final AtomicLongFieldUpdater DOWN_COMMAND_COUNT =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "downCommandCount");
  static final AtomicLongFieldUpdater DOWN_MESSAGE_RATE_MAX =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "downMessageRateMax");
  static final AtomicLongFieldUpdater UP_LINK_COUNT =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "upLinkCount");
  static final AtomicLongFieldUpdater UP_MESSAGE_COUNT =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "upMessageCount");
  static final AtomicLongFieldUpdater UP_EVENT_COUNT =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "upEventCount");
  static final AtomicLongFieldUpdater UP_COMMAND_COUNT =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "upCommandCount");
  static final AtomicLongFieldUpdater UP_COMMAND_AVG_SIZE =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "upCommandAvgSize");
  static final AtomicLongFieldUpdater UP_MESSAGE_RATE_MAX =
      AtomicLongFieldUpdater.newUpdater(LinkStats.class, "upMessageRateMax");

  private static Form form;

  @Kind
  public static Form form() {
    if (form == null) {
      form = new LinkStatsForm();
    }
    return form;
  }
}

final class LinkStatsForm extends Form {
  @Override
  public Class type() {
    return LinkStats.class;
  }

  @Override
  public Item mold(LinkStats stats) {
    if (stats != null) {
      final Record record = Record.create(12);
      if (stats.downLinkCount > 0L) {
        record.slot("downLinkCount", stats.downLinkCount);
      }
      if (stats.downMessageCount > 0L) {
        record.slot("downMessageCount", stats.downMessageCount);
      }
      if (stats.downEventCount > 0L) {
        record.slot("downEventCount", stats.downEventCount);
      }
      if (stats.downCommandCount > 0L) {
        record.slot("downCommandCount", stats.downCommandCount);
      }
      if (stats.downMessageRateMax > 0L) {
        record.slot("downMessageRateMax", stats.downMessageRateMax);
      }
      if (stats.upLinkCount > 0L) {
        record.slot("upLinkCount", stats.upLinkCount);
      }
      if (stats.upMessageCount > 0L) {
        record.slot("upMessageCount", stats.upMessageCount);
      }
      if (stats.upEventCount > 0L) {
        record.slot("upEventCount", stats.upEventCount);
      }
      if (stats.upCommandCount > 0L) {
        record.slot("upCommandCount", stats.upCommandCount);
        record.slot("upCommandSize", stats.upCommandCount * stats.upCommandAvgSize);
        record.slot("upCommandAvgSize", stats.upCommandAvgSize);
      }
      if (stats.upMessageRateMax > 0L) {
        record.slot("upMessageRateMax", stats.upMessageRateMax);
      }
      return record;
    } else {
      return Item.extant();
    }
  }

  @Override
  public LinkStats cast(Item item) {
    final Item value = item.toValue();
    final LinkStats stats = new LinkStats();
    stats.downLinkCount = value.get("downLinkCount").longValue(0L);
    stats.downMessageCount = value.get("downMessageCount").longValue(0L);
    stats.downEventCount = value.get("downEventCount").longValue(0L);
    stats.downCommandCount = value.get("downCommandCount").longValue(0L);
    stats.downMessageRateMax = value.get("downMessageRateMax").longValue(0L);
    stats.upLinkCount = value.get("upLinkCount").longValue(0L);
    stats.upMessageCount = value.get("upMessageCount").longValue(0L);
    stats.upEventCount = value.get("upEventCount").longValue(0L);
    stats.upCommandAvgSize = value.get("upCommandSize").longValue(0L) / value.get("upCommandCount").longValue(1L);
    stats.upCommandCount = value.get("upCommandCount").longValue(0L);
    stats.upMessageRateMax = value.get("upMessageRateMax").longValue(0L);
    return stats;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy