/**
* Copyright [2011] [Datasalt Systems S.L.]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 com.datasalt.utils.commons;
/**
* Provides strictly increasing timestamps. Returns a milliseconds timestamp padded with 6 digits that will increase in case
* that the same timestamp is requested
*
* @author pere
*
*/
public class TimestampOracle {
private long lastTimestamp = getTimestamp();
int paddingBits = 10;
private int nRepetitions = 0;
public long getUniqueTimestamp() {
long timestamp = getTimestamp() << paddingBits;
if(timestamp == lastTimestamp) {
nRepetitions++;
timestamp += nRepetitions;
} else {
nRepetitions = 0;
lastTimestamp = timestamp;
}
return timestamp;
}
private void setPadding(){
int maxBitsPadding = getMaxPaddingBits();
this.paddingBits = Math.min(maxBitsPadding,paddingBits);
}
public static int getMaxPaddingBits(){
int maxBits =(int) Math.floor(Math.log(Long.MAX_VALUE/System.currentTimeMillis())/Math.log(2));
return maxBits;
}
public TimestampOracle(){
setPadding();
}
public TimestampOracle(int paddingBits){
this.paddingBits = paddingBits;
setPadding();
}
public static long getTimestamp() { // test implementations might override this
return System.currentTimeMillis();
}
public static void main(String[] args){
TimestampOracle tmp = new TimestampOracle();
System.out.println("Timestamp : " + TimestampOracle.getTimestamp());
System.out.println("Unique timestamp : " + tmp.getUniqueTimestamp());
System.out.println("MAX LONG SIZE : " + Long.MAX_VALUE);
System.out.println(Math.log(Long.MAX_VALUE/TimestampOracle.getTimestamp())/Math.log(2));
int nShards = 10;
int bitsForShard = (int)Math.ceil(numBits(nShards));
System.out.println("Bits for shards " + bitsForShard);
int bitsForCurrentMillis = (int)Math.ceil(numBits(System.currentTimeMillis()));
System.out.println("Bits used for current time millis " + bitsForCurrentMillis);
int bitsInLong = Long.SIZE -1; // -1 because just positive
System.out.println("Bits in long " + bitsInLong);
int padding = bitsInLong - bitsForCurrentMillis - bitsForShard;
System.out.println("Padding : " + padding);
System.out.println((1l << 62) + (1l << 61));
}
public static double numBits(long num){
return Math.log(num)/Math.log(2);
}
/*
public static TimestampOracle createWithNBitsUnused(int nbits){
int usefulbits = Long.SIZE - 1 -nbits;
}*/
}