MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MultithreadedTest.java
1 /*
2  Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 package testsuite.clusterj;
19 
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Comparator;
23 import java.util.List;
24 import java.util.Random;
25 import java.util.Set;
26 import java.util.TreeSet;
27 
28 import com.mysql.clusterj.Query;
29 import com.mysql.clusterj.Session;
30 import com.mysql.clusterj.query.QueryDomainType;
31 
32 import testsuite.clusterj.model.Customer;
33 import testsuite.clusterj.model.Order;
34 import testsuite.clusterj.model.OrderLine;
35 
37 
38  @Override
39  protected boolean getDebug() {
40  return false;
41  }
42 
43  private int numberOfThreads = 50;
44  private int numberOfNewCustomersPerThread = 5;
45  private int numberOfNewOrdersPerNewCustomer = 5;
46  private int numberOfUpdatesPerThread = 2;
47 
48  private int maximumOrderLinesPerOrder = 5;
49  private int maximumQuantityPerOrderLine = 100;
50  private int maximumUnitPrice = 100;
51 
52 
53  private int numberOfInitialCustomers = 10;
54  private int nextCustomerId = numberOfInitialCustomers;
55  private int nextOrderId = 0;
56  private int nextOrderLineId = 0;
57 
58  private int numberOfUpdatedOrderLines = 0;
59  private int numberOfDeletedOrders = 0;
60  private int numberOfDeletedOrderLines = 0;
61 
62  private ThreadGroup threadGroup;
63 
65  List<Customer> customers = new ArrayList<Customer>();
66 
68  List<Order> orders = new ArrayList<Order>();
69 
71  Set<OrderLine> orderlines = new TreeSet<OrderLine>(
72  new Comparator<OrderLine>() {
73  public int compare(OrderLine o1, OrderLine o2) {
74  return o1.getId() - o2.getId();
75  }
76  }
77  );
78 
79  @Override
80  public void localSetUp() {
81  createSessionFactory();
82  session = sessionFactory.getSession();
83  // first delete all customers, orders, and order lines
84  tx = session.currentTransaction();
85  tx.begin();
86  session.deletePersistentAll(Customer.class);
87  session.deletePersistentAll(Order.class);
88  session.deletePersistentAll(OrderLine.class);
89  tx.commit();
90  // start out with some customers
91  createCustomerInstances(nextCustomerId);
92  // add new customer instances
93  tx.begin();
94  session.makePersistentAll(customers);
95  tx.commit();
96  // get rid of them when we're done
97  addTearDownClasses(Customer.class);
98  addTearDownClasses(Order.class);
99  addTearDownClasses(OrderLine.class);
100  }
101 
102  private void createCustomerInstances(int numberToCreate) {
103  for (int i = 0; i < numberToCreate; ++i) {
104  Customer customer = session.newInstance(Customer.class);
105  customer.setId(i);
106  customer.setName("Customer number " + i);
107  customer.setMagic(i * 100);
108  customers.add(customer);
109  }
110  }
111 
119  public void test() {
120  List<Thread> threads = new ArrayList<Thread>();
121  // create thread group
122  threadGroup = new ThreadGroup("Stuff");
123  // create uncaught exception handler
124  MyUncaughtExceptionHandler uncaughtExceptionHandler = new MyUncaughtExceptionHandler();
125  Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
126  // create all threads
127  for (int i = 0; i < numberOfThreads ; ++i) {
128  Thread thread = new Thread(threadGroup, new StuffToDo());
129  threads.add(thread);
130  thread.start();
131  }
132  // wait until all threads have finished
133  for (Thread t: threads) {
134  try {
135  t.join();
136  } catch (InterruptedException e) {
137  throw new RuntimeException("Interrupted while joining threads.");
138  }
139  }
140  // if any uncaught exceptions (from threads) signal an error
141  for (Throwable thrown: uncaughtExceptionHandler.getUncaughtExceptions()) {
142  error("Caught exception: " + thrown.getClass().getName() + ": " + thrown.getMessage());
143  StackTraceElement[] elements = thrown.getStackTrace();
144  for (StackTraceElement element: elements) {
145  error(" at " + element.toString());
146  }
147  }
148  // summarize for the record
149  if (getDebug()) {
150  System.out.println("Number of threads: " + numberOfThreads +
151  "; number of new customers per thread: " + numberOfNewCustomersPerThread +
152  "; number of orders per new customer: " + numberOfNewOrdersPerNewCustomer);
153  System.out.println("Created " + nextCustomerId + " customers; " +
154  nextOrderId + " orders; and " + nextOrderLineId + " order lines.");
155  System.out.println("Deleted " + numberOfDeletedOrders + " orders; and " +
156  numberOfDeletedOrderLines + " order lines.");
157  System.out.println("Updated " + numberOfUpdatedOrderLines + " order lines.");
158  }
159  errorIfNotEqual("Failed to create customers.",
160  numberOfThreads * numberOfNewCustomersPerThread + numberOfInitialCustomers, nextCustomerId);
161  errorIfNotEqual("Failed to create orders. ",
162  numberOfThreads * numberOfNewCustomersPerThread * numberOfNewOrdersPerNewCustomer, nextOrderId);
163  // double check the orders to make sure they were updated correctly
164  Session session = sessionFactory.getSession();
165  QueryDomainType<OrderLine> queryOrderType = session.getQueryBuilder().createQueryDefinition(OrderLine.class);
166  queryOrderType.where(queryOrderType.get("orderId").equal(queryOrderType.param("orderId")));
167  Query<OrderLine> query = session.createQuery(queryOrderType);
168  for (Order order: orders) {
169  int orderId = order.getId();
170  // replace order with its persistent representation
171  order = session.find(Order.class, orderId);
172  double expectedTotal = order.getValue();
173  double actualTotal = 0.0d;
174  for (OrderLine orderLine: getOrderLines(session, query, orderId)) {
175  actualTotal += orderLine.getTotalValue();
176  }
177  errorIfNotEqual("For order " + orderId + ", order value does not equal sum of order line values.",
178  expectedTotal, actualTotal);
179  }
180  failOnError();
181  }
182 
194  class StuffToDo implements Runnable {
195 
196  private Random myRandom = new Random();
197 
198  public void run() {
199  // get my own session
200  Session session = sessionFactory.getSession();
201  QueryDomainType<OrderLine> queryOrderType = session.getQueryBuilder().createQueryDefinition(OrderLine.class);
202  queryOrderType.where(queryOrderType.get("orderId").equal(queryOrderType.param("orderId")));
203  Query<OrderLine> query = session.createQuery(queryOrderType);
204  for (int i = 0; i < numberOfNewCustomersPerThread; ++i) {
205  // create a new customer
206  createCustomer(session, String.valueOf(Thread.currentThread().getId()));
207  for (int j = 0; j < numberOfNewOrdersPerNewCustomer ; ++j) {
208  // create a new order
209  createOrder(session, myRandom);
210  }
211  }
212  // update orders
213  for (int j = 0; j < numberOfUpdatesPerThread; ++j) {
214  updateOrder(session, myRandom, query);
215  }
216  // delete an order
217  deleteOrder(session, myRandom, query);
218  }
219 
220  }
221 
227  private void createCustomer(Session session, String threadId) {
228  Customer customer = session.newInstance(Customer.class);
229  int id = getNextCustomerId();
230  customer.setId(id);
231  customer.setName("Customer number " + id + " thread " + threadId);
232  customer.setMagic(id * 10000);
233  session.makePersistent(customer); // autocommit for this
234  addCustomer(customer);
235  }
236 
243  public void createOrder(Session session, Random random) {
244  session.currentTransaction().begin();
245  // get an order number
246  int orderid = getNextOrderId();
247  Order order = session.newInstance(Order.class);
248  order.setId(orderid);
249  // get a random customer number
250  int customerId = random .nextInt(nextCustomerId);
251  order.setCustomerId(customerId);
252  order.setDescription("Order " + orderid + " for Customer " + customerId);
253  Double orderValue = 0.0d;
254  // now create some order lines
255  int numberOfOrderLines = random.nextInt(maximumOrderLinesPerOrder);
256  for (int i = 0; i < numberOfOrderLines; ++i) {
257  int orderLineNumber = getNextOrderLineId();
258  OrderLine orderLine = session.newInstance(OrderLine.class);
259  orderLine.setId(orderLineNumber);
260  orderLine.setOrderId(orderid);
261  long quantity = random.nextInt(maximumQuantityPerOrderLine);
262  orderLine.setQuantity(quantity);
263  float unitPrice = ((float)random.nextInt(maximumUnitPrice)) / 4;
264  orderLine.setUnitPrice(unitPrice);
265  double orderLineValue = unitPrice * quantity;
266  orderValue += orderLineValue;
267  if (getDebug()) System.out.println("For order " + orderid + " orderline " + orderLineNumber +
268  " order line value " + orderLineValue + " order value " + orderValue);
269  orderLine.setTotalValue(orderLineValue);
270  addOrderLine(orderLine);
271  session.persist(orderLine);
272  }
273  order.setValue(orderValue);
274  session.persist(order);
275  session.currentTransaction().commit();
276  addOrder(order);
277  }
278 
285  public void updateOrder(Session session, Random random, Query<OrderLine> query) {
286  session.currentTransaction().begin();
287  Order order = null;
288  // pick an order to update; prevent anyone else from updating the same order
289  order = removeOrderFromOrdersCollection(random);
290  if (order == null) {
291  return;
292  }
293  int orderId = order.getId();
294  // replace order with its persistent representation
295  order = session.find(Order.class, orderId);
296  List<OrderLine> orderLines = getOrderLines(session, query, orderId);
297  int numberOfOrderLines = orderLines.size();
298  OrderLine orderLine = null;
299  double orderValue = order.getValue();
300  if (numberOfOrderLines > 0) {
301  int index = random.nextInt(numberOfOrderLines);
302  orderLine = orderLines.get(index);
303  orderValue -= orderLine.getTotalValue();
304  updateOrderLine(orderLine, random);
305  orderValue += orderLine.getTotalValue();
306  }
307  order.setValue(orderValue);
308  session.updatePersistent(orderLine);
309  session.updatePersistent(order);
310  session.currentTransaction().commit();
311  // put order back now that we're done updating it
312  addOrder(order);
313  }
314 
320  private void updateOrderLine(OrderLine orderLine, Random random) {
321  int orderid = orderLine.getOrderId();
322  int orderLineNumber = orderLine.getId();
323  double previousValue = orderLine.getTotalValue();
324  long quantity = random.nextInt(maximumQuantityPerOrderLine );
325  orderLine.setQuantity(quantity);
326  float unitPrice = ((float)random.nextInt(maximumUnitPrice)) / 4;
327  orderLine.setUnitPrice(unitPrice);
328  double orderLineValue = unitPrice * quantity;
329  orderLine.setTotalValue(orderLineValue);
330  if (getDebug()) System.out.println("For order " + orderid + " orderline " + orderLineNumber +
331  " previous order line value " + previousValue + " new order line value " + orderLineValue);
332  synchronized (orderlines) {
333  ++numberOfUpdatedOrderLines;
334  }
335  }
336 
343  public void deleteOrder(Session session, Random random, Query<OrderLine> query) {
344  session.currentTransaction().begin();
345  Order order = null;
346  // pick an order to delete
347  order = removeOrderFromOrdersCollection(random);
348  if (order == null) {
349  return;
350  }
351  int orderId = order.getId();
352  List<OrderLine> orderLines = getOrderLines(session, query, orderId);
353  removeOrderLinesFromOrderLinesCollection(orderLines);
354  session.deletePersistentAll(orderLines);
355  session.deletePersistent(order);
356  session.currentTransaction().commit();
357  }
358 
359  private List<OrderLine> getOrderLines(Session session, Query<OrderLine> query, int orderId) {
360  query.setParameter("orderId", orderId);
361  return query.getResultList();
362  }
363 
364  private Order removeOrderFromOrdersCollection(Random random) {
365  synchronized(orders) {
366  int numberOfOrders = orders.size();
367  if (numberOfOrders < 10) {
368  return null;
369  }
370  int orderId = random.nextInt(numberOfOrders);
371  ++numberOfDeletedOrders;
372  return orders.remove(orderId);
373  }
374  }
375 
376  private void removeOrderLinesFromOrderLinesCollection(Collection<OrderLine> orderLinesToRemove) {
377  synchronized(orderlines) {
378  orderlines.removeAll(orderLinesToRemove);
379  numberOfDeletedOrderLines += orderLinesToRemove.size();
380  }
381  }
382 
386  private void addCustomer(Customer customer) {
387  synchronized(customers) {
388  customers.add(customer);
389  }
390  }
391 
395  private int getNextCustomerId() {
396  synchronized(customers) {
397  return nextCustomerId++;
398  }
399  }
400 
404  private int getNextOrderId() {
405  synchronized(orders) {
406  return nextOrderId++;
407  }
408  }
409 
413  private int getNextOrderLineId() {
414  synchronized(orderlines) {
415  return nextOrderLineId++;
416  }
417  }
418 
423  private void addOrder(Order order) {
424  synchronized(orders) {
425  orders.add(order);
426  }
427  }
428 
433  private void addOrderLine(OrderLine orderLine) {
434  synchronized(orderlines) {
435  orderlines.add(orderLine);
436  }
437  }
438 
439 }