From 1d18148c9765a8d3bd17addfb308708ba830e438 Mon Sep 17 00:00:00 2001 From: rinoux Date: Tue, 10 May 2022 14:16:16 +0800 Subject: [PATCH 1/2] =?UTF-8?q?REPORT-71021=20=E6=81=A2=E5=A4=8D=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E7=BA=BF=E7=A8=8B=E5=90=AF=E5=81=9C=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fine-druid/readme.MD | 4 +- .../alibaba/druid/pool/DruidDataSource.java | 287 ++++++++++++------ 2 files changed, 203 insertions(+), 88 deletions(-) diff --git a/fine-druid/readme.MD b/fine-druid/readme.MD index a45bb5efa..275182ba3 100644 --- a/fine-druid/readme.MD +++ b/fine-druid/readme.MD @@ -1,9 +1,10 @@ # Alibaba Druid + - FineReport更新时间 `2022-04-27` - Druid版本 1.2.9 - [github地址](https://github.com/alibaba/druid) -## 变动列表 +## 变动列表 > 由于需要适配数据源的一些特性和默认配置,对Druid有部分修改,后续更新都要保留下列修改 @@ -14,3 +15,4 @@ | 1.2.9 | 2022-05-05 | MysqlUtils.getLastPacketReceivedTimeMs根据类加载器区分连接实现等,不在使用全局变量 | | 1.2.9 | 2022-05-05 | com.fr.third.alibaba.druid.util.Utils.loadClass改为优先从线程类加载器加载类 | | 1.2.9 | 2022-05-05 | 恢复com.fr.third.alibaba.druid.pool.DruidDataSourceFactory对hibernate配置属性的支持 | +| 1.2.9 | 2022-05-10 | 恢复DruidDataSource中的创建线程启停机制 | diff --git a/fine-druid/src/main/java/com/fr/third/alibaba/druid/pool/DruidDataSource.java b/fine-druid/src/main/java/com/fr/third/alibaba/druid/pool/DruidDataSource.java index c79171458..b27276b28 100644 --- a/fine-druid/src/main/java/com/fr/third/alibaba/druid/pool/DruidDataSource.java +++ b/fine-druid/src/main/java/com/fr/third/alibaba/druid/pool/DruidDataSource.java @@ -134,6 +134,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private volatile Future createSchedulerFuture; private CreateConnectionThread createConnectionThread; + private PeriodDetectionThread periodDetectionThread; private DestroyConnectionThread destroyConnectionThread; private LogStatsThread logStatsThread; private int createTaskCount; @@ -141,7 +142,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private volatile long createTaskIdSeed = 1L; private long[] createTasks; - private final CountDownLatch initedLatch = new CountDownLatch(2); + private CountDownLatch initedLatch = new CountDownLatch(2); private volatile boolean enable = true; @@ -161,6 +162,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public static ThreadLocal waitNanosLocal = new ThreadLocal(); private boolean logDifferentThread = true; private volatile boolean keepAlive = false; + private SQLException initException = null; private boolean asyncInit = false; protected boolean killWhenSocketReadTimeout = false; protected boolean checkExecuteTime = false; @@ -178,11 +180,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat protected static final AtomicLongFieldUpdater createTaskIdSeedUpdater = AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, "createTaskIdSeed"); - public DruidDataSource(){ + public DruidDataSource() { this(false); } - public DruidDataSource(boolean fairLock){ + public DruidDataSource(boolean fairLock) { super(fairLock); configFromPropety(System.getProperties()); @@ -526,6 +528,45 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } + private synchronized void doSomethingBeforeCreationThreadBreak() { + String threadName = "Druid-ConnectionPool-Create-" + System.identityHashCode(this) + this.getUrl(); + createConnectionThread = new CreateConnectionThread(threadName); + createConnectionThread.setStarted(false); + String destroyName = "Druid-ConnectionPool-Destroy-" + System.identityHashCode(this) + this.getUrl(); + if (destroyConnectionThread != null) { + if (!destroyConnectionThread.isInterrupted()) { + destroyConnectionThread.interrupt(); + } + } + destroyConnectionThread = new DestroyConnectionThread(destroyName); + destroyConnectionThread.setStarted(false); + initedLatch = new CountDownLatch(2); + } + + private void checkThread() throws SQLException { + if (createConnectionThread == null) { + throw new IllegalStateException("createConnectionThread not start!"); + } + if (destroyConnectionThread == null) { + throw new IllegalStateException("destroyConnectionThread not start!"); + } + if (!createConnectionThread.isStarted() && !destroyConnectionThread.isStarted()) { + synchronized (this) {//线程安全问题,加个双检锁 + if (!createConnectionThread.isStarted() && !destroyConnectionThread.isStarted()) { + createConnectionThread.setStarted(true); + createConnectionThread.start(); + destroyConnectionThread.setStarted(true); + destroyConnectionThread.start(); + try { + initedLatch.await(); + } catch (InterruptedException e) { + throw new SQLException(e.getMessage(), e); + } + } + } + } + } + public boolean isKillWhenSocketReadTimeout() { return killWhenSocketReadTimeout; } @@ -798,6 +839,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } public void init() throws SQLException { + if (initException != null) { + LOG.error("{dataSource-" + this.getID() + "} init error", initException); + throw initException; + } + if (inited) { return; } @@ -944,6 +990,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat createAndLogThread(); createAndStartCreatorThread(); createAndStartDestroyThread(); + createAndStartDetectThread(); initedLatch.await(); init = true; @@ -968,16 +1015,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } catch (SQLException e) { LOG.error("{dataSource-" + this.getID() + "} init error", e); + initException = e; throw e; } catch (InterruptedException e) { throw new SQLException(e.getMessage(), e); - } catch (RuntimeException e){ - LOG.error("{dataSource-" + this.getID() + "} init error", e); - throw e; - } catch (Error e){ - LOG.error("{dataSource-" + this.getID() + "} init error", e); + } catch (Throwable e) { + initException = new SQLException(e.getMessage()); throw e; - } finally { inited = true; lock.unlock(); @@ -1075,7 +1119,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat period = 1000; } destroySchedulerFuture = destroyScheduler.scheduleAtFixedRate(destroyTask, period, period, - TimeUnit.MILLISECONDS); + TimeUnit.MILLISECONDS); initedLatch.countDown(); return; } @@ -1087,7 +1131,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat protected void createAndStartCreatorThread() { if (createScheduler == null) { - String threadName = "Druid-ConnectionPool-Create-" + System.identityHashCode(this); + String threadName = "Druid-ConnectionPool-Create-" + System.identityHashCode(this) + this.getUrl(); createConnectionThread = new CreateConnectionThread(threadName); createConnectionThread.start(); return; @@ -1096,9 +1140,18 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat initedLatch.countDown(); } + private void createAndStartDetectThread() { + if (createScheduler == null) { + String threadName = "Druid-ConnectionPool-Detection-" + System.identityHashCode(this) + this.getUrl(); + periodDetectionThread = new PeriodDetectionThread(threadName); + periodDetectionThread.start(); + } + } + + /** * load filters from SPI ServiceLoader - * + * * @see ServiceLoader */ private void initFromSPIServiceLoader() { @@ -1149,7 +1202,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat /** * 会去重复 - * + * * @param filter */ private void addFilter(Filter filter) { @@ -1181,21 +1234,21 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return; } - String errorMessage = ""; + String infoMessage = ""; - if (testOnBorrow) { - errorMessage += "testOnBorrow is true, "; + if (isTestOnBorrow()) { + infoMessage += "testOnBorrow is true, "; } - if (testOnReturn) { - errorMessage += "testOnReturn is true, "; + if (isTestOnReturn()) { + infoMessage += "testOnReturn is true, "; } - if (testWhileIdle) { - errorMessage += "testWhileIdle is true, "; + if (isTestWhileIdle()) { + infoMessage += "testWhileIdle is true, "; } - LOG.error(errorMessage + "validationQuery not set"); + LOG.info(infoMessage + "validationQuery not set"); } protected void resolveDriver() throws SQLException { @@ -1233,7 +1286,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (driver.getMajorVersion() < 10) { throw new SQLException("not support oracle driver " + driver.getMajorVersion() + "." - + driver.getMinorVersion()); + + driver.getMinorVersion()); } if (driver.getMajorVersion() == 10 && isUseOracleImplicitCache()) { @@ -1277,7 +1330,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (query instanceof SQLSelectQueryBlock) { if (((SQLSelectQueryBlock) query).getFrom() == null) { LOG.error("invalid oracle validationQuery. " + validationQuery + ", may should be : " + validationQuery - + " FROM DUAL"); + + " FROM DUAL"); } } } @@ -1306,7 +1359,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (query instanceof SQLSelectQueryBlock) { if (((SQLSelectQueryBlock) query).getFrom() == null) { LOG.error("invalid db2 validationQuery. " + validationQuery + ", may should be : " + validationQuery - + " FROM SYSDUMMY"); + + " FROM SYSDUMMY"); } } } @@ -1325,8 +1378,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat this.validConnectionChecker = new OracleValidConnectionChecker(); } else if (realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER) - || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4) - || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_JTDS)) { + || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4) + || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_JTDS)) { this.validConnectionChecker = new MSSQLValidConnectionChecker(); } else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER) @@ -1351,7 +1404,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } - for (Class driverClass = driver.getClass();;) { + for (Class driverClass = driver.getClass(); ; ) { String realDriverClassName = driverClass.getName(); if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) // || realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)) { @@ -1402,6 +1455,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException { init(); + checkThread(); if (filters.size() > 0) { FilterChainImpl filterChain = new FilterChainImpl(this); return filterChain.dataSource_connect(this, maxWaitMillis); @@ -1422,7 +1476,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException { int notFullTimeoutRetryCnt = 0; - for (;;) { + for (; ; ) { // handle notFullTimeoutRetry DruidPooledConnection poolableConnection; try { @@ -1456,10 +1510,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (testWhileIdle) { final DruidConnectionHolder holder = poolableConnection.holder; - long currentTimeMillis = System.currentTimeMillis(); - long lastActiveTimeMillis = holder.lastActiveTimeMillis; - long lastExecTimeMillis = holder.lastExecTimeMillis; - long lastKeepTimeMillis = holder.lastKeepTimeMillis; + long currentTimeMillis = System.currentTimeMillis(); + long lastActiveTimeMillis = holder.lastActiveTimeMillis; + long lastExecTimeMillis = holder.lastExecTimeMillis; + long lastKeepTimeMillis = holder.lastKeepTimeMillis; if (checkExecuteTime && lastExecTimeMillis != lastActiveTimeMillis) { @@ -1470,7 +1524,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat lastActiveTimeMillis = lastKeepTimeMillis; } - long idleMillis = currentTimeMillis - lastActiveTimeMillis; + long idleMillis = currentTimeMillis - lastActiveTimeMillis; long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis; @@ -1480,7 +1534,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (idleMillis >= timeBetweenEvictionRunsMillis || idleMillis < 0 // unexcepted branch - ) { + ) { boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn); if (!validate) { if (LOG.isDebugEnabled()) { @@ -1488,7 +1542,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } discardConnection(poolableConnection.holder); - continue; + continue; } } } @@ -1518,7 +1572,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat /** * 抛弃连接,不进行回收,而是抛弃 - * + * * @param realConnection * @deprecated */ @@ -1591,7 +1645,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat DruidConnectionHolder holder; - for (boolean createDirect = false;;) { + for (boolean createDirect = false; ; ) { if (createDirect) { createStartNanosUpdater.set(this, System.nanoTime()); if (creatingCountUpdater.compareAndSet(this, 0, 1)) { @@ -1740,10 +1794,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat StringBuilder buf = new StringBuilder(128); buf.append("wait millis ")// - .append(waitNanos / (1000 * 1000))// - .append(", active ").append(activeCount)// - .append(", maxActive ").append(maxActive)// - .append(", creating ").append(creatingCount)// + .append(waitNanos / (1000 * 1000))// + .append(", active ").append(activeCount)// + .append(", maxActive ").append(maxActive)// + .append(", creating ").append(creatingCount)// ; if (creatingCount > 0 && createStartNanos > 0) { long createElapseMillis = (System.nanoTime() - createStartNanos) / (1000 * 1000); @@ -1756,17 +1810,21 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat buf.append(", createErrorCount ").append(createErrorCount); } - List sqlList = this.getDataSourceStat().getRuningSqlList(); - for (int i = 0; i < sqlList.size(); ++i) { - if (i != 0) { - buf.append('\n'); - } else { - buf.append(", "); + JdbcDataSourceStat sourceStat = this.getDataSourceStat(); + if (sourceStat != null) { + List sqlList = sourceStat.getRuningSqlList(); + for (int i = 0; i < sqlList.size(); ++i) { + if (i != 0) { + buf.append('\n'); + } else { + buf.append(", "); + } + JdbcSqlStatValue sql = sqlList.get(i); + buf.append("runningSqlCount "); + buf.append(sql.getRunningCount()); + buf.append(" : "); + buf.append(sql.getSql()); } - JdbcSqlStatValue sql = sqlList.get(i); - buf.append("runningSqlCount ").append(sql.getRunningCount()); - buf.append(" : "); - buf.append(sql.getSql()); } String errorMessage = buf.toString(); @@ -1858,13 +1916,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat lock.unlock(); } - if(onFatalError && holder != null && holder.getDataSource() != null) { + if (onFatalError && holder != null && holder.getDataSource() != null) { ReentrantLock dataSourceLock = holder.getDataSource().lock; dataSourceLock.lock(); try { emptySignal(); - } - finally { + } finally { dataSourceLock.unlock(); } } @@ -1901,8 +1958,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } if (logDifferentThread // - && (!isAsyncCloseConnectionEnable()) // - && pooledConnection.ownerThread != Thread.currentThread()// + && (!isAsyncCloseConnectionEnable()) // + && pooledConnection.ownerThread != Thread.currentThread()// ) { LOG.warn("get/close not same thread"); } @@ -2097,6 +2154,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat destroyConnectionThread.interrupt(); } + if (periodDetectionThread != null) { + periodDetectionThread.interrupt(); + } + if (createSchedulerFuture != null) { createSchedulerFuture.cancel(true); } @@ -2154,7 +2215,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat @Override public Object run() { ObjectName objectName = DruidDataSourceStatManager.addDataSource(DruidDataSource.this, - DruidDataSource.this.name); + DruidDataSource.this.name); DruidDataSource.this.setObjectName(objectName); DruidDataSource.this.mbeanRegistered = true; @@ -2248,7 +2309,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat private DruidConnectionHolder pollLast(long nanos) throws InterruptedException, SQLException { long estimate = nanos; - for (;;) { + for (; ; ) { if (poolingCount == 0) { emptySignal(); // send signal to CreateThread create connection @@ -2269,8 +2330,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { long startEstimate = estimate; estimate = notEmpty.awaitNanos(estimate); // signal by - // recycle or - // creator + // recycle or + // creator notEmptyWaitCount++; notEmptyWaitNanos += (startEstimate - estimate); @@ -2494,7 +2555,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat value.setCommitCount(commitCountUpdater.getAndSet(this, 0)); value.setRollbackCount(rollbackCountUpdater.getAndSet(this, 0)); - value.setPstmtCacheHitCount(cachedPreparedStatementHitCountUpdater.getAndSet(this,0)); + value.setPstmtCacheHitCount(cachedPreparedStatementHitCountUpdater.getAndSet(this, 0)); value.setPstmtCacheMissCount(cachedPreparedStatementMissCountUpdater.getAndSet(this, 0)); value.setStartTransactionCount(startTransactionCountUpdater.getAndSet(this, 0)); @@ -2572,7 +2633,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat clearCreateTask(createTaskId); if (poolingCount + createTaskCount < notEmptyWaitThreadCount // - && activeCount + poolingCount + createTaskCount < maxActive) { + && activeCount + poolingCount + createTaskCount < maxActive) { emptySignal(); } } @@ -2584,7 +2645,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public class CreateConnectionTask implements Runnable { - private int errorCount = 0; + private int errorCount = 0; private boolean initTask = false; private final long taskId; @@ -2603,7 +2664,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } private void runInternal() { - for (;;) { + for (; ; ) { // addLast lock.lock(); @@ -2769,8 +2830,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } public class CreateConnectionThread extends Thread { + private volatile boolean started = true; - public CreateConnectionThread(String name){ + public CreateConnectionThread(String name) { super(name); this.setDaemon(true); } @@ -2780,7 +2842,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat long lastDiscardCount = 0; int errorCount = 0; - for (;;) { + for (; ; ) { // addLast try { lock.lockInterruptibly(); @@ -2829,6 +2891,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if ((!closing) && (!closed)) { LOG.error("create connection Thread Interrupted, url: " + jdbcUrl, e); } + DruidDataSource.this.doSomethingBeforeCreationThreadBreak(); break; } finally { lock.unlock(); @@ -2838,9 +2901,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { connection = createPhysicalConnection(); - } catch (SQLException e) { - LOG.error("create connection SQLException, url: " + jdbcUrl + ", errorCode " + e.getErrorCode() - + ", state " + e.getSQLState(), e); + } catch (SQLException | RuntimeException e) { + if (e instanceof SQLException) { + LOG.error("create connection error, url: " + jdbcUrl + ", errorCode " + ((SQLException) e).getErrorCode() + + ", state " + ((SQLException) e).getSQLState(), e); + } else { + LOG.error("create connection error", e); + } errorCount++; if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) { @@ -2861,17 +2928,16 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { Thread.sleep(timeBetweenConnectErrorMillis); - } catch (InterruptedException interruptEx) { - break; + } catch (InterruptedException ignore) { + } + DruidDataSource.this.doSomethingBeforeCreationThreadBreak(); + break; } - } catch (RuntimeException e) { - LOG.error("create connection RuntimeException", e); - setFailContinuous(true); - continue; } catch (Error e) { LOG.error("create connection Error", e); setFailContinuous(true); + DruidDataSource.this.doSomethingBeforeCreationThreadBreak(); break; } @@ -2892,11 +2958,49 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } } + + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + } + + //周期性检查生产线程状态,因为在终止生产线程的时候,为了不让生产线程疯狂重试数据库,只是生成了一个生产线程,但是并没有start,需要一个守护线程 + //周期性检查线程状态,帮助其启动。 + private class PeriodDetectionThread extends Thread { + public PeriodDetectionThread(String name) { + super(name); + this.setDaemon(true); + } + + public void run() { + while (true) { + synchronized (DruidDataSource.this) { + //生产线程发生了切换,并且有线程在等待连接,需要主动唤醒生产线程,否则由getConnection方法来唤醒生产线程 + if (!createConnectionThread.started && !destroyConnectionThread.started && notEmptyWaitThreadCount > 0) { + createConnectionThread.setStarted(true); + createConnectionThread.start(); + destroyConnectionThread.setStarted(true); + destroyConnectionThread.start(); + } + } + try { + Thread.sleep(30000); + } catch (InterruptedException ignore) { + break; + } + } + } } public class DestroyConnectionThread extends Thread { - public DestroyConnectionThread(String name){ + private volatile boolean started = true; + + public DestroyConnectionThread(String name) { super(name); this.setDaemon(true); } @@ -2904,7 +3008,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public void run() { initedLatch.countDown(); - for (;;) { + for (; ; ) { // 从前面开始删除 try { if (closed || closing) { @@ -2928,6 +3032,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } } + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } } public class DestroyTask implements Runnable { @@ -2948,14 +3059,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public class LogStatsThread extends Thread { - public LogStatsThread(String name){ + public LogStatsThread(String name) { super(name); this.setDaemon(true); } public void run() { try { - for (;;) { + for (; ; ) { try { logStats(); } catch (Exception e) { @@ -2981,7 +3092,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { Iterator iter = activeConnections.keySet().iterator(); - for (; iter.hasNext();) { + for (; iter.hasNext(); ) { DruidPooledConnection pooledConnection = iter.next(); if (pooledConnection.isRunning()) { @@ -3033,7 +3144,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } buf.append("ownerThread current state is " + pooledConnection.getOwnerThread().getState() - + ", current stackTrace\n"); + + ", current stackTrace\n"); trace = pooledConnection.getOwnerThread().getStackTrace(); for (int i = 0; i < trace.length; i++) { buf.append("\tat "); @@ -3049,7 +3160,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return removeCount; } - /** Instance key */ + /** + * Instance key + */ protected String instanceKey = null; public Reference getReference() throws NamingException { @@ -3119,7 +3232,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat int keepAliveCount = 0; int fatalErrorIncrement = fatalErrorCount - fatalErrorCountLastShrink; fatalErrorCountLastShrink = fatalErrorCount; - + try { if (!inited) { return; @@ -3130,7 +3243,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat for (int i = 0; i < poolingCount; ++i) { DruidConnectionHolder connection = connections[i]; - if ((onFatalError || fatalErrorIncrement > 0) && (lastFatalErrorTimeMillis > connection.connectTimeMillis)) { + if ((onFatalError || fatalErrorIncrement > 0) && (lastFatalErrorTimeMillis > connection.connectTimeMillis)) { keepAliveConnections[keepAliveCount++] = connection; continue; } @@ -3754,7 +3867,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } if (this.statLogger != null - && (this.statLogger.getClass() == iface || DruidDataSourceStatLogger.class == iface)) { + && (this.statLogger.getClass() == iface || DruidDataSourceStatLogger.class == iface)) { return true; } @@ -3770,7 +3883,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } if (this.statLogger != null - && (this.statLogger.getClass() == iface || DruidDataSourceStatLogger.class == iface)) { + && (this.statLogger.getClass() == iface || DruidDataSourceStatLogger.class == iface)) { return (T) statLogger; } @@ -3814,7 +3927,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } int fillCount = 0; - for (;;) { + for (; ; ) { try { lock.lockInterruptibly(); } catch (InterruptedException e) { From ea271102a02c3ecb3be8b9a8d4145cb2fa71b64d Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 10 May 2022 17:02:09 +0800 Subject: [PATCH 2/2] =?UTF-8?q?REPORT-71241=20=E5=A4=A7=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=9B=86=E5=AF=BC=E5=87=BA=E5=8F=98=E6=85=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/poi/hssf/usermodel/HSSFCell.java | 28 ++++---- .../v2/org/apache/poi/ss/usermodel/Cell.java | 8 +-- .../apache/poi/xssf/streaming/SXSSFCell.java | 5 ++ .../poi/xssf/streaming/SheetDataWriter.java | 6 +- .../apache/poi/xssf/usermodel/XSSFCell.java | 68 ++++++++++--------- 5 files changed, 63 insertions(+), 52 deletions(-) diff --git a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/hssf/usermodel/HSSFCell.java b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/hssf/usermodel/HSSFCell.java index 8d4cd8d74..e9b9db1df 100644 --- a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -221,8 +221,8 @@ public class HSSFCell extends CellBase { BoolErrRecord boolErrRecord = ( BoolErrRecord ) record; return boolErrRecord.isBoolean() - ? CellType.BOOLEAN - : CellType.ERROR; + ? CellType.BOOLEAN + : CellType.ERROR; } throw new RuntimeException("Bad cell value rec (" + cval.getClass().getName() + ")"); } @@ -412,7 +412,7 @@ public class HSSFCell extends CellBase { throw new IllegalStateException("Invalid cell type: " + cellType); } if (cellType != _cellType && - _cellType != CellType._NONE ) // Special Value to indicate an uninitialized Cell + _cellType != CellType._NONE ) // Special Value to indicate an uninitialized Cell { _sheet.getSheet().replaceValueRecord(_record); } @@ -643,7 +643,7 @@ public class HSSFCell extends CellBase { private static RuntimeException typeMismatch(CellType expectedTypeCode, CellType actualTypeCode, boolean isFormulaCell) { String msg = "Cannot get a " + expectedTypeCode + " value from a " + actualTypeCode - + " " + (isFormulaCell ? "formula " : "") + "cell"; + + " " + (isFormulaCell ? "formula " : "") + "cell"; return new IllegalStateException(msg); } private static void checkFormulaCachedValueType(CellType expectedTypeCode, FormulaRecord fr) { @@ -723,8 +723,8 @@ public class HSSFCell extends CellBase { */ public String getStringCellValue() { - HSSFRichTextString str = getRichStringCellValue(); - return str.getString(); + HSSFRichTextString str = getRichStringCellValue(); + return str.getString(); } /** @@ -863,7 +863,7 @@ public class HSSFCell extends CellBase { case NUMERIC: return NumberToTextConverter.toText(((NumberRecord)_record).getValue()); case ERROR: - return FormulaError.forInt(((BoolErrRecord)_record).getErrorValue()).getString(); + return FormulaError.forInt(((BoolErrRecord)_record).getErrorValue()).getString(); case FORMULA: // should really evaluate, but HSSFCell can't call HSSFFormulaEvaluator // just use cached formula result instead @@ -970,9 +970,9 @@ public class HSSFCell extends CellBase { */ public HSSFCellStyle getCellStyle() { - short styleIndex=_record.getXFIndex(); - ExtendedFormatRecord xf = _book.getWorkbook().getExFormatAt(styleIndex); - return new HSSFCellStyle(styleIndex, xf, _book); + short styleIndex=_record.getXFIndex(); + ExtendedFormatRecord xf = _book.getWorkbook().getExFormatAt(styleIndex); + return new HSSFCellStyle(styleIndex, xf, _book); } /** @@ -1038,7 +1038,7 @@ public class HSSFCell extends CellBase { sdf.setTimeZone(LocaleUtil.getUserTimeZone()); return sdf.format(getDateCellValue()); } - return String.valueOf(getNumericCellValue()); + return String.valueOf(getNumericCellValue()); case STRING: return getStringCellValue(); default: @@ -1069,7 +1069,7 @@ public class HSSFCell extends CellBase { * * @return comment associated with this cell */ - public HSSFComment getCellComment(){ + public HSSFComment getCellComment(){ if (_comment == null) { _comment = _sheet.findCellComment(_record.getRow(), _record.getColumn()); } @@ -1258,5 +1258,9 @@ public class HSSFCell extends CellBase { return styleIndex; } + + public boolean isRichText() { + return false; + } } diff --git a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/ss/usermodel/Cell.java b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/ss/usermodel/Cell.java index d1c53a98e..292a42cfc 100644 --- a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/ss/usermodel/Cell.java +++ b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/ss/usermodel/Cell.java @@ -71,7 +71,7 @@ public interface Cell { * * @return the Row that owns this cell */ - Row getRow(); + Row getRow(); /** * Set the cells type (blank, numeric, boolean, error or string). @@ -253,7 +253,7 @@ public interface Cell { */ void setCellValue(String value); - + boolean isRichText(); /** * Sets formula for this cell. *

If {@code formula} is not null, sets or updates the formula. If {@code formula} is null, removes the formula. @@ -355,7 +355,7 @@ public interface Cell { * precalculated value, for booleans we'll set its value. For other types we * will change the cell to a boolean cell and set its value. */ - void setCellValue(boolean value); + void setCellValue(boolean value); /** * Set a error value for the cell @@ -419,7 +419,7 @@ public interface Cell { */ void setAsActiveCell(); - /** + /** * Gets the address of this cell * * @return A1 style address of this cell diff --git a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/streaming/SXSSFCell.java b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/streaming/SXSSFCell.java index fea14f491..a9cf01e99 100644 --- a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/streaming/SXSSFCell.java +++ b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/streaming/SXSSFCell.java @@ -741,6 +741,11 @@ public class SXSSFCell extends CellBase { } } + public boolean isRichText() { + CellType cellType = this.getCellType(); + return cellType == CellType.STRING ? ((SXSSFCell.StringValue)this._value).isRichText() : false; + } + @Override public void setCellValue(BigInteger value) { ensureTypeOrFormulaType(CellType.NUMERIC_BIG_INTEGER); diff --git a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/streaming/SheetDataWriter.java b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/streaming/SheetDataWriter.java index 145b79e5f..8c9bc9242 100644 --- a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/streaming/SheetDataWriter.java +++ b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/streaming/SheetDataWriter.java @@ -36,7 +36,6 @@ import com.fr.third.v2.org.apache.poi.ss.usermodel.Cell; import com.fr.third.v2.org.apache.poi.ss.usermodel.CellStyle; import com.fr.third.v2.org.apache.poi.ss.usermodel.CellType; import com.fr.third.v2.org.apache.poi.ss.usermodel.FormulaError; -import com.fr.third.v2.org.apache.poi.ss.usermodel.RichTextString; import com.fr.third.v2.org.apache.poi.ss.util.CellReference; import com.fr.third.v2.org.apache.poi.util.POILogFactory; import com.fr.third.v2.org.apache.poi.util.POILogger; @@ -315,9 +314,8 @@ public class SheetDataWriter implements Closeable { break; } case STRING: { - if (_sharedStringSource != null) { - //XSSFRichTextString rt = new XSSFRichTextString(cell.getStringCellValue()); - RichTextString rt = cell.getRichStringCellValue(); + if (_sharedStringSource != null&& cell.isRichText()) { + XSSFRichTextString rt = new XSSFRichTextString(cell.getStringCellValue()); int sRef = _sharedStringSource.addSharedStringItem(rt); writeAttribute("t", STCellType.S.toString()); diff --git a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/usermodel/XSSFCell.java b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/usermodel/XSSFCell.java index 73f4b0815..0449df6d7 100644 --- a/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/fine-poi/src/main/java/com/fr/third/v2/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -138,9 +138,9 @@ public final class XSSFCell extends CellBase { /** * Copy cell value, formula and style, from srcCell per cell copy policy * If srcCell is null, clears the cell value and cell style per cell copy policy - * + * * This does not shift references in formulas. Use {@link com.fr.third.v2.org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter} to shift references in formulas. - * + * * @param srcCell The cell to take value, formula and style from * @param policy The policy for copying the information, see {@link CellCopyPolicy} * @throws IllegalArgumentException if copy cell style and srcCell is from a different workbook @@ -190,12 +190,12 @@ public final class XSSFCell extends CellBase { setBlank(); } } - + // Copy CellStyle if (policy.isCopyCellStyle()) { setCellStyle(srcCell == null ? null : srcCell.getCellStyle()); } - + final Hyperlink srcHyperlink = (srcCell == null) ? null : srcCell.getHyperlink(); if (policy.isMergeHyperlink()) { @@ -301,17 +301,17 @@ public final class XSSFCell extends CellBase { return 0.0; case NUMERIC: if(_cell.isSetV()) { - String v = _cell.getV(); - if (v.isEmpty()) { - return 0.0; - } - try { - return Double.parseDouble(v); - } catch(NumberFormatException e) { - throw typeMismatch(CellType.NUMERIC, CellType.STRING, false); - } + String v = _cell.getV(); + if (v.isEmpty()) { + return 0.0; + } + try { + return Double.parseDouble(v); + } catch(NumberFormatException e) { + throw typeMismatch(CellType.NUMERIC, CellType.STRING, false); + } } else { - return 0.0; + return 0.0; } case FORMULA: throw new AssertionError(); @@ -441,7 +441,7 @@ public final class XSSFCell extends CellBase { // existing behavior - create a new XSSFEvaluationWorkbook for every call return getCellFormula(null); } - + /** * package/hierarchy use only - reuse an existing evaluation workbook if available for caching * @@ -627,7 +627,7 @@ public final class XSSFCell extends CellBase { * *

To change the style of a cell without affecting other cells that use the same style, * use {@link com.fr.third.v2.org.apache.poi.ss.util.CellUtil#setCellStyleProperties(Cell, java.util.Map)}

- * + * * @param style reference contained in the workbook. * If the value is null then the style information is removed causing the cell to used the default workbook style. * @throws IllegalArgumentException if style belongs to a different styles source (most likely because style is from a different Workbook) @@ -646,7 +646,7 @@ public final class XSSFCell extends CellBase { _cell.setS(idx); } } - + /** * POI currently supports these formula types: *
    @@ -663,7 +663,7 @@ public final class XSSFCell extends CellBase { } return false; } - + /** * Return the cell type. Tables in an array formula return * {@link CellType#FORMULA} for all cells, even though the formula is only defined @@ -697,7 +697,7 @@ public final class XSSFCell extends CellBase { return getBaseCellType(false); } - + /** * Only valid for formula cells * @return one of ({@link CellType#NUMERIC}, {@link CellType#STRING}, @@ -736,7 +736,7 @@ public final class XSSFCell extends CellBase { case STCellType.INT_S: // String is in shared strings case STCellType.INT_INLINE_STR: // String is inline in cell case STCellType.INT_STR: - return CellType.STRING; + return CellType.STRING; default: throw new IllegalStateException("Illegal cell type: " + this._cell.getT()); } @@ -915,7 +915,7 @@ public final class XSSFCell extends CellBase { protected void setCellTypeImpl(CellType cellType) { setCellType(cellType, null); } - + /** * Needed by bug #62834, which points out getCellFormula() expects an evaluation context or creates a new one, * so if there is one in use, it needs to be carried on through. @@ -1076,7 +1076,7 @@ public final class XSSFCell extends CellBase { /** * Removes the comment for this cell, if there is one. - */ + */ @Override public void removeCellComment() { XSSFComment comment = getCellComment(); @@ -1138,10 +1138,10 @@ public final class XSSFCell extends CellBase { public CTCell getCTCell(){ return _cell; } - + /** * Set a new internal xml bean. This is only for internal use, do not call this from outside! - * + * * This is necessary in some rare cases to work around XMLBeans specialties. */ @Internal @@ -1179,7 +1179,7 @@ public final class XSSFCell extends CellBase { // fall-through case BLANK: return false; - + default: throw new RuntimeException("Unexpected cell type (" + cellType + ")"); } @@ -1218,19 +1218,19 @@ public final class XSSFCell extends CellBase { return FALSE; } throw new IllegalStateException("Unexpected boolean cached formula value '" - + textValue + "'."); - + + textValue + "'."); + case STRING: // fall-through case NUMERIC: // fall-through case ERROR: return textValue; - + default: throw new IllegalStateException("Unexpected formula result type (" + cellType + ")"); } - + } @Override @@ -1257,14 +1257,18 @@ public final class XSSFCell extends CellBase { CalculationChain calcChain = getSheet().getWorkbook().getCalculationChain(); int sheetId = Math.toIntExact(getSheet().sheet.getSheetId()); - + //remove the reference in the calculation chain if(calcChain != null) calcChain.removeItem(sheetId, getReference()); - + CTCell ctCell = getCTCell(); String r = new CellReference(getRowIndex(), getColumnIndex()).formatAsString(); ctCell.setR(r); } - + + public boolean isRichText() { + return false; + } + }