All pastes #20974 Raw Edit

Miscellany

public java v1 · immutable
#20974 ·published 2005-08-24 12:27 UTC
rendered paste body
public class IdFactory{	private static Logger _log = Logger.getLogger(IdFactory.class.getName());	private static final int STACK_SIZE_INCREMENT = 8196;    private AtomicInteger freeIdCount;    private AtomicInteger nextFreeId;    private static int newFreeID;		private static String[] id_updates = 	{		"UPDATE items                SET owner_id = ?    WHERE owner_id = ?",		"UPDATE items                SET object_id = ?   WHERE object_id = ?",        "UPDATE character_quests     SET char_id = ?     WHERE char_id = ?",		"UPDATE character_recipebook SET char_id = ?     WHERE char_id = ?",		"UPDATE character_shortcuts  SET char_obj_id = ? WHERE char_obj_id = ?",		"UPDATE character_shortcuts  SET shortcut_id = ? WHERE shortcut_id = ? AND type = 1", // items		"UPDATE character_macroses   SET char_obj_id = ? WHERE char_obj_id = ?",		"UPDATE character_skills     SET char_obj_id = ? WHERE char_obj_id = ?",		"UPDATE characters           SET obj_Id = ?      WHERE obj_Id = ?",		"UPDATE characters           SET clanid = ?      WHERE clanid = ?",		"UPDATE clan_data            SET clan_id = ?     WHERE clan_id = ?",		"UPDATE clan_data            SET ally_id = ?     WHERE ally_id = ?",		"UPDATE clan_data            SET leader_id = ?   WHERE leader_id = ?",		"UPDATE pets                 SET item_obj_id = ? WHERE item_obj_id = ?",	};	private static String[] id_checks = 	{		"SELECT object_id   FROM items                WHERE object_id >= ?   AND object_id < ?",		"SELECT owner_id    FROM items                WHERE object_id >= ?   AND object_id < ?",		"SELECT char_id     FROM character_quests     WHERE char_id >= ?     AND char_id < ?",		"SELECT char_id     FROM character_recipebook WHERE char_id >= ?     AND char_id < ?",		"SELECT char_obj_id FROM character_shortcuts  WHERE char_obj_id >= ? AND char_obj_id < ?",		"SELECT char_obj_id FROM character_macroses   WHERE char_obj_id >= ? AND char_obj_id < ?",		"SELECT char_obj_id FROM character_skills     WHERE char_obj_id >= ? AND char_obj_id < ?",		"SELECT obj_Id      FROM characters           WHERE obj_Id >= ?      AND obj_Id < ?",		"SELECT clanid      FROM characters           WHERE clanid >= ?      AND clanid < ?",		"SELECT clan_id     FROM clan_data            WHERE clan_id >= ?     AND clan_id < ?",		"SELECT ally_id     FROM clan_data            WHERE ally_id >= ?     AND ally_id < ?",		"SELECT leader_id   FROM clan_data            WHERE leader_id >= ?   AND leader_id < ?",		"SELECT item_obj_id FROM pets                 WHERE item_obj_id >= ? AND item_obj_id < ?",	};	private int _curOID;	private int _tempOID;	private int[] _freeOIDs;	private int _freeSize;		private Stack<Integer> _freeOIDStack = new Stack<Integer>();		private boolean initialized;		private static int FIRST_OID   = 0x10000000;    private static int LAST_OID    = 0x7FFFFFFF;    	private static IdFactory _instance = new IdFactory();	private IdFactory()	{        if (Config.COMPACTION)        {            _curOID = FIRST_OID;            _tempOID = FIRST_OID;            _freeOIDs = new int[STACK_SIZE_INCREMENT];            _freeSize = 0;            java.sql.Connection con = null;            try            {                con = L2DatabaseFactory.getInstance().getConnection();                //con.createStatement().execute("drop table if exists tmp_obj_id");                                //create a temporary table                Statement s = con.createStatement();                try                {                    s.executeUpdate("drop table temporaryObjectTable");                }                catch (SQLException e)                {                    // TODO Auto-generated catch block                    //e.printStackTrace();                }                s.executeUpdate("create table temporaryObjectTable" + " (object_id int NOT NULL PRIMARY KEY)");                s.executeUpdate("insert into temporaryObjectTable (object_id)" + " select obj_id from characters");                s.executeUpdate("insert into temporaryObjectTable (object_id)" + " select object_id from items");                s.executeUpdate("insert into temporaryObjectTable (object_id)" + " select clan_id from clan_data");                ResultSet result = s.executeQuery("select count(object_id) from temporaryObjectTable ORDER BY object_id");                result.next();                int size = result.getInt(1);                int[] tmp_obj_ids = new int[size];                // System.out.println("tmp table size: " + tmp_obj_ids.length);                result.close();                result = s.executeQuery("select object_id from temporaryObjectTable ORDER BY object_id");                int idx = 0;                while (result.next())                {                    tmp_obj_ids[idx++] = result.getInt(1);                }                _curOID = tmp_obj_ids[size-1];                System.out.println("Max Id = " + _curOID);                result.close();                s.close();                                int N = tmp_obj_ids.length;                for (idx = 0; idx < N; idx++)                {                	//long time1 = System.currentTimeMillis();                    N = insertUntil(tmp_obj_ids, idx, N, con);                   // if (System.currentTimeMillis() - time1 > 0)                   // 	System.out.println("T1:  " + (System.currentTimeMillis() - time1));                }                _curOID++;                _log.config("IdFactory: Next usable Object ID is: " + _curOID);                initialized = true;            }            catch (Exception e1)            {				e1.printStackTrace();                _log.severe("ID Factory could not be initialized correctly:" + e1);            }            finally            {                try { con.close(); } catch (Exception e) {}            }        }        else        {            initialize();            _log.info("IDFactory: "+ freeIds.size() + " id's avaliable.");        }                //setFreeIds();        // _log.info("IDFactory: "+ freeIds.size() + " id's avaliable.");                java.sql.Connection con2 = null;        try            {                con2 = L2DatabaseFactory.getInstance().getConnection();                Statement s2 = con2.createStatement();                s2.executeUpdate("update characters set online=0");        	_log.info("Updated characters online status.");            }        catch (SQLException e)            {            }        finally            {                try { con2.close(); } catch (Exception e) {}            }	}        private IdFactory(int i) {}    /**     * @param con     * @return     * @throws SQLException     */    private int[] extractUsedObjectIDTable(java.sql.Connection con) throws SQLException    {        // create a temporary table        Statement s = con.createStatement();        s.executeUpdate("drop table if exists tmp_obj_id");        s.executeUpdate("create table tmp_obj_id (object_id int NOT NULL PRIMARY KEY)");        s.executeUpdate("insert into tmp_obj_id (object_id) select obj_id from characters");        s.executeUpdate("insert into tmp_obj_id (object_id) select clan_id from clan_data");		s.executeUpdate("update items i left join tmp_obj_id t on (i.object_id = t.object_id) set i.object_id = i.object_id + 200000000 where i.object_id IS NOT NULL AND t.object_id IS NOT NULL;");        s.executeUpdate("insert into tmp_obj_id (object_id) select object_id from items");        ResultSet result = s.executeQuery("select count(object_id) from tmp_obj_id ORDER BY object_id");        result.next();        int[] tmp_obj_ids = new int[result.getInt(1)];        // System.out.println("tmp table size: " + tmp_obj_ids.length);        result.close();        result = s.executeQuery("select object_id from tmp_obj_id ORDER BY object_id");        int idx = 0;        while (result.next())        {            tmp_obj_ids[idx++] = result.getInt(1);        }        result.close();        s.close();        return tmp_obj_ids;    }        public static void main(String[] args)    {        System.out.println("Commencing Database Reindexing.");        new IdFactory(1).reindex();        System.out.println("Finished Reindexing Database.");    }        public void reindex()    {        newFreeID   = FIRST_OID;                java.sql.Connection con = null;        try        {            con = L2DatabaseFactory.getInstance().getConnection();                        // create a temporary table            int[] objectIds = extractUsedObjectIDTable(con);            ArrayList<Integer> objectIDList = new ArrayList<Integer>();            for (Integer oId: objectIds)            {                objectIDList.add(oId);            }                        reindexCharacterIds(con, objectIDList);            reindexPetItemIds(con, objectIDList);        }        catch (Exception e1)        {            _log.severe("ID Factory could not be initialized correctly (2):" + e1);			e1.printStackTrace();        }        finally        {            try { con.close(); } catch (Exception e) {}        }    }    /**     * @param con     * @param objectIDList     */    private static void reindexPetItemIds(Connection con, ArrayList<Integer> objectIDList) throws SQLException    {        System.out.println("Reindexing Pet Items.");        Statement s = con.createStatement();        ResultSet result = s.executeQuery("select count(item_obj_id) from pets");        result.next();        int[] characterIds = new int[result.getInt(1)];        result.close();        result = s.executeQuery("select item_obj_id from pets ORDER BY item_obj_id");        int idx = 0;        while (result.next())        {            characterIds[idx++] = result.getInt(1);        }        result.close();        int[] chars = {1,13};        for (Integer oldOID : characterIds)        {            //System.out.println("Reindexing Character ID: "+oldOID+".");            for (Integer updateId : chars)            {                String update   = id_updates[updateId];                newFreeID       = getNextUnusedID(objectIDList, newFreeID);                PreparedStatement ps = con.prepareStatement(update);                ps.setInt(1, oldOID);                ps.setInt(2, newFreeID);                ps.execute();                ps.close();                objectIDList.remove(oldOID);            }            System.out.println("Reindexed Pet Item from Old ID: "+oldOID+"\tto New ID: "+newFreeID+".");        }        System.out.println("Finished Reindexing Pet Items.");    }    /**     * @param newFreeID     * @param con     * @param objectIds     * @throws SQLException     */    private static void reindexCharacterIds(java.sql.Connection con, ArrayList<Integer> objectIDList) throws SQLException    {        System.out.println("Reindexing Characters.");        Statement s = con.createStatement();        ResultSet result = s.executeQuery("select count(obj_id) from characters ORDER BY obj_id");        result.next();        int[] characterIds = new int[result.getInt(1)];        result.close();        result = s.executeQuery("select obj_id from characters ORDER BY obj_id");        int idx = 0;        while (result.next())        {            characterIds[idx++] = result.getInt(1);        }        result.close();        int[] chars = {0,2,3,4,6,7,8,12};        for (Integer oldOID : characterIds)        {            //System.out.println("Reindexing Character ID: "+oldOID+".");            for (Integer updateId : chars)            {                String update   = id_updates[updateId];                newFreeID       = getNextUnusedID(objectIDList, newFreeID);                PreparedStatement ps = con.prepareStatement(update);                ps.setInt(1, oldOID);                ps.setInt(2, newFreeID);                ps.execute();                ps.close();                objectIDList.remove(oldOID);            }            System.out.println("Reindexed Character from Old ID: "+oldOID+"\tto New ID: "+newFreeID+".");        }        System.out.println("Finished Reindexing Characters.");    }        private static int getNextUnusedID(ArrayList<Integer> objectIDList, int startIndex)    {        int id  = startIndex+1;                while (id <= LAST_OID)        {            if (!objectIDList.contains(id))            {                return id;            }            id++;        }                return -1;    }	public boolean isInitialized() {		return initialized;	}		private int insertUntil(int[] tmp_obj_ids, int idx, int N,            java.sql.Connection con) throws SQLException    {        int id = tmp_obj_ids[idx];        if (id == _tempOID)        {        	_tempOID++;            return N;        }        /*if (id == _curOID)        {            _curOID++;            return N;        }*/        // check these IDs not present in DB        for (String check : id_checks)        {            PreparedStatement ps = con.prepareStatement(check);            ps.setInt(1, _tempOID);            //ps.setInt(1, _curOID);            ps.setInt(2, id);            ResultSet rs = ps.executeQuery();            while (rs.next())            {                int badId = rs.getInt(1);                _log.severe("Bad ID " + badId + " in DB found by: " + check);                throw new RuntimeException();            }            rs.close();            ps.close();        }        //int hole = id - _curOID;        int hole = id - _tempOID;        if (hole > N - idx) hole = N - idx;        for (int i = 1; i <= hole; i++)        {        	//long time1 = System.currentTimeMillis();            id = tmp_obj_ids[N - i];            //System.out.println("Compacting DB object ID=" + id + " into " + (_curOID));           /* for (String update : id_updates)            {                PreparedStatement ps = con.prepareStatement(update);                ps.setInt(1, _tempOID);                //ps.setInt(1, _curOID);                ps.setInt(2, id);                ps.execute();                ps.close();            }*/            System.out.println("Free ID added " + (_tempOID));            _freeOIDStack.push(_tempOID);            _tempOID++;            //_curOID++;          //  System.out.println("T2:  " + (System.currentTimeMillis() - time1));        }        //if (hole < N - idx) _curOID++;        if (hole < N - idx) _tempOID++;       // return N - hole;        return N - hole;    }		public static IdFactory getInstance()	{        return _instance;	}	public synchronized int getNextId()    {        /*if (Config.COMPACTION)        {            if (_freeSize == 0)                return _curOID++;            else                return _freeOIDs[--_freeSize];        }        else        {*/        	int id;        	if (!_freeOIDStack.empty())        		id = _freeOIDStack.pop();        	else        	{        		id = _curOID;        		_curOID = _curOID+1;        	}        	System.out.println("Next id = " + id);        	return id;        	           /* int newID       = nextFreeId.get();            int nextFree    = freeIds.nextClearBit(newID);            if (nextFree < 0)                nextFree    = freeIds.nextClearBit(0);            if (nextFree < 0)                throw new NullPointerException("Ran out of valid Id's.");            nextFreeId.set(nextFree);                        return newID + FIRST_OID;*/       // }    }		/**	 * return a used Object ID back to the pool	 * @param object ID	 */	public synchronized void releaseId(int id)    {       /* if (Config.COMPACTION)        {            if (_freeSize >= _freeOIDs.length)            {                int[] tmp = new int[_freeSize + STACK_SIZE_INCREMENT];                System.arraycopy(_freeOIDs, 0, tmp, 0, _freeSize);                _freeOIDs = tmp;            }            _freeOIDs[_freeSize++] = id;        }        else if (id >= FIRST_OID)        {            freeIds.clear(id-FIRST_OID);            freeIdCount.incrementAndGet();        }*/		_freeOIDStack.push(id);		System.out.println("Released id: " + id);    }        public int size()    {        if (!Config.COMPACTION)        {            return freeIdCount.get();        }                return _freeSize + LAST_OID - FIRST_OID;    }        private BitSet freeIds  = null;        public void initialize()    {        try        {            freeIds = new BitSet(LAST_OID - FIRST_OID);            freeIdCount = new AtomicInteger(freeIds.size());                        nextFreeId  = new AtomicInteger(0);            freeIds.set(0);            //for (int objectID = FIRST_OID; objectID <= LAST_OID; objectID++)            //{            //    freeIds.s(objectID);            //}            initialized = true;        }        catch (Exception e)        {            initialized = false;            e.printStackTrace();        }    }    /**     * @param id     */    public synchronized void setObjectIDAsUsed(int id)    {        if (id >= FIRST_OID && !Config.COMPACTION)        {            freeIds.set(id-FIRST_OID);            freeIdCount.decrementAndGet();        }    }}