001/* 002 * Stallion Core: A Modern Web Framework 003 * 004 * Copyright (C) 2015 - 2016 Stallion Software LLC. 005 * 006 * This program is free software: you can redistribute it and/or modify it under the terms of the 007 * GNU General Public License as published by the Free Software Foundation, either version 2 of 008 * the License, or (at your option) any later version. This program is distributed in the hope that 009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 011 * License for more details. You should have received a copy of the GNU General Public License 012 * along with this program. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>. 013 * 014 * 015 * 016 */ 017 018package io.stallion.dataAccess; 019 020import io.stallion.settings.Settings; 021 022import java.util.concurrent.atomic.AtomicInteger; 023 024/** 025 * This generates unique IDs (unique within a particular stallion application) based on the current time. 026 * This is used in file based systems. 027 * 028 * Generates a unique ticket based on a counter, the current time rounded to nearest 10 seconds, and the node number. 029 * This will create duplicates if you need to generate more than 10,000 tickets in a second. 030 * This will also exceed the MAX_SAFE_INTEGER value for javascript around the year 2248. 031 * 032 * 033 */ 034public class TimebasedTickets implements Tickets { 035 private AtomicInteger i = new AtomicInteger(); 036 private Long baseSeconds = null; 037 private static int loadedCount = 0; 038 039 public TimebasedTickets() { 040 // If we reload tickets during a test, we need to start with a higher increment or else 041 // we will generate the same IDs over again. If we run more than 100 test cases with 042 // full app context reloads in a single 043 // second, then we might get duplicate IDs, but that is probably impossible 044 loadedCount++; 045 i.set(loadedCount * 1000); 046 } 047 048 049 050 051 /** 052 * 053 * 054 * @return 055 */ 056 @Override 057 public Long nextId() { 058 Integer counter = i.incrementAndGet(); 059 if (counter > 99500) { 060 i.set(0); 061 } 062 Long currentSeconds = System.currentTimeMillis() / 1000; 063 Long sec = currentSeconds - getBaseSeconds(); 064 Long ticket = ((sec) * 1000000) + (counter * 10) + Settings.instance().getNodeNumber(); 065 return ticket; 066 } 067 068 private Long getBaseSeconds() { 069 if (baseSeconds == null) { 070 baseSeconds = Settings.instance().getAppCreatedMillis() / 1000; 071 } 072 return baseSeconds; 073 } 074}