/** * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, * org.olat.core.gui.components.Component, org.olat.core.gui.control.Event) */ @Override public void event(UserRequest ureq, Component source, Event event) { if (STATISTICS_FULL_RECALCULATION_TRIGGER_BUTTON.equals(event.getCommand())) { StatisticUpdateManager statisticUpdateManager = getStatisticUpdateManager(); if (statisticUpdateManager == null) { log_.info("event: UpdateStatisticsJob configured, but no StatisticManager available"); } else { String title = getTranslator().translate("statistics.fullrecalculation.really.title"); String text = getTranslator().translate("statistics.fullrecalculation.really.text"); dialogCtr_ = DialogBoxUIFactory.createYesNoDialog(ureq, getWindowControl(), title, text); listenTo(dialogCtr_); dialogCtr_.activate(); } } else if (STATISTICS_UPDATE_TRIGGER_BUTTON.equals(event.getCommand())) { StatisticUpdateManager statisticUpdateManager = getStatisticUpdateManager(); if (statisticUpdateManager == null) { log_.info("event: UpdateStatisticsJob configured, but no StatisticManager available"); } else { statisticUpdateManager.updateStatistics(false, getUpdateFinishedCallback()); refreshUIState(); getInitialComponent().setDirty(true); } } }
private void updateStatisticUpdateOngoingFlag() { StatisticUpdateManager statisticUpdateManager = getStatisticUpdateManager(); if (statisticUpdateManager == null) { log_.info("event: UpdateStatisticsJob configured, but no StatisticManager available"); content.contextPut("statisticUpdateOngoing", Boolean.TRUE); } else { content.contextPut("statisticUpdateOngoing", statisticUpdateManager.updateOngoing()); } }
private void checkPublisher(Publisher p) { try { if (!NotificationsUpgradeHelper.checkCourse(p)) { log.info("deactivating publisher with key; " + p.getKey(), null); NotificationsManager.getInstance().deactivate(p); } } catch (Exception e) { log.error("", e); } }
@Override public void run() { long start = System.nanoTime(); log.info("Start scanning for QTI resources"); List<String> types = new ArrayList<>(2); types.add(TestFileResource.TYPE_NAME); types.add(SurveyFileResource.TYPE_NAME); List<OLATResource> qtiResources = CoreSpringFactory.getImpl(OLATResourceManager.class).findResourceByTypes(types); DBFactory.getInstance().commitAndCloseSession(); for (OLATResource qtiResource : qtiResources) { OnyxModule.isOnyxTest(qtiResource); } log.info( qtiResources.size() + " QTI Resources scanned in (ms): " + CodeHelper.nanoToMilliTime(start)); }
private final void executeProcess(Process proc) { StringBuilder errors = new StringBuilder(); StringBuilder output = new StringBuilder(); InputStream stderr = proc.getErrorStream(); InputStreamReader iserr = new InputStreamReader(stderr); BufferedReader berr = new BufferedReader(iserr); String line = null; try { while ((line = berr.readLine()) != null) { errors.append(line); } } catch (IOException e) { // } InputStream stdout = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(stdout); BufferedReader br = new BufferedReader(isr); line = null; try { while ((line = br.readLine()) != null) { output.append(line); } } catch (IOException e) { // } try { int exitValue = proc.waitFor(); if (log.isDebug()) { log.info("PDF extracted: " + exitValue); } } catch (InterruptedException e) { // } if (log.isDebug()) { log.error(errors.toString()); log.info(output.toString()); } }
/** internal counter method * */ private synchronized void returnSlot(final Identity identity) { identitiesOfJobsCurrentlyRunning_.remove(identity); log_.info( "returnSlot: user " + identity.getName() + " returns a slot. Running count: " + identitiesOfJobsCurrentlyRunning_.size() + ", Total pending jobs: " + waitingCnt_); notifyAll(); }
public void event(UserRequest ureq, Controller source, Event event) { if (source == dialogCtr_) { if (DialogBoxUIFactory.isYesEvent(event)) { StatisticUpdateManager statisticUpdateManager = getStatisticUpdateManager(); if (statisticUpdateManager == null) { log_.info("event: UpdateStatisticsJob configured, but no StatisticManager available"); } else { statisticUpdateManager.updateStatistics(true, getUpdateFinishedCallback()); refreshUIState(); getInitialComponent().setDirty(true); } } } }
private void refreshUIState() { boolean enabled = false; String cronExpression = ""; if (CoreSpringFactory.containsBean("schedulerFactoryBean")) { log_.info("refreshUIState: schedulerFactoryBean found"); Object schedulerFactoryBean = CoreSpringFactory.getBean("schedulerFactoryBean"); if (schedulerFactoryBean != null && schedulerFactoryBean instanceof Scheduler) { Scheduler schedulerBean = (Scheduler) schedulerFactoryBean; int triggerState; try { triggerState = schedulerBean.getTriggerState("updateStatisticsTrigger", null /*trigger group*/); enabled = (triggerState != Trigger.STATE_NONE) && (triggerState != Trigger.STATE_ERROR); log_.info( "refreshUIState: updateStatisticsTrigger state was " + triggerState + ", enabled now: " + enabled); } catch (SchedulerException e) { log_.warn( "refreshUIState: Got a SchedulerException while asking for the updateStatisticsTrigger's state", e); } } CronTriggerBean triggerBean = (CronTriggerBean) CoreSpringFactory.getBean("updateStatisticsTrigger"); JobDetail jobDetail = triggerBean.getJobDetail(); enabled &= jobDetail.getName().equals("org.olat.statistics.job.enabled"); log_.info("refreshUIState: org.olat.statistics.job.enabled check, enabled now: " + enabled); cronExpression = triggerBean.getCronExpression(); StatisticUpdateManager statisticUpdateManager = getStatisticUpdateManager(); if (statisticUpdateManager == null) { log_.info("refreshUIState: statisticUpdateManager not configured"); enabled = false; } else { enabled &= statisticUpdateManager.isEnabled(); log_.info("refreshUIState: statisticUpdateManager configured, enabled now: " + enabled); } } else { log_.info("refreshUIState: schedulerFactoryBean not found"); } if (enabled) { content.contextPut( "status", getTranslator().translate("statistics.status.enabled", new String[] {cronExpression})); } else { content.contextPut("status", getTranslator().translate("statistics.status.disabled")); } content.contextPut("statisticEnabled", enabled); recalcLastUpdated(); updateStatisticUpdateOngoingFlag(); }
@Test public void testNestedLockingSupported() { log.info("testing if nested locking is supported"); // make sure all three row entries for the locks are created, otherwise the system-wide locking // applied on lock-row-creation cannot support row-level-locking by definition. PLock pc1 = pessimisticLockManager.findOrPersistPLock("blabla"); assertNotNull(pc1); PLock pc2 = pessimisticLockManager.findOrPersistPLock("blublu"); assertNotNull(pc2); PLock pc3 = pessimisticLockManager.findOrPersistPLock("blibli"); assertNotNull(pc3); dbInstance.closeSession(); final List<Long> holder = new ArrayList<Long>(1); // first thread acquires the two locks and waits and continues holding the lock for some time. PLock p1 = pessimisticLockManager.findOrPersistPLock("blabla"); assertNotNull(p1); PLock p3 = pessimisticLockManager.findOrPersistPLock("blibli"); assertNotNull(p3); new Thread( new Runnable() { public void run() { PLock p2 = pessimisticLockManager.findOrPersistPLock("blibli"); assertNotNull(p2); long p2Acquired = System.nanoTime(); holder.add(new Long(p2Acquired)); dbInstance.closeSession(); } }) .start(); sleep(500); boolean acOk = holder.size() == 0; // the commit will drop the lock on blibli d dbInstance.closeSession(); sleep(500); boolean acNowOk = holder.size() == 1; // if row locking is not supported, then the timestamp when p2 has been acquired will be shortly // -after- p1 has been released assertTrue("since holding the blabla lock, no other may acquire it", acOk); assertTrue( "after having released the blabla lock, a next waiting thread must have acquired it after some time", acNowOk); }
private void doNoLockingEnrol(Identity i, SecurityGroup group) { // check that below max try { StringBuilder sb = new StringBuilder(); int cnt = BaseSecurityManager.getInstance().countIdentitiesOfSecurityGroup(group); sb.append("enrol:cnt:" + cnt); if (cnt < MAX_COUNT) { // now sleep a while to allow others to think also that there is still space left in the // group sleep(100); // now add the user to the security group sb.append(" adding " + i.getName() + ": current.. " + cnt + ", max = " + MAX_COUNT); BaseSecurityManager.getInstance().addIdentityToSecurityGroup(i, group); } log.info(sb.toString()); } catch (Exception e) { log.error("", e); } }
/** Test method i18nManager.searchForBundleNamesContainingI18nFiles() */ @Test public void testSearchForBundleNamesContainingI18nFiles() { long start = System.currentTimeMillis(); List<String> foundBundles = i18nMgr.searchForBundleNamesContainingI18nFiles(); long end = System.currentTimeMillis(); log.info( "Searching for " + foundBundles.size() + " bundles on OLAT source path took me " + (end - start) + "ms", "testSearchForBundleNamesContainingI18nFiles"); // Must contain packages from core assertTrue(foundBundles.contains("org.olat.core")); assertTrue(foundBundles.contains("org.olat.core.gui.control")); assertTrue(foundBundles.contains("org.olat.core.commons.fullWebApp")); // Must contain packages from olat app assertTrue(foundBundles.contains("org.olat")); assertTrue(foundBundles.contains("org.olat.course")); }
/** internal counter method * */ private synchronized void waitForSlot(final Identity identity) { waitingCnt_++; while (identitiesOfJobsCurrentlyRunning_.size() > concurrentExportsPerNode_ || identitiesOfJobsCurrentlyRunning_.contains(identity)) { try { log_.info( "waitForSlot: user " + identity.getName() + " wants to archive a course log, but the queue is full. Running count: " + identitiesOfJobsCurrentlyRunning_.size() + ". Total pending jobs: " + waitingCnt_); wait(); } catch (final InterruptedException ie) { // this empty catch is ok } } waitingCnt_--; identitiesOfJobsCurrentlyRunning_.add(identity); }
@Test public void testSingleRowLockingSupported() { log.info( "testing if one lock only locks the given row and not the complete table (test whether the database supports rowlocking)"); // make sure both row entries for the locks are created, otherwise the system-wide locking // applied on lock-row-creation cannot support row-level-locking by definition. PLock pc1 = pessimisticLockManager.findOrPersistPLock("blabla"); Assert.assertNotNull(pc1); PLock pc2 = pessimisticLockManager.findOrPersistPLock("blublu"); Assert.assertNotNull(pc2); dbInstance.closeSession(); final List<Long> holder = new ArrayList<Long>(1); // first thread acquires the lock and waits and continues holding the lock for some time. PLock p1 = pessimisticLockManager.findOrPersistPLock("blabla"); Assert.assertNotNull(p1); new Thread( new Runnable() { public void run() { PLock p2 = pessimisticLockManager.findOrPersistPLock("blublu"); assertNotNull(p2); long p2Acquired = System.nanoTime(); holder.add(new Long(p2Acquired)); dbInstance.closeSession(); } }) .start(); sleep(500); long p1AboutToRelease = System.nanoTime(); dbInstance.closeSession(); // if row locking is not supported, then the timestamp when p2 has been acquired will be shortly // -after- p1 has been released boolean singleRowLockingOk = holder.size() > 0 && holder.get(0).longValue() < p1AboutToRelease; assertTrue( "the database does not seem to support row locking when executing 'select for update', critical for performance!, ", singleRowLockingOk); }
@Test public void testSync() { log.info("testing enrollment"); // ------------------ now check with lock ------------------- // create a group // create users final List<Identity> identities = new ArrayList<Identity>(); for (int i = 0; i < MAX_COUNT + MAX_USERS_MORE; i++) { Identity id = JunitTestHelper.createAndPersistIdentityAsUser( "u-" + i + "-" + UUID.randomUUID().toString()); identities.add(id); log.info("testSync: Identity=" + id.getName() + " created"); } dbInstance.closeSession(); final SecurityGroup group2 = BaseSecurityManager.getInstance().createAndPersistSecurityGroup(); // make sure the lock has been written to the disk (tests for createOrFind see other methods) dbInstance.closeSession(); // prepare threads int numOfThreads = MAX_COUNT + MAX_USERS_MORE; final CountDownLatch finishCount = new CountDownLatch(numOfThreads); // try to enrol all in the same group for (int i = 0; i < numOfThreads; i++) { final int j = i; new Thread( new Runnable() { public void run() { try { log.info("testSync: thread started j=" + j); Identity id = identities.get(j); // PLock p2 = pessimisticLockManager.findOrPersistPLock("befinsert"); assertNotNull(p2); doNoLockingEnrol(id, group2); dbInstance.commit(); dbInstance.closeSession(); } catch (Exception e) { e.printStackTrace(); } finally { finishCount.countDown(); } } }) .start(); } try { finishCount.await(120, TimeUnit.SECONDS); } catch (InterruptedException e) { log.error("", e); } // now count dbInstance.closeSession(); int cnt2 = BaseSecurityManager.getInstance().countIdentitiesOfSecurityGroup(group2); assertTrue( "cnt should be smaller or eq than allowed since synced with select for update. cnt:" + cnt2 + ", max " + MAX_COUNT, cnt2 <= MAX_COUNT); assertTrue( "cnt should be eq to allowed since synced with select for update. cnt:" + cnt2 + ", max " + MAX_COUNT, cnt2 == MAX_COUNT); log.info("cnt lock " + cnt2); }
@Test public void testPerf() { log.info("testing what the throughput is for the pessimistic locking"); // test what the throughput is for the pessimistic locking. // take 500 threads (created and started with no delay (as fast as the vm can) trying to acquire // a plock on 20 different olatresourceables. // measure how long that takes. and warn if it exceeds an upper boundary. // the server is assumed to have around 2GHz cpu and 2GBytes RAM. // the first thread to acquire a new olatres will first lock on the global lock and then create // the new entry to lock upon. // we therefore also measure how long it takes again when all locks have already been inserted // into the plock table. // results: on a std. laptop with postgres 8, 500 threads with 20 resourceables take about // 3000ms (thread creation inclusive) // -> about // 1. prepare collection int numthreads = 500; int numores = 1; // 2. create 500 threads and start them long start = System.currentTimeMillis(); final CountDownLatch doneSignal = new CountDownLatch(numthreads); for (int i = 0; i < numthreads; i++) { final String asset = "assetaboutaslongasores" + (i % numores); Runnable r = new Runnable() { public void run() { try { pessimisticLockManager.findOrPersistPLock(asset); doneSignal.countDown(); } catch (Exception e) { e.printStackTrace(); } finally { dbInstance.closeSession(); } } }; new Thread(r).start(); } // 4. wait till all are finished or it takes too long try { doneSignal.await(20, TimeUnit.SECONDS); log.info("perf for Plocktest:testPerf(): " + (System.currentTimeMillis() - start)); } catch (InterruptedException e) { fail("Test takes too long (more than 20s)"); } // repeat the same again - this time it should/could be faster // 2. create 500 threads and start them long start2 = System.currentTimeMillis(); final CountDownLatch doneSignal2 = new CountDownLatch(numthreads); for (int i2 = 0; i2 < numthreads; i2++) { final String asset = "assetaboutaslongasores" + (i2 % numores); Runnable r = new Runnable() { public void run() { try { pessimisticLockManager.findOrPersistPLock(asset); doneSignal2.countDown(); } catch (Exception e) { e.printStackTrace(); } finally { dbInstance.commitAndCloseSession(); } } }; new Thread(r).start(); } // 4. wait till all are finished or it takes too long try { boolean interrupt = doneSignal.await(20, TimeUnit.SECONDS); log.info("perf (again) for Plocktest:testPerf(): " + (System.currentTimeMillis() - start2)); assertTrue("Test takes too long (more than 20s)", interrupt); } catch (InterruptedException e) { fail("" + e.getMessage()); } }
@Test public void testDeadLockTimeout() { log.info("testing if deadlock detection and handling is supported"); // make sure all three row entries for the locks are created, otherwise the system-wide locking // applied on lock-row-creation cannot support row-level-locking by definition. PLock pc1 = pessimisticLockManager.findOrPersistPLock("blabla"); assertNotNull(pc1); PLock pc2 = pessimisticLockManager.findOrPersistPLock("blublu"); assertNotNull(pc2); PLock pc3 = pessimisticLockManager.findOrPersistPLock("blibli"); assertNotNull(pc3); dbInstance.closeSession(); /** * t1 t2 bla bli .. .. .. .. .. .. bli .. .. .. bla -> deadlock! t2 waits on bla (already * acquired by t1, but t1 waits on bli, already acquired by t2) */ final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1)); final CountDownLatch finishCount = new CountDownLatch(2); // t1 new Thread( new Runnable() { public void run() { try { PLock p1 = pessimisticLockManager.findOrPersistPLock("blabla"); assertNotNull(p1); sleep(250); // now try to acquire blibli but that fails, since blibli is already locked by // thread 2. // but thread 2 cannot continue either, since it is waiting for lock blabla, which // is already hold by thread 1 // -> deadlock PLock p3 = pessimisticLockManager.findOrPersistPLock("blibli"); assertNotNull(p3); } catch (Exception e) { exceptionHolder.add(e); } finally { try { dbInstance.closeSession(); } catch (Exception e) { // ignore } finishCount.countDown(); } } }) .start(); // t2 new Thread( new Runnable() { public void run() { try { PLock p2 = pessimisticLockManager.findOrPersistPLock("blibli"); assertNotNull(p2); sleep(500); PLock p3 = pessimisticLockManager.findOrPersistPLock("blabla"); assertNotNull(p3); } catch (Exception e) { exceptionHolder.add(e); } finally { try { dbInstance.closeSession(); } catch (Exception e) { // ignore } finishCount.countDown(); } } }) .start(); // sleep until t1 and t2 should have terminated/excepted try { finishCount.await(8, TimeUnit.SECONDS); } catch (InterruptedException e) { Assert.fail("Takes too long (more than 8sec)"); } // if not -> they are in deadlock and the db did not detect it for (Exception exception : exceptionHolder) { log.error("exception: ", exception); } assertTrue("expected a deadlock exception, but got none", exceptionHolder.size() > 0); }
public void asyncArchiveCourseLogFiles( final Identity identity, final Runnable callback, final Long oresID, final String exportDir, final Date begin, final Date end, final boolean adminLog, final boolean userLog, final boolean statisticLog, final String charset, final Locale locale, final String email) { // argument checks if (identity == null) { throw new IllegalArgumentException("identity must not be null"); } if (callback == null) { throw new IllegalArgumentException("callback must not be null"); } // DEBUG ONLY synchronized (this) { log_.info( "asyncArchiveCourseLogFiles: user " + identity.getName() + " wants to archive a course log. Already pending jobs: " + waitingCnt_); } TaskExecutorManager.getInstance() .runTask( new Runnable() { @Override public void run() { try { log_.info( "asyncArchiveCourseLogFiles: user " + identity.getName() + " aquires lock for archiving course log"); waitForSlot(identity); log_.info( "asyncArchiveCourseLogFiles: user " + identity.getName() + " starts archiving..."); ExportManager.getInstance() .archiveCourseLogFiles( oresID, exportDir, begin, end, adminLog, userLog, statisticLog, charset, locale, email); log_.info( "asyncArchiveCourseLogFiles: user " + identity.getName() + " finished archiving..."); } finally { returnSlot(identity); log_.info( "asyncArchiveCourseLogFiles: user " + identity.getName() + " releases lock for archiving course log"); callback.run(); } } }); }
@Test public void testLockWaitTimout() { // Ignore Test if DB is PostgreSQL. PostgreSQL has not lock timeout assumeTrue(!isPostgresqlConfigured() && !isOracleConfigured()); final String asset = "testLockWaitTimout"; log.info("testing if holding a lock timeouts"); // make sure all three row entries for the locks are created, otherwise the system-wide locking // applied on lock-row-creation cannot support row-level-locking by definition. PLock pc3 = pessimisticLockManager.findOrPersistPLock("blibli"); assertNotNull(pc3); dbInstance.closeSession(); /** t1 t2 .. bli .. .. .. .. .. .. bli .. .. .. .... hold for longer than 30 secs */ final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1)); final CountDownLatch finishCount = new CountDownLatch(2); // t1 new Thread( new Runnable() { public void run() { try { sleep(500); PLock p3 = pessimisticLockManager.findOrPersistPLock(asset); assertNotNull(p3); } catch (Exception e) { exceptionHolder.add(e); } finally { finishCount.countDown(); try { dbInstance.closeSession(); } catch (Exception e) { // ignore } } } }) .start(); // t2 new Thread( new Runnable() { public void run() { try { PLock p2 = pessimisticLockManager.findOrPersistPLock(asset); assertNotNull(p2); sleep(55000); // holding the lock for more than the transaction timeout // (normally 30secs, configured where? hib) should cause a lock timeout // if the db is configured so (innodb_lock_wait_timeout). } catch (Exception e) { exceptionHolder.add(e); } finally { finishCount.countDown(); try { dbInstance.closeSession(); } catch (Exception e) { // ignore } } } }) .start(); // sleep until t1 and t2 should have terminated/excepted try { log.info("Sleep 55s"); finishCount.await(60, TimeUnit.SECONDS); } catch (InterruptedException e) { Assert.fail(""); } Assert.assertEquals( "expected a lock wait timeout exceeded exception", 1, exceptionHolder.size()); }
/** Test methods i18nManager.findInKeys() i18nManager.findInValues() */ @Test public void testFindInKeysAndFindInValues() { Locale testLocale = i18nMgr.getLocaleOrDefault("de"); // in keys speedtest long start = System.currentTimeMillis(); List<I18nItem> foundTransItems = i18nMgr.findI18nItemsByKeySearch("menu", testLocale, testLocale, null, true); long end = System.currentTimeMillis(); log.info( "Searching for term 'menu' took me " + (end - start) + "ms, found " + foundTransItems.size() + " item", "testFindInKeys"); // in values speedtest start = System.currentTimeMillis(); foundTransItems = i18nMgr.findI18nItemsByValueSearch("OLAT", testLocale, testLocale, null, true); int uppercaseSize = foundTransItems.size(); end = System.currentTimeMillis(); log.info( "Searching for term 'OLAT' took me " + (end - start) + "ms, found " + foundTransItems.size() + " item", "testFindInKeys"); // uppercase and lowercase must find the same values foundTransItems = i18nMgr.findI18nItemsByValueSearch("olat", testLocale, testLocale, null, true); assertEquals(uppercaseSize, foundTransItems.size()); // find in values and regexp tests: * is replaced with regexp, assertEquals( 1, i18nMgr .findI18nItemsByValueSearch( "Eingabefehler aufgetreten", testLocale, testLocale, null, true) .size()); assertEquals( 1, i18nMgr .findI18nItemsByValueSearch( "Eingabefehler*aufgetreten", testLocale, testLocale, null, true) .size()); assertEquals( 1, i18nMgr .findI18nItemsByValueSearch( "Eingabefe*ler*aufgetreten", testLocale, testLocale, null, true) .size()); assertEquals( 2, i18nMgr .findI18nItemsByValueSearch( "Bitte f*llen Sie dieses Feld aus", testLocale, testLocale, null, true) .size()); assertEquals( 1, i18nMgr .findI18nItemsByValueSearch( "Bitte f*llen Sie dieses Feld aus", testLocale, testLocale, "org.olat.core", false) .size()); // escape reserved regexp keywords assertEquals( 1, i18nMgr .findI18nItemsByValueSearch("OpenOLAT", testLocale, testLocale, "org.olat.core", false) .size()); assertEquals( 1, i18nMgr .findI18nItemsByValueSearch("nOLAT", testLocale, testLocale, "org.olat.core", false) .size()); assertEquals( 1, i18nMgr .findI18nItemsByValueSearch("*learning", testLocale, testLocale, "org.olat.core", false) .size()); assertEquals( 1, i18nMgr .findI18nItemsByValueSearch( "Eingaben</i> </br >*<b>bold</b>*<br>_<i>italic</i>_<br>* Listen", testLocale, testLocale, null, true) .size()); assertEquals( 1, i18nMgr .findI18nItemsByValueSearch( "dargestellt werden. Bitte rufen Sie", testLocale, testLocale, null, true) .size()); // multi line value search assertEquals( 1, i18nMgr .findI18nItemsByValueSearch( "Die Aktion konnte nicht ausgef\u00FChrt werden", testLocale, testLocale, null, true) .size()); }
/** T1 T2 */ @Test public void testReentrantLock2Threads() { final String asset = "p1-2"; // make sure the lock is created first PLock pc = pessimisticLockManager.findOrPersistPLock(asset); assertNotNull(pc); dbInstance.closeSession(); final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1)); final CountDownLatch finishCount = new CountDownLatch(2); // thread 1 new Thread( new Runnable() { public void run() { try { PLock pc1 = pessimisticLockManager.findOrPersistPLock(asset); assertNotNull(pc1); log.info("Thread-1: got PLock pc1=" + pc1); log.info("Thread-1: sleep 1sec"); sleep(1000); PLock pc2 = pessimisticLockManager.findOrPersistPLock(asset); assertNotNull(pc2); log.info("Thread-1: got PLock pc2=" + pc2); log.info("Thread-1: finished"); } catch (Exception e) { exceptionHolder.add(e); } finally { finishCount.countDown(); try { dbInstance.commitAndCloseSession(); } catch (Exception e) { // ignore } } } }) .start(); // thread 2 new Thread( new Runnable() { public void run() { try { log.info("Thread-2: sleep 0.5sec"); sleep(500); log.info("Thread-2: try to get PLock..."); PLock p1 = pessimisticLockManager.findOrPersistPLock(asset); assertNotNull(p1); log.info("Thread-2: got PLock p1=" + p1); log.info("Thread-2: sleep 1sec"); sleep(1000); PLock p2 = pessimisticLockManager.findOrPersistPLock(asset); assertNotNull(p2); log.info("Thread-1: got PLock p2=" + p2); log.info("Thread-1: finished"); } catch (Exception e) { exceptionHolder.add(e); } finally { finishCount.countDown(); try { dbInstance.commitAndCloseSession(); } catch (Exception e) { // ignore } } } }) .start(); // sleep until t1 and t2 should have terminated/excepted try { finishCount.await(60, TimeUnit.SECONDS); } catch (InterruptedException e) { Assert.fail("Test takes too long (more than 60s)"); } // if not -> they are in deadlock and the db did not detect it for (Exception exception : exceptionHolder) { log.info("exception: " + exception.getMessage()); exception.printStackTrace(); } assertTrue("exception in test => see sysout", exceptionHolder.size() == 0); }
/** * Performance test of 500 propertycreations per type. Rename to testPerf500Properties to include * this test in the test suit. */ @Test public void testPerf500Properties() { // create identity, group and resource OLATResource res = JunitTestHelper.createRandomResource(); Identity identity = JunitTestHelper.createAndPersistIdentityAsUser("prop-5-" + UUID.randomUUID().toString()); BusinessGroup group = businessGroupService.createBusinessGroup( identity, "a buddygroup", "a desc", -1, -1, false, false, null); dbInstance.commitAndCloseSession(); long start, stop; long count = 500; // create generic proerties log.info("----------------------------------------------------------------"); log.info("Performance test startet. Running " + count + " cycles per test."); log.info("CREATE generic property test started..."); start = System.currentTimeMillis(); for (int i = 0; i < count; i++) { Property p = pm.createPropertyInstance( identity, group, res, "perf500", "TestProperty" + i, new Float(1.1), new Long(123456), "stringValue", "textValue"); pm.saveProperty(p); if (i % 50 == 0) { dbInstance.commitAndCloseSession(); } } dbInstance.commitAndCloseSession(); stop = System.currentTimeMillis(); log.info( "CREATE generic property test: " + (stop - start) + " ms (" + (count * 1000 / (stop - start)) + "/sec)"); // some find identitites tests List<Identity> ids = pm.findIdentitiesWithProperty(null, null, "perf500", null, false); Assert.assertNotNull("Identities cannot be null", ids); Assert.assertFalse("Identities cannot be empty", ids.isEmpty()); Assert.assertTrue("Identities must contains reference identity", ids.contains(identity)); // create course and user properties log.info("Preparing user/group properties test. Creating additional properties.."); start = System.currentTimeMillis(); for (int i = 0; i < count; i++) { Property pUser = pm.createUserPropertyInstance( identity, "perf500", "TestProperty" + i, new Float(1.1), new Long(123456), "stringValue", "textValue"); pm.saveProperty(pUser); if (i % 50 == 0) { dbInstance.commitAndCloseSession(); } } dbInstance.commitAndCloseSession(); stop = System.currentTimeMillis(); log.info("Ready : " + (stop - start) + " ms (" + (2 * count * 1000 / (stop - start)) + "/sec)"); log.info("Starting find tests. DB holds " + count * 3 + " records."); // find generic property test log.info("FIND generic property test started..."); start = System.currentTimeMillis(); for (int i = 0; i < count; i++) { Property p = pm.findProperty(identity, group, res, "perf500", "TestProperty" + i); assertNotNull("Must find the p (count=" + i + ")", p); dbInstance.commitAndCloseSession(); } stop = System.currentTimeMillis(); log.info( "FIND generic property test: " + (stop - start) + " ms (" + (count * 1000 / (stop - start)) + "/sec)"); // find user property test log.info("FIND user property test started..."); start = System.currentTimeMillis(); for (int i = 0; i < count; i++) { Property p = pm.findUserProperty(identity, "perf500", "TestProperty" + i); assertNotNull("Must find the p (count=" + i + ")", p); dbInstance.commitAndCloseSession(); } stop = System.currentTimeMillis(); log.info( "FIND user property test: " + (stop - start) + " ms (" + (count * 1000 / (stop - start)) + "/sec)"); // find & delete log.info("FIND and DELETE generic property test started..."); start = System.currentTimeMillis(); for (int i = 0; i < count; i++) { Property p = pm.findUserProperty(identity, "perf500", "TestProperty" + i); pm.deleteProperty(p); } stop = System.currentTimeMillis(); log.info( "FIND and DELETE generic property test: " + (stop - start) + " ms (" + (count * 1000 / (stop - start)) + "/sec)"); log.info("----------------------------------------------------------------"); log.info("Performance test finished."); }