/* $Id: IDFactory.java 988245 2010-08-23 18:39:35Z kwright $ */ /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.manifoldcf.core.interfaces; import org.apache.manifoldcf.core.system.ManifoldCF; import org.apache.manifoldcf.core.system.Logging; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.*; /** The purpose of this class is to create global unique identifiers. For performance, every JVM has a local pool of identifiers as well * as there being a global system of identifier creation, which is also resilient against entire system restarts. */ public class IDFactory { public static final String _rcsid = "@(#)$Id: IDFactory.java 988245 2010-08-23 18:39:35Z kwright $"; private static ArrayList idPool = new ArrayList(); // The id algorithm depends on the clock. We don't want to fetch too many; we'll // run the risk of a restart in the non-synchronized case beating the clock. private final static int poolSize = 100; /** This is the critical section name */ private final static String criticalSectionName = "_IDFACTORY_"; /** This is the global lock name */ private final static String globalLockName = "_IDFACTORY_"; /** This is the name of the global ID data object */ private final static String globalIDDataName = "_IDFACTORY_"; private IDFactory() { } public static String make(IThreadContext tc) throws ManifoldCFException { ILockManager lockManager = LockManagerFactory.make(tc); // Enter critical section before we look at the pool lockManager.enterWriteCriticalSection(criticalSectionName); try { // check the pool if (idPool.size() == 0) { // Pool was empty. We need to grab more id's from the global resource. lockManager.enterWriteLock(globalLockName); try { // Read shared data byte[] idData = lockManager.readData(globalIDDataName); long _id; if (idData == null) _id = 0L; else _id = new Long(new String(idData, StandardCharsets.UTF_8)).longValue(); int i = 0; while (i < poolSize) { long newid = System.currentTimeMillis(); if (newid <= _id) { newid = _id + 1; } _id = newid; idPool.add(Long.toString(newid)); i++; } lockManager.writeData(globalIDDataName,Long.toString(_id).getBytes(StandardCharsets.UTF_8)); } finally { lockManager.leaveWriteLock(globalLockName); } } return (String)idPool.remove(idPool.size()-1); } finally { lockManager.leaveWriteCriticalSection(criticalSectionName); } } }