📄 idbroker.java
字号:
.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 + -