/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.bigdata.util; import java.util.UUID; /** * An instance of this class is thrown if we observe that the timestamps * generated by two or more services violate a requirement for synchronized * clocks. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> */ public class ClocksNotSynchronizedException extends RuntimeException { /** * */ private static final long serialVersionUID = 1L; public ClocksNotSynchronizedException() { super(); } public ClocksNotSynchronizedException(String msg) { super(msg); } /** * Assert that <code>t1</code> LT <code>t2</code>, where <code>t1</code> and * <code>t2</code> are timestamps obtain such that this relation will be * <code>true</code> if the clocks on the nodes are synchronized. * <p> * Note: Clock synchronization errors can arise across nodes if the nodes * are not using a common network time source. * <p> * Note: Synchronization errors can arise on a single node if the clock is * changed on that node - specifically if the clock is move backwards to * before the most recent commit timestamp. For example, if the timezone is * changed. * * @param serviceId1 * The service that reported the timestamp <code>t1</code>. * @param serviceId2 * The service that reported the timestamp <code>t2</code>. * @param t1 * A timestamp from one service. * @param t2 * A timestamp from the another service. * @param maxSkew * The maximum allowed clock skew (typically on the order of * seconds). * * @throws ClocksNotSynchronizedException */ static public void assertBefore(final UUID serviceId1, final UUID serviceId2, final long t1, final long t2, final long maxSkew) throws ClocksNotSynchronizedException { if (t1 < t2) { /* * Strictly LT. * * Note: There can be large latencies between t1 and t2. If t1 is * taken on the leader before t2 is taken on the follower, then a * full GC on either node before t2 is taken will result in a large * latency between t1 and t2. Our concern here is to identify skew * that violates the BEFORE semantics, not latency in which time * moves forward. */ return; } final long delta = Math.abs(t1 - t2); if (delta <= maxSkew) return; // if (t2 >= min && t2 <= max) { // // The 2nd clock is within the allowed window. // return; // } throw new ClocksNotSynchronizedException("service1=" + serviceId1 + ", serviceId2=" + serviceId2 + ", skew=" + delta + "ms exceeds maximumSkew=" + maxSkew + "ms."); } }