📄 sequencemgr.java~18~
字号:
package com.redmoon.forum;
import java.sql.*;
import cn.js.fan.web.Global;
import org.apache.log4j.Logger;
import cn.js.fan.db.Conn;
public class SequenceMgr {
String connname;
Logger logger = Logger.getLogger(SequenceMgr.class.getName());
private static final String LOAD_ID =
"SELECT id FROM sq_id WHERE idType=?";
private static final String UPDATE_ID =
"UPDATE sq_id SET id=? WHERE idType=? AND id=?";
public static int MSG = 0;
public static int DOCUMENT = 1;
public static int AuctionOrderId = 2;
public static int ShopId = 3;
public static int SQ_CHATROOM = 4;
public static int SQ_FRIEND = 5;
public static int SQ_MASTER = 6;
public static int SQ_MESSAGE_ATTACH = 7;
public static int SQ_USER = 8;
public static int DOCUMENT_ATTACH = 9;
public static int COMMENT = 10;
public static int PHOTO = 11;
public static int SQ_FORBID_IP_RANGE = 12;
/**
* The number of ID's to checkout at a time. 15 should provide a good
* balance between speed and not wasing too many ID's on appserver restarts.
* Feel free to change this number if you believe your Jive setup warrants
* it.
*/
private static final int INCREMENT = 10;
// Statically startup a sequence manager for each of the five sequence
// counters.
private static SequenceMgr[] managers;
static {
managers = new SequenceMgr[13];
for (int i=0; i<managers.length; i++) {
managers[i] = new SequenceMgr(i);
}
}
/**
* Returns the next ID of the specified type.
*
* @param type the type of unique ID.
* @return the next unique ID of the specified type.
*/
public static long nextID(int type) {
return managers[type].nextUniqueID();
}
public static long nextID() {
return managers[0].nextUniqueID();
}
private int type;
private long currentID;
private long maxID;
/**
* Creates a new DbSequenceManager.
*/
public SequenceMgr(int type) {
connname = Global.defaultDB;
if (connname.equals(""))
logger.info("SequenceMgr:默认数据库名为空!");
this.type = type;
currentID = 0l;
maxID = 0l;
}
/**
* Returns the next available unique ID. Essentially this provides for the
* functionality of an auto-increment database field.
*/
public synchronized long nextUniqueID() {
if (! (currentID < maxID)) {
// Get next block -- make 5 attempts at maximum.
getNextBlock(5);
}
long id = currentID;
currentID++;
return id;
}
/**
* Performs a lookup to get the next availabe ID block. The algorithm is as
* follows:<ol>
* <li> Select currentID from appropriate db row.
* <li> Increment id returned from db.
* <li> Update db row with new id where id=old_id.
* <li> If update fails another process checked out the block first; go
* back to step 1. Otherwise, done.
* </ol>
*/
private void getNextBlock(int count) {
if (count == 0) {
System.err.println("Failed at last attempt to obtain an ID, aborting...");
return;
}
boolean success = false;
Conn conn = new Conn(connname);
PreparedStatement pstmt = null;
try {
// Get the current ID from the database.
pstmt = conn.prepareStatement(LOAD_ID);
pstmt.setInt(1, type);
ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
throw new SQLException("Loading the current ID failed. The " +
"redmoon_id table may not be correctly populated.");
}
long currentID = rs.getLong(1);
pstmt.close();
// Increment the id to define our block.
long newID = currentID + INCREMENT;
// The WHERE clause includes the last value of the id. This ensures
// that an update will occur only if nobody else has performed an
// update first.
pstmt = conn.prepareStatement(UPDATE_ID);
pstmt.setLong(1, newID);
pstmt.setInt(2, type);
pstmt.setLong(3, currentID);
// Check to see if the row was affected. If not, some other process
// already changed the original id that we read. Therefore, this
// round failed and we'll have to try again.
success = pstmt.executeUpdate() == 1;
if (success) {
this.currentID = currentID;
this.maxID = newID;
}
}
catch( Exception sqle ) {
sqle.printStackTrace();
}
finally {
try { pstmt.close(); }
catch (Exception e) { e.printStackTrace(); }
if (conn!=null) {
conn.close(); conn = null;
}
}
if (!success) {
logger.warn("WARNING: failed to obtain next ID block due to " +
"thread contention. Trying again...");
// Call this method again, but sleep briefly to try to avoid thread
// contention.
try {
Thread.currentThread().sleep(75);
} catch (InterruptedException ie) {
logger.error(ie.getMessage());
}
getNextBlock(count-1);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -