PageRenderTime 25ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/derby-10.9.1.0/db-derby-10.9.1.0-src/java/testing/org/apache/derbyTesting/functionTests/tests/store/AutomaticIndexStatisticsMultiTest.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 349 lines | 269 code | 38 blank | 42 comment | 27 complexity | 02ba3991d1f02187b52b88f2f929a64c MD5 | raw file
  1. /*
  2. Derby - Class org.apache.derbyTesting.functionTests.tests.store.AutomaticIndexStatisticsMultiTest
  3. Licensed to the Apache Software Foundation (ASF) under one or more
  4. contributor license agreements. See the NOTICE file distributed with
  5. this work for additional information regarding copyright ownership.
  6. The ASF licenses this file to you under the Apache License, Version 2.0
  7. (the "License"); you may not use this file except in compliance with
  8. the License. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing, software
  11. distributed under the License is distributed on an "AS IS" BASIS,
  12. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. See the License for the specific language governing permissions and
  14. limitations under the License.
  15. */
  16. package org.apache.derbyTesting.functionTests.tests.store;
  17. import java.io.PrintWriter;
  18. import java.io.StringWriter;
  19. import java.sql.Connection;
  20. import java.sql.PreparedStatement;
  21. import java.sql.ResultSet;
  22. import java.sql.SQLException;
  23. import java.sql.Statement;
  24. import java.util.ArrayList;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Random;
  28. import junit.framework.Test;
  29. import junit.framework.TestSuite;
  30. import org.apache.derbyTesting.junit.BaseJDBCTestCase;
  31. import org.apache.derbyTesting.junit.IndexStatsUtil;
  32. import org.apache.derbyTesting.junit.IndexStatsUtil.IdxStats;
  33. /**
  34. * Tests that the update triggering code can handle a high amount of requests,
  35. * both when the data dictionary is operating in cached mode and in DDL mode.
  36. */
  37. public class AutomaticIndexStatisticsMultiTest
  38. extends BaseJDBCTestCase {
  39. private static final String TAB = "MTSEL";
  40. private static final int _100K = 100000;
  41. public AutomaticIndexStatisticsMultiTest(String name) {
  42. super(name);
  43. }
  44. public void testMTSelect()
  45. throws Exception {
  46. prepareTable(true);
  47. // Create threads compiling a select query for the table
  48. int threadCount = 5;
  49. long runTime = 10000;
  50. MTCompileThread[] compileThreads = new MTCompileThread[threadCount];
  51. for (int i=0; i < threadCount; i++) {
  52. compileThreads[i] =
  53. new MTCompileThread(openDefaultConnection(), runTime);
  54. }
  55. // Start the threads and let them run for a while.
  56. Thread[] threads = new Thread[threadCount];
  57. for (int i=0; i < threadCount; i++) {
  58. threads[i] = new Thread(compileThreads[i]);
  59. threads[i].start();
  60. }
  61. // Wait for the threads to finish.
  62. for (int i=0; i < threadCount; i++) {
  63. threads[i].join(600*1000); // Time out after 600 seconds.
  64. }
  65. int total = 0;
  66. int totalError = 0;
  67. List errors = new ArrayList();
  68. for (int i=0; i < threadCount; i++) {
  69. MTCompileThread ct = compileThreads[i];
  70. int count = ct.getCount();
  71. int errorCount = ct.getErrorCount();
  72. total += count;
  73. totalError += errorCount;
  74. errors.addAll(ct.getErrors());
  75. }
  76. println("TOTAL = " + total + " (of which " + totalError + " errors)");
  77. if (totalError > 0) {
  78. // Build an informative failure string.
  79. StringWriter msg = new StringWriter();
  80. PrintWriter out = new PrintWriter(msg);
  81. out.println(totalError + " select/compile errors reported:");
  82. for (Iterator ei = errors.iterator(); ei.hasNext(); ) {
  83. out.println("------");
  84. SQLException sqle = (SQLException)ei.next();
  85. sqle.printStackTrace(out);
  86. }
  87. out.close();
  88. fail(msg.toString());
  89. }
  90. verifyStatistics();
  91. // Shutdown database to log daemon stats (if logging is enabled).
  92. getTestConfiguration().shutdownDatabase();
  93. }
  94. public void testMTSelectWithDDL()
  95. throws Exception {
  96. prepareTable(true);
  97. // Create threads compiling a select query for the table
  98. int threadCount = 5;
  99. long runTime = 10000;
  100. MTCompileThread[] compileThreads = new MTCompileThread[threadCount];
  101. for (int i=0; i < threadCount; i++) {
  102. compileThreads[i] =
  103. new MTCompileThread(openDefaultConnection(), runTime);
  104. }
  105. // Start the drop/create thread.
  106. MTCreateDropThread createThread = new MTCreateDropThread(
  107. openDefaultConnection(), runTime);
  108. Thread[] threads = new Thread[threadCount +1];
  109. threads[0] = new Thread(createThread);
  110. threads[0].start();
  111. // Start the threads and let them run for a while.
  112. for (int i=0; i < threadCount; i++) {
  113. threads[i+1] = new Thread(compileThreads[i]);
  114. threads[i+1].start();
  115. }
  116. // Wait for the threads to finish.
  117. for (int i=0; i < threadCount; i++) {
  118. threads[i].join(600*1000); // Time out after 600 seconds.
  119. }
  120. int total = 0;
  121. int totalError = 0;
  122. List errors = new ArrayList();
  123. for (int i=0; i < threadCount; i++) {
  124. MTCompileThread ct = compileThreads[i];
  125. int count = ct.getCount();
  126. int errorCount = ct.getErrorCount();
  127. total += count;
  128. totalError += errorCount;
  129. errors.addAll(ct.getErrors());
  130. }
  131. println("TOTAL = " + total + " (of which " + totalError +
  132. " errors) CREATES = " + createThread.getCreates());
  133. if (totalError > 0 || createThread.failed()) {
  134. // Build an informative failure string.
  135. StringWriter msg = new StringWriter();
  136. PrintWriter out = new PrintWriter(msg);
  137. out.println("create/drop thread " +
  138. (createThread.failed() ? "died" : "survived") + ", " +
  139. totalError + " select/compile errors reported:");
  140. if (createThread.failed()) {
  141. out.println("create/drop thread error: ");
  142. createThread.getError().printStackTrace(out);
  143. }
  144. out.println("select/compile errors:");
  145. for (Iterator ei = errors.iterator(); ei.hasNext(); ) {
  146. out.println("------");
  147. SQLException sqle = (SQLException)ei.next();
  148. sqle.printStackTrace(out);
  149. }
  150. out.close();
  151. fail(msg.toString());
  152. }
  153. verifyStatistics();
  154. // Shutdown database to log daemon stats (if logging is enabled).
  155. getTestConfiguration().shutdownDatabase();
  156. }
  157. private void verifyStatistics()
  158. throws SQLException {
  159. // DERBY-5097: On machines with a single core/CPU the load generated
  160. // by the test threads may cause the index statistics daemon worker
  161. // thread to be "starved". Add a timeout to give it a chance to do
  162. // what it has been told to do.
  163. IndexStatsUtil stats = new IndexStatsUtil(getConnection(), 5000);
  164. IdxStats[] myStats = stats.getStatsTable(TAB, 2);
  165. for (int i=0; i < myStats.length; i++) {
  166. IdxStats s = myStats[i];
  167. assertEquals(_100K, s.rows);
  168. switch (s.lcols) {
  169. case 1:
  170. assertEquals(10, s.card);
  171. break;
  172. case 2:
  173. assertEquals(_100K, s.card);
  174. break;
  175. default:
  176. fail("unexpected number of leading columns: " + s.lcols);
  177. }
  178. }
  179. }
  180. private void prepareTable(boolean dropIfExists)
  181. throws SQLException {
  182. Statement stmt = createStatement();
  183. ResultSet rs = getConnection().getMetaData().getTables(
  184. null, null, TAB, null);
  185. if (rs.next()) {
  186. assertFalse(rs.next());
  187. rs.close();
  188. if (dropIfExists) {
  189. println("table " + TAB + " already exists, dropping");
  190. stmt.executeUpdate("drop table " + TAB);
  191. } else {
  192. println("table " + TAB + " already exists, reusing");
  193. return;
  194. }
  195. } else {
  196. rs.close();
  197. }
  198. stmt.executeUpdate("create table " + TAB + " (val1 int, val2 int)");
  199. stmt.executeUpdate("create index " +
  200. "mtsel_idx on " + TAB + " (val1, val2)");
  201. setAutoCommit(false);
  202. PreparedStatement ps = prepareStatement(
  203. "insert into " + TAB + " values (?,?)");
  204. // Insert blocks of 10000 rows.
  205. int blockCount = 10;
  206. int blockSize = 10000;
  207. for (int i=0; i < blockCount; i++) {
  208. ps.setInt(1, i);
  209. for (int j=0; j < blockSize; j++) {
  210. ps.setInt(2, j);
  211. ps.addBatch();
  212. }
  213. ps.executeBatch();
  214. commit();
  215. println("inserted block " + (i+1) + "/" + blockCount);
  216. }
  217. setAutoCommit(true);
  218. }
  219. public static Test suite() {
  220. return new TestSuite(AutomaticIndexStatisticsMultiTest.class);
  221. }
  222. private static class MTCompileThread
  223. implements Runnable {
  224. private final Random rand = new Random();
  225. private final Connection con;
  226. private final long runTime;
  227. private final ArrayList errors = new ArrayList();
  228. private volatile int count;
  229. public MTCompileThread(Connection con, long runTime)
  230. throws SQLException {
  231. this.con = con;
  232. this.runTime = runTime;
  233. }
  234. public void run() {
  235. final long started = System.currentTimeMillis();
  236. int counter = 0;
  237. while (System.currentTimeMillis() - started < runTime) {
  238. try {
  239. con.prepareStatement("select * from mtsel where " +
  240. (++counter) + " = " + counter + " AND val2 = " +
  241. (1 + rand.nextInt(10)));
  242. } catch (SQLException sqle) {
  243. synchronized (this) {
  244. errors.add(sqle);
  245. }
  246. }
  247. count++;
  248. }
  249. }
  250. public int getCount() {
  251. return count;
  252. }
  253. public synchronized int getErrorCount() {
  254. return errors.size();
  255. }
  256. public synchronized List getErrors() {
  257. return (List)errors.clone();
  258. }
  259. }
  260. private static class MTCreateDropThread
  261. implements Runnable {
  262. private final Connection con;
  263. private final long runTime;
  264. private volatile long creates;
  265. private volatile SQLException error;
  266. public MTCreateDropThread(Connection con, long runTime)
  267. throws SQLException {
  268. this.con = con;
  269. this.runTime = runTime;
  270. }
  271. public void run() {
  272. final long started = System.currentTimeMillis();
  273. try {
  274. ResultSet rs = con.getMetaData().getTables(
  275. null, null, "TMPTABLE", null);
  276. boolean lastWasCreate = rs.next();
  277. rs.close();
  278. Statement stmt = con.createStatement();
  279. while (System.currentTimeMillis() - started < runTime) {
  280. if (lastWasCreate) {
  281. // Drop the table
  282. stmt.executeUpdate("drop table TMPTABLE");
  283. } else {
  284. // Create the table
  285. stmt.executeUpdate("create table TMPTABLE("
  286. + "i int primary key, v varchar(30), b blob)");
  287. creates++;
  288. }
  289. lastWasCreate = !lastWasCreate;
  290. }
  291. } catch (SQLException sqle) {
  292. error = sqle;
  293. println("create/drop thread failed: " + sqle.getMessage());
  294. }
  295. }
  296. public long getCreates() {
  297. return creates;
  298. }
  299. public boolean failed() {
  300. return error != null;
  301. }
  302. public SQLException getError() {
  303. return error;
  304. }
  305. }
  306. }