⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idbroker.java

📁 另外一种持久性o/m软件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
            .append(" where ")            .append(TABLE_NAME).append("='").append(tableName).append('\'')            .toString();        boolean exists = false;        Connection dbCon = null;        try        {            String databaseName = tableMap.getDatabaseMap().getName();            dbCon = Torque.getConnection(databaseName);            Statement statement = dbCon.createStatement();            ResultSet rs = statement.executeQuery(query);            exists = rs.next();            statement.close();        }        finally        {            // Return the connection to the pool.            try            {                dbCon.close();            }            catch (Exception e)            {                log.error("Release of connection failed.", e);            }        }        return exists;    }    /**     * A background thread that tries to ensure that when someone asks     * for ids, that there are already some loaded and that the     * database is not accessed.     */    public void run()    {        log.debug("IDBroker thread was started.");        Thread thisThread = Thread.currentThread();        while (houseKeeperThread == thisThread)        {            try            {                Thread.sleep(SLEEP_PERIOD);            }            catch (InterruptedException exc)            {                // ignored            }            // logger.info("IDBroker thread checking for more keys.");            Iterator it = ids.keySet().iterator();            while (it.hasNext())            {                String tableName = (String) it.next();                if (log.isDebugEnabled())                {                    log.debug("IDBroker thread checking for more keys "                            + "on table: " + tableName);                }                List availableIds = (List) ids.get(tableName);                int quantity = getQuantity(tableName, null).intValue();                if (quantity > availableIds.size())                {                    try                    {                        // Second parameter is false because we don't                        // want the quantity to be adjusted for thread                        // calls.                        storeIDs(tableName, false, null);                        if (log.isDebugEnabled())                        {                            log.debug("Retrieved more ids for table: " + tableName);                        }                    }                    catch (Exception exc)                    {                        log.error("There was a problem getting new IDs "                                     + "for table: " + tableName, exc);                    }                }            }        }        log.debug("IDBroker thread finished.");    }    /**     * Shuts down the IDBroker thread.     *     * Calling this method stops the thread that was started for this     * instance of the IDBroker. This method should be called during     * MapBroker Service shutdown.     */    public void stop()    {        houseKeeperThread = null;    }    /**     * Check the frequency of retrieving new ids from the database.     * If the frequency is high then we increase the amount (i.e.     * quantity column) of ids retrieved on each access.  Tries to     * alter number of keys grabbed so that IDBroker retrieves a new     * set of ID's prior to their being needed.     *     * @param tableName The name of the table for which we want an id.     */    private void checkTiming(String tableName)    {        // Check if quantity changing is switched on.        // If prefetch is turned off, changing quantity does not make sense        if (!configuration.getBoolean(DB_IDBROKER_CLEVERQUANTITY, true)            || !configuration.getBoolean(DB_IDBROKER_PREFETCH, true))        {            return;        }        // Get the last id request for this table.        java.util.Date lastTime = (java.util.Date) lastQueryTime.get(tableName);        java.util.Date now = new java.util.Date();        if (lastTime != null)        {            long thenLong = lastTime.getTime();            long nowLong = now.getTime();            int timeLapse = (int) (nowLong - thenLong);            if (timeLapse < SLEEP_PERIOD && timeLapse > 0)            {                if (log.isDebugEnabled())                {                    log.debug("Unscheduled retrieval of more ids for table: "                            + tableName);                }                // Increase quantity, so that hopefully this does not                // happen again.                float rate = getQuantity(tableName, null).floatValue()                    / (float) timeLapse;                quantityStore.put(tableName, new BigDecimal(                    Math.ceil(SLEEP_PERIOD * rate * SAFETY_MARGIN)));            }        }        lastQueryTime.put(tableName, now);    }    /**     * Grabs more ids from the id_table and stores it in the ids     * Hashtable.  If adjustQuantity is set to true the amount of id's     * retrieved for each call to storeIDs will be adjusted.     *     * @param tableName The name of the table for which we want an id.     * @param adjustQuantity True if amount should be adjusted.     * @param connection a Connection     * @exception Exception a generic exception.     */    private synchronized void storeIDs(String tableName,                          boolean adjustQuantity,                          Connection connection)        throws Exception    {        BigDecimal nextId = null;        BigDecimal quantity = null;        DatabaseMap dbMap = tableMap.getDatabaseMap();        // Block on the table.  Multiple tables are allowed to ask for        // ids simultaneously.        //        TableMap tMap = dbMap.getTable(tableName);        //        synchronized(tMap)  see comment in the getNextIds method        //        {        if (adjustQuantity)        {            checkTiming(tableName);        }        boolean useNewConnection = (connection == null) || (configuration                .getBoolean(DB_IDBROKER_USENEWCONNECTION, true));        try        {            if (useNewConnection)            {                connection = Transaction.beginOptional(dbMap.getName(),                    transactionsSupported);            }            // Write the current value of quantity of keys to grab            // to the database, primarily to obtain a write lock            // on the table/row, but this value will also be used            // as the starting value when an IDBroker is            // instantiated.            quantity = getQuantity(tableName, connection);            updateQuantity(connection, tableName, quantity);            // Read the next starting ID from the ID_TABLE.            BigDecimal[] results = selectRow(connection, tableName);            nextId = results[0]; // NEXT_ID column            // Update the row based on the quantity in the            // ID_TABLE.            BigDecimal newNextId = nextId.add(quantity);            updateNextId(connection, tableName, newNextId.toString());            if (useNewConnection)            {                Transaction.commit(connection);            }        }        catch (Exception e)        {            if (useNewConnection)            {                Transaction.rollback(connection);            }            throw e;        }        List availableIds = (List) ids.get(tableName);        if (availableIds == null)        {            availableIds = new ArrayList();            ids.put(tableName, availableIds);        }        // Create the ids and store them in the list of available ids.        int numId = quantity.intValue();        for (int i = 0; i < numId; i++)        {            availableIds.add(nextId);            nextId = nextId.add(ONE);        }        //        }    }    /**     * This method allows you to get the number of ids that are to be     * cached in memory.  This is either stored in quantityStore or     * read from the db. (ie the value in ID_TABLE.QUANTITY).     *     * Though this method returns a BigDecimal for the quantity, it is     * unlikey the system could withstand whatever conditions would lead     * to really needing a large quantity, it is retrieved as a BigDecimal     * only because it is going to be added to another BigDecimal.     *     * @param tableName The name of the table we want to query.     * @param connection a Connection     * @return An int with the number of ids cached in memory.     */    private BigDecimal getQuantity(String tableName, Connection connection)    {        BigDecimal quantity = null;        // If prefetch is turned off we simply return 1        if (!configuration.getBoolean(DB_IDBROKER_PREFETCH, true))        {            quantity = new BigDecimal(1);        }        // Initialize quantity, if necessary.        else if (quantityStore.containsKey(tableName))        {            quantity = (BigDecimal) quantityStore.get(tableName);        }        else        {            Connection dbCon = null;            try            {                if (connection == null || configuration                    .getBoolean(DB_IDBROKER_USENEWCONNECTION, true))                {                    String databaseName = tableMap.getDatabaseMap().getName();                    // Get a connection to the db                    dbCon = Torque.getConnection(databaseName);                }                // Read the row from the ID_TABLE.                BigDecimal[] results = selectRow(dbCon, tableName);                // QUANTITY column.                quantity = results[1];                quantityStore.put(tableName, quantity);            }            catch (Exception e)            {                quantity = new BigDecimal(10);            }            finally            {                // Return the connection to the pool.                try                {                    dbCon.close();                }                catch (Exception e)                {                    log.error("Release of connection failed.", e);                }            }        }        return quantity;    }    /**     * Helper method to select a row in the ID_TABLE.     *     * @param con A Connection.     * @param tableName The properly escaped name of the table to     * identify the row.     * @return A BigDecimal[].     * @exception Exception a generic exception.     */    private BigDecimal[] selectRow(Connection con, String tableName)        throws Exception    {        StringBuffer stmt = new StringBuffer();        stmt.append("SELECT ")            .append(COL_NEXT_ID)            .append(", ")            .append(COL_QUANTITY)            .append(" FROM ")            .append(ID_TABLE)            .append(" WHERE ")            .append(COL_TABLE_NAME)            .append(" = '")            .append(tableName)            .append('\'');        Statement statement = null;        BigDecimal[] results = new BigDecimal[2];        try        {            statement = con.createStatement();            ResultSet rs = statement.executeQuery(stmt.toString());            if (rs.next())            {                // work around for MySQL which appears to support                // getBigDecimal in the source code, but the binary                // is throwing an NotImplemented exception.                results[0] = new BigDecimal(rs.getString(1)); // next_id                results[1] = new BigDecimal(rs.getString(2)); // quantity            }            else            {                throw new TorqueException("The table " + tableName                        + " does not have a proper entry in the " + ID_TABLE);            }        }        finally        {            if (statement != null)            {                statement.close();            }        }        return results;    }    /**     * Helper method to update a row in the ID_TABLE.     *     * @param con A Connection.     * @param tableName The properly escaped name of the table to identify the     * row.     * @param id An int with the value to set for the id.     * @exception Exception Database error.     */    private void updateNextId(Connection con, String tableName, String id)        throws Exception    {        StringBuffer stmt = new StringBuffer(id.length()                                             + tableName.length() + 50);        stmt.append("UPDATE " + ID_TABLE)            .append(" SET ")            .append(COL_NEXT_ID)            .append(" = ")            .append(id)            .append(" WHERE ")            .append(COL_TABLE_NAME)            .append(" = '")            .append(tableName)            .append('\'');        Statement statement = null;        if (log.isDebugEnabled())        {            log.debug("updateNextId: " + stmt.toString());        }        try        {            statement = con.createStatement();            statement.executeUpdate(stmt.toString());        }        finally        {            if (statement != null)            {                statement.close();            }        }    }    /**     * Helper method to update a row in the ID_TABLE.     *     * @param con A Connection.     * @param tableName The properly escaped name of the table to identify the     * row.     * @param quantity An int with the value of the quantity.     * @exception Exception Database error.     */    private void updateQuantity(Connection con, String tableName,                                BigDecimal quantity)        throws Exception    {        StringBuffer stmt = new StringBuffer(quantity.toString().length()                                             + tableName.length() + 50);        stmt.append("UPDATE ")            .append(ID_TABLE)            .append(" SET ")            .append(COL_QUANTITY)            .append(" = ")            .append(quantity)            .append(" WHERE ")            .append(COL_TABLE_NAME)            .append(" = '")            .append(tableName)            .append('\'');        Statement statement = null;        if (log.isDebugEnabled())        {            log.debug("updateQuantity: " + stmt.toString());        }        try        {            statement = con.createStatement();            statement.executeUpdate(stmt.toString());        }        finally        {            if (statement != null)            {                statement.close();            }        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -