com.l2jfree.gameserver.idfactory.IdFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.l2jfree.gameserver.idfactory.IdFactory.java

Source

/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jfree.gameserver.idfactory;

import gnu.trove.TIntArrayList;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.l2jfree.Config;
import com.l2jfree.L2DatabaseFactory;
import com.l2jfree.gameserver.util.TableOptimizer;
import com.l2jfree.gameserver.util.TableOptimizer.CharacterRelatedTable;
import com.l2jfree.gameserver.util.TableOptimizer.ItemRelatedTable;

/**
 * This class ...
 * 
 * @version $Revision: 1.3.2.1.2.7 $ $Date: 2005/04/11 10:06:12 $
 */
public abstract class IdFactory {
    private final static Log _log = LogFactory.getLog(IdFactory.class);

    protected static final String[] ID_UPDATES = {
            "UPDATE items                 SET owner_id = ?    WHERE owner_id = ?",
            "UPDATE items                 SET object_id = ?   WHERE object_id = ?",
            "UPDATE character_quests      SET charId = ?      WHERE charId = ?",
            "UPDATE character_blocks      SET charId = ?      WHERE charId = ?",
            "UPDATE character_friends     SET charId1 = ?     WHERE charId1 = ?",
            "UPDATE character_friends     SET charId2 = ?     WHERE charId2 = ?",
            "UPDATE character_hennas      SET charId = ?      WHERE charId = ?",
            "UPDATE character_recipebook  SET charId = ?      WHERE charId = ?",
            "UPDATE character_shortcuts   SET charId = ?      WHERE charId = ?",
            "UPDATE character_shortcuts   SET shortcut_id = ? WHERE shortcut_id = ? AND type = 1", // items
            "UPDATE character_macroses    SET charId = ?      WHERE charId = ?",
            "UPDATE character_skills      SET charId = ?      WHERE charId = ?",
            "UPDATE character_subclasses  SET charId = ?      WHERE charId = ?",
            "UPDATE characters            SET charId = ?      WHERE charId = ?",
            "UPDATE characters            SET clanid = ?      WHERE clanid = ?",
            "UPDATE clan_data             SET clan_id = ?     WHERE clan_id = ?",
            "UPDATE siege_clans           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 = ?",
            // Added by DaDummy
            "UPDATE auction_bid          SET bidderId = ?      WHERE bidderId = ?",
            "UPDATE character_hennas     SET charId = ?        WHERE charId = ?",
            "UPDATE clan_wars            SET clan1 = ?         WHERE clan1 = ?",
            "UPDATE clan_wars            SET clan2 = ?         WHERE clan2 = ?",
            "UPDATE clanhall             SET ownerId = ?       WHERE ownerId = ?",
            "UPDATE petitions            SET charId = ?        WHERE charId = ?",
            "UPDATE posts                SET post_ownerid = ?  WHERE post_ownerid = ?",
            "UPDATE seven_signs          SET charId = ?        WHERE charId = ?",
            "UPDATE topic                SET topic_ownerid = ? WHERE topic_ownerid = ?",
            "UPDATE itemsonground        SET object_id = ?     WHERE object_id = ?",
            // Added by GDL
            "UPDATE olympiad_nobles          SET charId = ?         WHERE charId = ?",
            "UPDATE clan_privs               SET clan_id = ?        WHERE clan_id = ?",
            "UPDATE clan_skills              SET clan_id = ?        WHERE clan_id = ?",
            "UPDATE clan_subpledges          SET clan_id = ?        WHERE clan_id = ?",
            "UPDATE character_effects        SET charId = ?         WHERE charId = ?",
            "UPDATE character_recommends     SET charId = ?         WHERE charId = ?",
            "UPDATE character_recommends     SET target_id = ?      WHERE target_id = ?",
            "UPDATE character_raid_points     SET charId = ?       WHERE charId = ?",
            "UPDATE character_skill_reuses   SET charId = ?         WHERE charId = ?",
            "UPDATE couples                  SET id = ?             WHERE id = ?",
            "UPDATE couples                  SET player1Id = ?      WHERE player1Id = ?",
            "UPDATE couples                  SET player2Id = ?      WHERE player2Id = ?",
            "UPDATE cursed_weapons           SET playerId = ?       WHERE playerId = ?",
            "UPDATE forums                   SET forum_owner_id = ? WHERE forum_owner_id = ?",
            "UPDATE heroes                   SET charId = ?         WHERE charId = ?" };

    protected static final String[] ID_CHECKS = {
            "SELECT owner_id    FROM items                 WHERE object_id >= ?   AND object_id < ?",
            "SELECT object_id   FROM items                 WHERE object_id >= ?   AND object_id < ?",
            "SELECT charId      FROM character_quests      WHERE charId >= ?      AND charId < ?",
            "SELECT charId      FROM character_blocks      WHERE charId >= ?      AND charId < ?",
            "SELECT charId      FROM character_effects     WHERE charId >= ?      AND charId < ?",
            "SELECT charId1     FROM character_friends     WHERE charId1 >= ?     AND charId1 < ?",
            "SELECT charId2     FROM character_friends     WHERE charId2 >= ?     AND charId2 < ?",
            "SELECT charId      FROM character_hennas      WHERE charId >= ?      AND charId < ?",
            "SELECT charId      FROM character_recipebook  WHERE charId >= ?      AND charId < ?",
            "SELECT charId      FROM character_shortcuts   WHERE charId >= ?      AND charId < ?",
            "SELECT charId      FROM character_macroses    WHERE charId >= ?      AND charId < ?",
            "SELECT charId      FROM character_skill_reuses WHERE charId >= ?     AND charId < ?",
            "SELECT charId      FROM character_skills      WHERE charId >= ?      AND charId < ?",
            "SELECT charId      FROM character_subclasses  WHERE charId >= ?      AND charId < ?",
            "SELECT charId      FROM characters            WHERE charId >= ?      AND charId < ?",
            "SELECT clanid      FROM characters            WHERE clanid >= ?      AND clanid < ?",
            "SELECT clan_id     FROM clan_data             WHERE clan_id >= ?     AND clan_id < ?",
            "SELECT clan_id     FROM siege_clans           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 < ?",
            // Added by DaDummy
            "SELECT charId      FROM seven_signs           WHERE charId >= ?      AND charId < ?",
            "SELECT object_id   FROM itemsonground         WHERE object_id >= ?   AND object_id < ?" };

    private static final String[] TIMESTAMPS_CLEAN = { "DELETE FROM character_instance_time WHERE time <= ?",
            "DELETE FROM character_skill_reuses WHERE expiration <= ?" };

    protected boolean _initialized;

    public static final int FIRST_OID = 0x10000000;
    public static final int LAST_OID = 0x7FFFFFFF;
    public static final int FREE_OBJECT_ID_SIZE = LAST_OID - FIRST_OID;

    protected static IdFactory _instance = null;

    protected IdFactory() {
        setAllCharacterOffline();
        cleanUpDB();
        cleanUpTimeStamps();
    }

    static {
        switch (Config.IDFACTORY_TYPE) {
        case BitSet:
            _instance = new BitSetIDFactory();
            break;
        case Stack:
            _instance = new StackIDFactory();
            break;
        case Increment:
            _instance = new IncrementIDFactory();
            break;
        case Rebuild:
            _instance = new BitSetRebuildFactory();
            break;
        }
    }

    /**
     * Sets all character offline
     */
    protected void setAllCharacterOffline() {
        Connection con = null;
        try {
            con = L2DatabaseFactory.getInstance().getConnection(con);
            Statement s2 = con.createStatement();
            s2.executeUpdate("UPDATE characters SET online = 0;");
            if (_log.isDebugEnabled())
                _log.debug("Updated characters online status.");
            s2.close();
        } catch (SQLException e) {
            _log.warn("", e);
        } finally {
            L2DatabaseFactory.close(con);
        }
    }

    /**
     * Cleans up Database
     */
    protected void cleanUpDB() {
        // TODO:
        // Check for more cleanup query
        // Check order

        Connection con = null;
        try {
            int cleanCount = 0;
            con = L2DatabaseFactory.getInstance().getConnection(con);
            Statement stmt = con.createStatement();

            // If a character not exists
            for (CharacterRelatedTable table : TableOptimizer.getCharacterRelatedTables()) {
                cleanCount += stmt.executeUpdate(table.getCleanQuery());
            }

            cleanCount += stmt.executeUpdate(
                    "DELETE FROM clan_data WHERE clan_data.leader_id NOT IN (SELECT charId FROM characters) AND clan_data.clan_id != 6619248;");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM items WHERE loc <> 'clanwh' and items.owner_id NOT IN (SELECT charId FROM characters);");

            // If a clan not exists
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM auction_bid WHERE auction_bid.bidderId NOT IN (SELECT clan_id FROM clan_data);");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM clan_privs WHERE clan_privs.clan_id NOT IN (SELECT clan_id FROM clan_data);");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM clan_skills WHERE clan_skills.clan_id NOT IN (SELECT clan_id FROM clan_data);");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM clan_subpledges WHERE clan_subpledges.clan_id NOT IN (SELECT clan_id FROM clan_data);");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM clan_wars WHERE clan_wars.clan1 NOT IN (SELECT clan_id FROM clan_data) OR clan_wars.clan2 NOT IN (SELECT clan_id FROM clan_data);");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM forums WHERE forum_owner_id <> 0 AND forums.forum_owner_id NOT IN (SELECT clan_id FROM clan_data);");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM items WHERE loc = 'clanwh' AND items.owner_id NOT IN (SELECT clan_id FROM clan_data);");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM siege_clans WHERE siege_clans.clan_id NOT IN (SELECT clan_id FROM clan_data);");

            stmt.executeUpdate(
                    "UPDATE characters SET `clanid`='0', `clan_privs`='0', `clan_join_expiry_time`='0', `clan_create_expiry_time`='0' WHERE characters.clanid NOT IN (SELECT clan_id FROM clan_data);");
            stmt.executeUpdate(
                    "UPDATE clan_subpledges SET leader_id=0 WHERE clan_subpledges.leader_id NOT IN (SELECT charId FROM characters) AND leader_id > 0;");
            stmt.executeUpdate(
                    "UPDATE clan_data SET ally_id=0 WHERE clan_data.ally_id NOT IN (SELECT clanid FROM characters WHERE clanid!=0 GROUP BY clanid);");
            stmt.executeUpdate(
                    "UPDATE clanhall SET ownerId=0, paidUntil=0, paid=0 WHERE clanhall.ownerId NOT IN (SELECT clan_id FROM clan_data);");

            // If the clanhall isn't free
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM auction WHERE auction.id IN (SELECT id FROM clanhall WHERE ownerId <> 0) AND auction.sellerId = 0;");
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM auction_bid WHERE auction_bid.auctionId IN (SELECT id FROM clanhall WHERE ownerId <> 0);");
            stmt.executeUpdate(
                    "UPDATE clan_data SET auction_bid_at = 0 WHERE auction_bid_at NOT IN (SELECT auctionId FROM auction_bid);");
            // If the clanhall is free
            cleanCount += stmt.executeUpdate(
                    "DELETE FROM clanhall_functions WHERE clanhall_functions.hall_id NOT IN (SELECT id FROM clanhall WHERE ownerId <> 0);");

            // If an item not exists
            for (ItemRelatedTable table : TableOptimizer.getItemRelatedTables()) {
                cleanCount += stmt.executeUpdate(table.getCleanQuery());
            }

            stmt.close();
            _log.info("Cleaned " + cleanCount + " elements from database.");
        } catch (SQLException e) {
            _log.error(e.getMessage(), e);
        } finally {
            L2DatabaseFactory.close(con);
        }
    }

    private void cleanUpTimeStamps() {
        Connection con = null;
        try {
            int cleanCount = 0;
            con = L2DatabaseFactory.getInstance().getConnection();
            PreparedStatement stmt;
            for (String line : TIMESTAMPS_CLEAN) {
                stmt = con.prepareStatement(line);
                stmt.setLong(1, System.currentTimeMillis());
                cleanCount += stmt.executeUpdate();
                stmt.close();
            }

            _log.info("Cleaned " + cleanCount + " expired timestamps from database.");
        } catch (SQLException e) {
        } finally {
            L2DatabaseFactory.close(con);
        }
    }

    /**
     * @return
     * @throws SQLException
     */
    protected final int[] extractUsedObjectIDTable() throws SQLException {
        Connection con = null;
        try {
            con = L2DatabaseFactory.getInstance().getConnection();

            Statement statement = con.createStatement();

            ResultSet rset = null;
            int count = 0;

            rset = statement.executeQuery("SELECT COUNT(*) FROM characters");
            rset.next();
            count += rset.getInt(1);

            rset = statement.executeQuery("SELECT COUNT(*) FROM items");
            rset.next();
            count += rset.getInt(1);

            rset = statement.executeQuery("SELECT COUNT(*) FROM clan_data");
            rset.next();
            count += rset.getInt(1);

            rset = statement.executeQuery("SELECT COUNT(*) FROM itemsonground");
            rset.next();
            count += rset.getInt(1);

            final TIntArrayList temp = new TIntArrayList(count);

            rset = statement.executeQuery("SELECT charId FROM characters");
            while (rset.next()) {
                temp.add(rset.getInt(1));
            }

            rset = statement.executeQuery("SELECT object_id FROM items");
            while (rset.next()) {
                temp.add(rset.getInt(1));
            }

            rset = statement.executeQuery("SELECT clan_id FROM clan_data");
            while (rset.next()) {
                temp.add(rset.getInt(1));
            }

            rset = statement.executeQuery("SELECT object_id FROM itemsonground");
            while (rset.next()) {
                temp.add(rset.getInt(1));
            }

            temp.sort();

            return temp.toNativeArray();
        } finally {
            L2DatabaseFactory.close(con);
        }
    }

    public boolean isInitialized() {
        return _initialized;
    }

    public static IdFactory getInstance() {
        return _instance;
    }

    public abstract int getNextId();

    /**
     * return a used Object ID back to the pool
     * @param id ID
     */
    public abstract void releaseId(int id);

    public abstract int getCurrentId();

    public abstract int size();
}