test_class.file: outland-feature-server/src/test/java/outland/feature/server/features/DefaultVersionServiceTest.java
test_class.identifier: DefaultVersionServiceTest
test_case.body: @Test
    public void sendPhysicalTimeInTheFuture() {
  
      final int[] calls = {0};
  
      final DefaultVersionService.Clock clock = () -> {
  
        if (calls[0]++ == 0) {
          return (System.currentTimeMillis() * 1000L);
        }
  
        return (System.currentTimeMillis() * 1000L) + DefaultVersionService.MAX_SYSTEM_TIME_FORWARD_DRIFT + 1;
      };
  
      DefaultVersionService v = new DefaultVersionService(clock);
      final DefaultVersionService.HybridLogicalTimestamp send = v.nextVersion();
      final DefaultVersionService.HybridLogicalTimestamp send1 = v.nextVersion();
  
      // when our physical clock is too far ahead, only the counter moves forward
      assertEquals(send.logicalTime(), send1.logicalTime());
      assertTrue(send.counter() < send1.counter());
      assertSame(send.counter(), send1.counter() - 1);
    }
test_case.class_method_signature: DefaultVersionServiceTest.sendPhysicalTimeInTheFuture()
test_case.full_signature: @Test public void sendPhysicalTimeInTheFuture()
test_case.identifier: sendPhysicalTimeInTheFuture
test_case.invocations: currentTimeMillis currentTimeMillis nextVersion nextVersion assertEquals logicalTime logicalTime assertTrue counter counter assertSame counter counter
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void sendPhysicalTimeInTheFuture()
focal_class.declarator: logger = LoggerFactory.getLogger(DefaultVersionService.class)
focal_class.modifier: private static final
focal_class.original_string: private static final Logger logger = LoggerFactory.getLogger(DefaultVersionService.class);
focal_class.type: Logger
focal_class.var_name: logger
focal_class.declarator: ONE_HOUR_MICROSECONDS = 3600L * 1000L * 1000L
focal_class.modifier: private static final
focal_class.original_string: private static final long ONE_HOUR_MICROSECONDS = 3600L * 1000L * 1000L;
focal_class.type: long
focal_class.var_name: ONE_HOUR_MICROSECONDS
focal_class.declarator: MAX_SYSTEM_TIME_FORWARD_DRIFT = 12 * ONE_HOUR_MICROSECONDS
focal_class.modifier: static final
focal_class.original_string: static final long MAX_SYSTEM_TIME_FORWARD_DRIFT = 12 * ONE_HOUR_MICROSECONDS;
focal_class.type: long
focal_class.var_name: MAX_SYSTEM_TIME_FORWARD_DRIFT
focal_class.declarator: MAX_INCOMING_TIME_FORWARD_DRIFT = 12 * ONE_HOUR_MICROSECONDS
focal_class.modifier: private static final
focal_class.original_string: private static final long MAX_INCOMING_TIME_FORWARD_DRIFT = 12 * ONE_HOUR_MICROSECONDS;
focal_class.type: long
focal_class.var_name: MAX_INCOMING_TIME_FORWARD_DRIFT
focal_class.declarator: INITIAL_COUNTER = 0L
focal_class.modifier: private static final
focal_class.original_string: private static final long INITIAL_COUNTER = 0L;
focal_class.type: long
focal_class.var_name: INITIAL_COUNTER
focal_class.declarator: clock
focal_class.modifier: private final
focal_class.original_string: private final Clock clock;
focal_class.type: Clock
focal_class.var_name: clock
focal_class.declarator: localTime
focal_class.modifier: private final
focal_class.original_string: private final AtomicLong localTime;
focal_class.type: AtomicLong
focal_class.var_name: localTime
focal_class.declarator: localCounter
focal_class.modifier: private final
focal_class.original_string: private final AtomicLong localCounter;
focal_class.type: AtomicLong
focal_class.var_name: localCounter
focal_class.file: outland-feature-server/src/main/java/outland/feature/server/features/DefaultVersionService.java
focal_class.identifier: DefaultVersionService
focal_class.interfaces: implements VersionService
focal_class.class_method_signature: DefaultVersionService.DefaultVersionService(Clock clock)
focal_class.full_signature:   DefaultVersionService(Clock clock)
focal_class.identifier: DefaultVersionService
focal_class.parameters: (Clock clock)
focal_class.signature:  DefaultVersionService(Clock clock)
focal_class.class_method_signature: DefaultVersionService.DefaultVersionService()
focal_class.full_signature:   DefaultVersionService()
focal_class.identifier: DefaultVersionService
focal_class.parameters: ()
focal_class.signature:  DefaultVersionService()
focal_class.class_method_signature: DefaultVersionService.nextVersion()
focal_class.full_signature: @Override public HybridLogicalTimestamp nextVersion()
focal_class.identifier: nextVersion
focal_class.modifiers: @Override public
focal_class.parameters: ()
focal_class.return: HybridLogicalTimestamp
focal_class.signature: HybridLogicalTimestamp nextVersion()
focal_class.class_method_signature: DefaultVersionService.nextVersionUpdate(HybridLogicalTimestamp incoming)
focal_class.full_signature: @Override public HybridLogicalTimestamp nextVersionUpdate(HybridLogicalTimestamp incoming)
focal_class.identifier: nextVersionUpdate
focal_class.modifiers: @Override public
focal_class.parameters: (HybridLogicalTimestamp incoming)
focal_class.return: HybridLogicalTimestamp
focal_class.signature: HybridLogicalTimestamp nextVersionUpdate(HybridLogicalTimestamp incoming)
focal_class.class_method_signature: DefaultVersionService.physicalNowTooFarAhead(long physicalNow, AtomicLong logicalTime)
focal_class.full_signature: private boolean physicalNowTooFarAhead(long physicalNow, AtomicLong logicalTime)
focal_class.identifier: physicalNowTooFarAhead
focal_class.modifiers: private
focal_class.parameters: (long physicalNow, AtomicLong logicalTime)
focal_class.return: boolean
focal_class.signature: boolean physicalNowTooFarAhead(long physicalNow, AtomicLong logicalTime)
focal_class.class_method_signature: DefaultVersionService.resolveLocalAndIncomingTimestamps(HybridLogicalTimestamp incoming)
focal_class.full_signature: private void resolveLocalAndIncomingTimestamps(HybridLogicalTimestamp incoming)
focal_class.identifier: resolveLocalAndIncomingTimestamps
focal_class.modifiers: private
focal_class.parameters: (HybridLogicalTimestamp incoming)
focal_class.return: void
focal_class.signature: void resolveLocalAndIncomingTimestamps(HybridLogicalTimestamp incoming)
focal_class.class_method_signature: DefaultVersionService.traceForwardDrift(long physicalNow, long localTime)
focal_class.full_signature: private void traceForwardDrift(long physicalNow, long localTime)
focal_class.identifier: traceForwardDrift
focal_class.modifiers: private
focal_class.parameters: (long physicalNow, long localTime)
focal_class.return: void
focal_class.signature: void traceForwardDrift(long physicalNow, long localTime)
focal_class.class_method_signature: DefaultVersionService.traceIncomingForwardDrift(long localTime, long incomingTime)
focal_class.full_signature: private void traceIncomingForwardDrift(long localTime, long incomingTime)
focal_class.identifier: traceIncomingForwardDrift
focal_class.modifiers: private
focal_class.parameters: (long localTime, long incomingTime)
focal_class.return: void
focal_class.signature: void traceIncomingForwardDrift(long localTime, long incomingTime)
focal_class.class_method_signature: DefaultVersionService.traceBackwardDrift(long physicalNow, long localTime, long incoming)
focal_class.full_signature: private void traceBackwardDrift(long physicalNow, long localTime, long incoming)
focal_class.identifier: traceBackwardDrift
focal_class.modifiers: private
focal_class.parameters: (long physicalNow, long localTime, long incoming)
focal_class.return: void
focal_class.signature: void traceBackwardDrift(long physicalNow, long localTime, long incoming)
focal_class.class_method_signature: DefaultVersionService.traceBackwardDrift(long physicalNow, long localTime)
focal_class.full_signature: private void traceBackwardDrift(long physicalNow, long localTime)
focal_class.identifier: traceBackwardDrift
focal_class.modifiers: private
focal_class.parameters: (long physicalNow, long localTime)
focal_class.return: void
focal_class.signature: void traceBackwardDrift(long physicalNow, long localTime)
focal_method.body: @Override
    public HybridLogicalTimestamp nextVersion() {
  
      final long physicalNow = this.clock.timestampMicros();
  
      if (localTime.get() >= physicalNow) {
        //physical clock hasn't moved forward relative to local, keep the logicalTime, bump counter
        localCounter.incrementAndGet();
        traceBackwardDrift(physicalNow, localTime.get());
      } else {
        // the physical clock is ahead
  
        /*
         a hack to handle the 2051 problem; if our system clock is "too" far ahead of our local
         logicalTime then all future versions get dragged forward to keep up with it and we have
         to wait for "reality" to catch up with that logicalTime to reset things.
  
         todo: this misses the case where the clock is borked on construction;
         in the ctor we set the initial local to the physical clock, so this only catches drift
         when updating the local. it also needs some thought such that if multiple nodes are stuck
         on fwd/back physical times and just bumping counters they don't clash.
          */
        if (physicalNowTooFarAhead(physicalNow, localTime)) {
          localCounter.incrementAndGet();
          traceForwardDrift(physicalNow, localTime.get());
        } else {
          // things look sane, take the physical logicalTime and reset the counter
          localTime.set(physicalNow);
          localCounter.set(INITIAL_COUNTER);
        }
      }
  
      return new HybridLogicalTimestamp(localTime.get(), localCounter.get());
    }
focal_method.class_method_signature: DefaultVersionService.nextVersion()
focal_method.full_signature: @Override public HybridLogicalTimestamp nextVersion()
focal_method.identifier: nextVersion
focal_method.invocations: timestampMicros get incrementAndGet traceBackwardDrift get physicalNowTooFarAhead incrementAndGet traceForwardDrift get set set get get
focal_method.modifiers: @Override public
focal_method.parameters: ()
focal_method.return: HybridLogicalTimestamp
focal_method.signature: HybridLogicalTimestamp nextVersion()