package org.openbravo.test.dal;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.junit.Test;
import org.openbravo.dal.core.OBContext;
import org.openbravo.dal.core.SessionHandler;
import org.openbravo.dal.service.OBDal;
import org.openbravo.model.ad.module.Module;
import org.openbravo.test.base.OBBaseTest;

public class DalProxyConcurrency extends OBBaseTest {

  @Test
  public void concurrencyInProxies() throws InterruptedException {
    for (int i = 1; i <= 10; i++) {
      testProxyConcurrency(i, 1_000_000);
    }
  }

  private void testProxyConcurrency(int numThreaads, final int numLoops)
      throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(numThreaads);

    ArrayList<Callable<Long>> threads = new ArrayList<Callable<Long>>();
    for (int i = 0; i < numThreaads; i++) {
      threads.add(new Callable<Long>() {
        @Override
        public Long call() throws Exception {
          OBContext.setOBContext("0");
          Connection cn = OBDal.getInstance().getConnection();
          try {
            // each thread has its own proxy instance
            Module mod = OBDal.getInstance().get(Module.class, "0");

            long t = System.currentTimeMillis();
            for (int j = 0; j < numLoops; j++) {
              mod.getClient().getId();
            }

            long time = System.currentTimeMillis() - t;
            return time;
          } finally {
            SessionHandler.getInstance().commitAndClose();
            OBDal.getInstance().getSession().disconnect();
            cn.close();
          }
        }
      });
    }
    long t = System.currentTimeMillis();
    executor.invokeAll(threads, 5, TimeUnit.MINUTES);

    System.out.println((System.currentTimeMillis() - t) + " - threads " + numThreaads + " loops "
        + numLoops);
  }

}
