io.cloudslang.engine.data.SimpleHiloIdentifierGenerator Maven / Gradle / Ivy
/*******************************************************************************
* (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License v2.0 which accompany this distribution.
*
* The Apache License is available at
* http://www.apache.org/licenses/LICENSE-2.0
*
*******************************************************************************/
package io.cloudslang.engine.data;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import javax.sql.DataSource;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by IntelliJ IDEA.
* User: froelica
* Date: 4/25/13
* Time: 11:03 AM
*/
public class SimpleHiloIdentifierGenerator implements IdentifierGenerator, IdentityGenerator {
private final Logger logger = Logger.getLogger(getClass());
static final String TABLE_NAME = "OO_HILO";
static final String SQL_SELECT = "SELECT NEXT_HI FROM " + TABLE_NAME;
static final String SQL_UPDATE = "UPDATE " + TABLE_NAME + " SET NEXT_HI = NEXT_HI+1";
static final String SQL_LOCK = "UPDATE " + TABLE_NAME + " SET NEXT_HI = NEXT_HI";
static final long CHUNK_SIZE = 100000L;
private static DataSource dataSource;
private int currentChunk;
private long currentId;
private Lock lock = new ReentrantLock();
// been initialized by Hibernate
public SimpleHiloIdentifierGenerator() {
updateCurrentChunk();
}
public static void setDataSource(DataSource injectedDataSource) {
dataSource = injectedDataSource;
}
@Override
public Long next() {
return (Long) generate(null, null);
}
@Override
public List bulk(int bulkSize) {
List idsList = new ArrayList<>();
for (int i = 0; i < bulkSize; i++) {
idsList.add(next());
}
return idsList;
}
@Override
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
lock.lock();
try {
long id = ++currentId;
if (id > CHUNK_SIZE) {
if (logger.isDebugEnabled()) logger.debug("ID has reached chunk size");
updateCurrentChunk();
id = ++currentId;
}
return currentChunk * CHUNK_SIZE + id;
} finally {
lock.unlock();
}
}
private void updateCurrentChunk() {
if (logger.isDebugEnabled()) {
logger.debug("Updating HILO chunk...");
}
long t = System.currentTimeMillis();
try (Connection conn = dataSource.getConnection()) {
conn.setAutoCommit(false);
JdbcTemplate jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn, true));
jdbcTemplate.update(SQL_LOCK);
currentChunk = jdbcTemplate.queryForObject(SQL_SELECT, Integer.class);
if (logger.isDebugEnabled())
logger.debug("Current chunk: " + currentChunk);
jdbcTemplate.execute(SQL_UPDATE);
jdbcTemplate.execute("commit");
if (logger.isDebugEnabled()) {
logger.debug("Updating HILO chunk done in " + (System.currentTimeMillis() - t) + " ms");
}
currentId = 0;
} catch (SQLException e) {
logger.error("Unable to update current chunk", e);
throw new IllegalStateException("Unable to update current chunk");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy