/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.repository;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.olat.basesecurity.Constants;
import org.olat.basesecurity.Manager;
import org.olat.basesecurity.ManagerFactory;
import org.olat.basesecurity.SecurityGroup;
import org.olat.commons.coordinate.cluster.ClusterSyncer;
import org.olat.core.commons.persistence.DB;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles;
import org.olat.core.logging.Tracing;
import org.olat.core.test.OlatTestCase;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.coordinate.Syncer;
import org.olat.course.CourseModule;
import org.olat.resource.OLATResource;
import org.olat.resource.OLATResourceManager;
import org.olat.test.JunitTestHelper;
import org.olat.testutils.codepoints.client.BreakpointStateException;
import org.olat.testutils.codepoints.client.CodepointClient;
import org.olat.testutils.codepoints.client.CodepointClientFactory;
import org.olat.testutils.codepoints.client.CodepointRef;
import org.olat.testutils.codepoints.client.CommunicationException;
import org.olat.testutils.codepoints.client.TemporaryPausedThread;
import org.olat.testutils.codepoints.server.CodepointInstaller;
import org.olat.testutils.codepoints.server.impl.JMSCodepointServer;
/**
* Initial Date: Mar 26, 2004
*
* @author gnaegi
*
* Comment:
*
*/
public class RepositoryManagerTest extends OlatTestCase {
private static boolean isInitialized = false;
private static String CODEPOINT_SERVER_ID = "RepositoryManagerTest";
private JMSCodepointServer codepointServer_;
/**
* @param arg0
*/
public RepositoryManagerTest(String arg0) {
super(arg0);
}
/**
* @see junit.framework.TestCase#setUp()
*/
public void setUp() {
if (RepositoryManagerTest.isInitialized == false) {
try {
DBFactory.getJunitInstance().clearDatabase();
// Setup for code-points
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
ActiveMQQueue queue = new ActiveMQQueue("olat/codepoints");
codepointServer_ = new JMSCodepointServer(connectionFactory, queue, CODEPOINT_SERVER_ID);
CodepointInstaller.installCodepointServer(codepointServer_);
System.out.println("Codepoint server startet");
RepositoryManagerTest.isInitialized = true;
} catch (Exception e) {
Tracing.logError("Error while generating database tables or opening hibernate session",
e, RepositoryManagerTest.class);
}
}
}
/**
* @see junit.framework.TestCase#tearDown()
*/
public void tearDown() {
try {
DBFactory.getInstance().closeSession();
} catch (Exception e) {
Tracing.logError("tearDown failed", e, RepositoryManagerTest.class);
}
}
/**
* Test creation of a repository entry.
*/
public void testRawRepositoryEntryCreate() {
try {
DB db = DBFactory.getInstance();
OLATResourceManager rm = OLATResourceManager.getInstance();
// create course and persist as OLATResourceImpl
OLATResourceable resourceable = new OLATResourceable() {
public String getResourceableTypeName() { return "Course";}
public Long getResourceableId() {return new Long(456);}
};
OLATResource r = rm.createOLATResourceInstance(resourceable);
db.saveObject(r);
// now make a repository entry for this course
RepositoryEntry d = new RepositoryEntry();
d.setOlatResource(r);
d.setResourcename("Lernen mit OLAT");
d.setInitialAuthor("Florian Gnägi");
d.setDisplayname("JunitTest_RepositoryEntry");
// TODO: chg: Remove for 5.3 MetaDataElement because it does not work with mySql 5.0
// and it is not used !
// lastmodified of MetaDataElement is null and is not set by hibernate because
// it is a child object od RepositoryEntry !
// It could be solved with defintion of MetaDataElement.lastmodified IS NULL = false
// MetaDataElement v1, v2, v3;
// v1 = new MetaDataElement("version", "1.0 alpha");
// d.getMetaDataElements().add(v1);
// v2 = new MetaDataElement("duration", "2h");
// d.getMetaDataElements().add(v2);
// v3 = new MetaDataElement("path", "/UNIZH/ID/MELS/");
// d.getMetaDataElements().add(v3);
db.saveObject(d);
} catch(Exception ex) {
fail("No Exception allowed. ex=" + ex.getMessage());
}
}
/**
*/
public void testQueryReferencableResourcesLimitType() {
DB db = DBFactory.getInstance();
OLATResourceManager resm = OLATResourceManager.getInstance();
RepositoryManager rm = RepositoryManager.getInstance();
Manager securityManager = ManagerFactory.getManager();
Identity id1 = JunitTestHelper.createAndPersistIdentityAsAuthor("id1");
Identity id2 = JunitTestHelper.createAndPersistIdentityAsAuthor("id2");
// generate 5000 repo entries
int numbRes = 5000;
long startCreate = System.currentTimeMillis();
for (int i = 1; i < numbRes; i++) {
// create course and persist as OLATResourceImpl
final int ifin = i;
OLATResourceable resourceable = new OLATResourceable() {
public String getResourceableTypeName() { return CourseModule.getCourseTypeName();}
public Long getResourceableId() {return new Long(ifin);}
};
OLATResource r = resm.createOLATResourceInstance(resourceable);
db.saveObject(r);
// now make a repository entry for this course
RepositoryEntry re = rm.createRepositoryEntryInstance("Florian Gnägi", "Lernen mit OLAT " + i, "yo man description bla bla + i");
re.setDisplayname("JunitTest_RepositoryEntry_" + i);
re.setOlatResource(r);
re.setAccess(RepositoryEntry.ACC_OWNERS_AUTHORS);
if ((i % 2 > 0)) {
re.setCanReference(true);
} else {
re.setCanReference(false);
}
// create security group
SecurityGroup ownerGroup = securityManager.createAndPersistSecurityGroup();
// member of this group may modify member's membership
securityManager.createAndPersistPolicy(ownerGroup, Constants.PERMISSION_ACCESS, ownerGroup);
// members of this group are always authors also
securityManager.createAndPersistPolicy(ownerGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_AUTHOR);
if ((i % 2 > 0)) {
securityManager.addIdentityToSecurityGroup(id1, ownerGroup);
} else {
securityManager.addIdentityToSecurityGroup(id2, ownerGroup);
}
re.setOwnerGroup(ownerGroup);
// save the repository entry
rm.saveRepositoryEntry(re);
// Create course admin policy for owner group of repository entry
// -> All owners of repository entries are course admins
securityManager.createAndPersistPolicy(re.getOwnerGroup(), Constants.PERMISSION_ADMIN, re.getOlatResource());
// flush database and hibernate session cache after 10 records to improve performance
// without this optimization, the first entries will be fast but then the adding new
// entries will slow down due to the fact that hibernate needs to adjust the size of
// the session cache permanently. flushing or transactions won't help since the problem
// is in the session cache.
if (i%2 == 0) {
db.closeSession();
db = DBFactory.getInstance();
}
}
long endCreate = System.currentTimeMillis();
Tracing.logDebug("created " + numbRes + " repo entries in " + (endCreate - startCreate) + "ms", RepositoryManagerTest.class);
List typelist = new ArrayList();
typelist.add(CourseModule.getCourseTypeName());
// finally the search query
long startSearchReferencable = System.currentTimeMillis();
List results = rm.queryReferencableResourcesLimitType(id1, new Roles(false, false, false, true, false, false), typelist, null, null, null);
long endSearchReferencable = System.currentTimeMillis();
Tracing.logDebug("found " + results.size() + " repo entries " + (endSearchReferencable - startSearchReferencable) + "ms", RepositoryManagerTest.class);
// only half of the items should be found
assertTrue(results.size() == (int) (numbRes / 2));
// inserting must take longer than searching, otherwhise most certainly we have a problem somewhere in the query
assertTrue((endCreate - startCreate) > (endSearchReferencable - startSearchReferencable));
}
public void testCountByTypeLimitAccess() {
DBFactory.getJunitInstance().clearDatabase();
RepositoryManager rm = RepositoryManager.getInstance();
int count = rm.countByTypeLimitAccess(CourseModule.getCourseTypeName(), RepositoryEntry.ACC_OWNERS_AUTHORS);
assertEquals(0,count);
}
/**
*
*/
public void testIncrementLaunchCounter() {
Syncer syncer = CoordinatorManager.getCoordinator().getSyncer();
assertTrue("syncer is not of type 'ClusterSyncer'", syncer instanceof ClusterSyncer);
RepositoryEntry repositoryEntry = createRepository("T1_perf2", new Long(927888101));
final Long keyRepo = repositoryEntry.getKey();
final OLATResourceable resourceable = repositoryEntry.getOlatResource();
DBFactory.getInstance().closeSession();
assertEquals("Launch counter was not 0", 0, repositoryEntry.getLaunchCounter() );
final int mainLoop = 10;
final int loop = 50; // 10 * 50 = 500
for (int m = 0; m < mainLoop; m++) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
// 1. load RepositoryEntry
RepositoryEntry repositoryEntryT1 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
RepositoryManager.getInstance().incrementLaunchCounter(repositoryEntryT1);
DBFactory.getInstance().closeSession();
}
long endTime = System.currentTimeMillis();
System.out.println("testIncrementLaunchCounter time=" + (endTime - startTime) + " for " + loop + " incrementLaunchCounter calls");
sleep(2000);
}
sleep(20000);
RepositoryEntry repositoryEntry2 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong value of incrementLaunch counter",mainLoop * loop,repositoryEntry2.getLaunchCounter());
System.out.println("testIncrementLaunchCounter finished");
}
/**
*
*/
public void testIncrementDownloadCounter() {
Syncer syncer = CoordinatorManager.getCoordinator().getSyncer();
assertTrue("syncer is not of type 'ClusterSyncer'", syncer instanceof ClusterSyncer);
RepositoryEntry repositoryEntry = createRepository("T1_perf2", new Long(927888102));
final Long keyRepo = repositoryEntry.getKey();
final OLATResourceable resourceable = repositoryEntry.getOlatResource();
DBFactory.getInstance().closeSession();
assertEquals("Download counter was not 0", 0, repositoryEntry.getDownloadCounter() );
final int mainLoop = 10;
final int loop = 50; // 10 * 50 = 500
for (int m = 0; m < mainLoop; m++) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
// 1. load RepositoryEntry
RepositoryEntry repositoryEntryT1 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
RepositoryManager.getInstance().incrementDownloadCounter(repositoryEntryT1);
DBFactory.getInstance().closeSession();
}
long endTime = System.currentTimeMillis();
System.out.println("testIncrementDownloadCounter time=" + (endTime - startTime) + " for " + loop + " incrementDownloadCounter calls");
sleep(2000);
}
sleep(20000);
RepositoryEntry repositoryEntry2 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong value of incrementLaunch counter",mainLoop * loop,repositoryEntry2.getDownloadCounter());
System.out.println("testIncrementDownloadCounter finished");
}
/**
* Test synchronization between same RepositoryEntry and setLastUsageNowFor, incrementLaunchCounter and incrementDownloadCounter.
* This test starts 4 threads :
* 2 to call setLastUsageNowFor,
* 1 to call incrementLaunchCounter
* 1 to call incrementDownloadCounter
* Breakpoint is set for 'setLastUsageNowFor', all other calls must wait.
*/
public void testSetLastUsageNowFor() {
Date lastSetLastUsageDate = null;
Syncer syncer = CoordinatorManager.getCoordinator().getSyncer();
assertTrue("syncer is not of type 'ClusterSyncer'", syncer instanceof ClusterSyncer);
final int loop = 500;
RepositoryEntry repositoryEntry = createRepository("T1_perf2", new Long(927888103));
final Long keyRepo = repositoryEntry.getKey();
final OLATResourceable resourceable = repositoryEntry.getOlatResource();
DBFactory.getInstance().closeSession();
long startTime = System.currentTimeMillis();
for (int i = 0; i < loop; i++) {
// 1. load RepositoryEntry
RepositoryEntry repositoryEntryT1 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
RepositoryManager.getInstance().setLastUsageNowFor(repositoryEntryT1);
lastSetLastUsageDate = Calendar.getInstance().getTime();
DBFactory.getInstance().closeSession();
}
long endTime = System.currentTimeMillis();
sleep(20000);
RepositoryEntry repositoryEntry2 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertTrue("Wrong date-value of lastUsage, could not be before ",repositoryEntry2.getLastUsage().after(lastSetLastUsageDate) );
System.out.println("testSetLastUsageNowFor time=" + (endTime - startTime) + " for " + loop + " testSetLastUsageNowFor calls");
System.out.println("testSetLastUsageNowFor finished");
}
public void testConcurrentIncrementLaunchCounter() {
System.out.println("**************************");
System.out.println("START testConcurrentIncrementLaunchCounter");
System.out.println("**************************");
final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
final List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1));
Syncer syncer = CoordinatorManager.getCoordinator().getSyncer();
assertTrue("syncer is not of type 'ClusterSyncer'", syncer instanceof ClusterSyncer);
final int loop = 100;
final int numberOfThreads = 3;
RepositoryEntry repositoryEntry = createRepository("T1_perf2", new Long(927888104));
final Long keyRepo = repositoryEntry.getKey();
final OLATResourceable resourceable = repositoryEntry.getOlatResource();
DBFactory.getInstance().closeSession();
assertEquals("Launch counter was not 0", 0, repositoryEntry.getLaunchCounter() );
long startTime = System.currentTimeMillis();
// start thread 1 : incrementLaunchCounter / setAccess
new Thread(new Runnable() {
public void run() {
try {
for (int i = 1; i <= loop; i++) {
// 1. load RepositoryEntry
RepositoryEntry repositoryEntryT1 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
RepositoryManager.getInstance().incrementLaunchCounter(repositoryEntryT1);
if (i % 20 == 0 ) {
int ACCESS_VALUE = 4;
System.out.println("RepositoryManagerTest: call setAccess i=" + i);
RepositoryManager.getInstance().setAccess(repositoryEntryT1, ACCESS_VALUE);
DBFactory.getInstance().closeSession();
RepositoryEntry repositoryEntryT1Reloaded = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong access value",ACCESS_VALUE,repositoryEntryT1Reloaded.getAccess());
} else if (i % 10 == 0 ) {
int ACCESS_VALUE = 1;
System.out.println("RepositoryManagerTest: call setAccess i=" + i);
RepositoryManager.getInstance().setAccess(repositoryEntryT1, ACCESS_VALUE);
DBFactory.getInstance().closeSession();
RepositoryEntry repositoryEntryT1Reloaded = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong access value",ACCESS_VALUE,repositoryEntryT1Reloaded.getAccess());
}
DBFactory.getInstance().closeSession();
}
System.out.println("Thread-1: finished");
statusList.add(Boolean.TRUE);
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
try {
DBFactory.getInstance().closeSession();
} catch (Exception e) {
// ignore
}
}
}}).start();
// start thread 2 : incrementLaunchCounter / setDescriptionAndName
new Thread(new Runnable() {
public void run() {
try {
for (int i = 1; i <= loop; i++) {
// 1. load RepositoryEntry
RepositoryEntry repositoryEntryT1 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
RepositoryManager.getInstance().incrementLaunchCounter(repositoryEntryT1);
if (i % 25 == 0 ) {
String displayName = "DisplayName" + i;
String description = "Description" + i;
System.out.println("RepositoryManagerTest: call setDescriptionAndName");
RepositoryManager.getInstance().setDescriptionAndName(repositoryEntryT1, displayName,description);
DBFactory.getInstance().closeSession();
RepositoryEntry repositoryEntryT1Reloaded = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong displayName value",displayName,repositoryEntryT1Reloaded.getDisplayname());
assertEquals("Wrong description value",description,repositoryEntryT1Reloaded.getDescription());
}
DBFactory.getInstance().closeSession();
}
System.out.println("Thread-1: finished");
statusList.add(Boolean.TRUE);
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
try {
DBFactory.getInstance().closeSession();
} catch (Exception e) {
// ignore
}
}
}}).start();
// start thread 3
new Thread(new Runnable() {
public void run() {
try {
for (int i = 1; i <= loop; i++) {
// 1. load RepositoryEntry
RepositoryEntry repositoryEntryT1 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
RepositoryManager.getInstance().incrementLaunchCounter(repositoryEntryT1);
if (i % 30 == 0 ) {
System.out.println("RepositoryManagerTest: call setProperties i=" + i);
RepositoryManager.getInstance().setProperties(repositoryEntryT1, true, false, true, false);
DBFactory.getInstance().closeSession();
RepositoryEntry repositoryEntryT1Reloaded = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong canCopy value",true,repositoryEntryT1Reloaded.getCanCopy());
assertEquals("Wrong getCanReference value",false,repositoryEntryT1Reloaded.getCanReference());
assertEquals("Wrong getCanLaunch value",true,repositoryEntryT1Reloaded.getCanLaunch());
assertEquals("Wrong getCanDownload value",false,repositoryEntryT1Reloaded.getCanDownload());
} else if (i % 15 == 0 ) {
System.out.println("RepositoryManagerTest: call setProperties i=" + i);
RepositoryManager.getInstance().setProperties(repositoryEntryT1, false, true, false, true);
DBFactory.getInstance().closeSession();
RepositoryEntry repositoryEntryT1Reloaded = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong canCopy value",false,repositoryEntryT1Reloaded.getCanCopy());
assertEquals("Wrong getCanReference value",true,repositoryEntryT1Reloaded.getCanReference());
assertEquals("Wrong getCanLaunch value",false,repositoryEntryT1Reloaded.getCanLaunch() );
assertEquals("Wrong getCanDownload value",true,repositoryEntryT1Reloaded.getCanDownload());
}
DBFactory.getInstance().closeSession();
}
System.out.println("Thread-1: finished");
statusList.add(Boolean.TRUE);
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
try {
DBFactory.getInstance().closeSession();
} catch (Exception e) {
// ignore
}
}
}}).start();
long endTime = System.currentTimeMillis();
System.out.println("testConcurrentIncrementLaunchCounter sleeping 30sec");
sleep(30000);
System.out.println("testConcurrentIncrementLaunchCounter sleeping 30sec done");
RepositoryEntry repositoryEntry2 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Worng value of incrementLaunch counter",loop * numberOfThreads,repositoryEntry2.getLaunchCounter());
System.out.println("testConcurrentIncrementLaunchCounter time=" + (endTime - startTime) + " for " + loop + " incrementLaunchCounter calls");
System.out.println("testConcurrentIncrementLaunchCounter finished");
System.out.println("**************************");
}
/**
* Compare async increment-call with sync 'setDscription' call.
*/
public void testIncrementLaunchCounterSetDescription() {
System.out.println("testIncrementLaunchCounterSetDescription: START...");
RepositoryEntry repositoryEntry = createRepository("testIncrementLaunchCounterSetDescription", new Long(927888105));
DBFactory.getInstance().closeSession();
final Long keyRepo = repositoryEntry.getKey();
RepositoryEntry repositoryEntryT1 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
System.out.println("RepositoryManagerTest: call incrementLaunchCounter");
long t1 = System.nanoTime();
RepositoryManager.getInstance().incrementLaunchCounter(repositoryEntryT1);
long t2 = System.nanoTime();
System.out.println("RepositoryManagerTest: call incrementLaunchCounter DONE");
String displayName = "DisplayName_testIncrementLaunchCounterSetDescription";
String description = "Description_testIncrementLaunchCounterSetDescription";
System.out.println("RepositoryManagerTest: call setDescriptionAndName");
long t3 = System.nanoTime();
RepositoryManager.getInstance().setDescriptionAndName(repositoryEntryT1, displayName,description);
long t4 = System.nanoTime();
System.out.println("RepositoryManagerTest: call setDescriptionAndName DONE");
System.out.println("RepositoryManagerTest: increments take=" + (t2 - t1) + " setDescription take=" + (t4 -t3) );
DBFactory.getInstance().closeSession();
RepositoryEntry repositoryEntryT1Reloaded = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong displayName value",displayName,repositoryEntryT1Reloaded.getDisplayname());
assertEquals("Wrong description value",description,repositoryEntryT1Reloaded.getDescription());
System.out.println("testIncrementLaunchCounterSetDescription: FINISHED");
}
/**
* Modify a repository-entry from three thread to check if the exception does not pop up.
* Thread 1 : call incrementDownloadCounter after 100ms
* Thread 2 : call incrementDownloadCounter after 300ms
* Thread 3 : update access-value on repository-entry directly after 200ms
* Codepoint-breakpoint at IncrementDownloadCounterBackgroundTask in executeTask before update
*/
public void testConcurrentIncrementLaunchCounterWithCodePoints() {
final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
final List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1));
RepositoryEntry repositoryEntry = createRepository("IncCodePoint", new Long(927888106));
final Long keyRepo = repositoryEntry.getKey();
final OLATResourceable resourceable = repositoryEntry.getOlatResource();
final int access = 4;
DBFactory.getInstance().closeSession();
assertEquals("Launch counter was not 0", 0, repositoryEntry.getLaunchCounter() );
// enable breakpoint
CodepointClient codepointClient = null;
CodepointRef codepointRef = null;
try {
codepointClient = CodepointClientFactory.createCodepointClient("vm://localhost?broker.persistent=false", CODEPOINT_SERVER_ID);
codepointRef = codepointClient.getCodepoint("org.olat.repository.async.IncrementDownloadCounterBackgroundTask.executeTask-before-update");
codepointRef.enableBreakpoint();
} catch (Exception e) {
e.printStackTrace();
fail("Could not initialzed CodepointClient");
}
// thread 1
new Thread(new Runnable() {
public void run() {
try {
Thread.currentThread().sleep(100);
System.out.println("Thread 1 starts with lookup");
RepositoryEntry repositoryEntryT1 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
System.out.println("Thread 1 starts does inc downloadcounter");
RepositoryManager.getInstance().incrementDownloadCounter(repositoryEntryT1);
System.out.println("testConcurrentIncrementLaunchCounterWithCodePoints: Thread1 incremented download-counter");
} catch (Exception ex) {
ex.printStackTrace(System.out);
exceptionHolder.add(ex);// no exception should happen
} finally {
System.out.println("Thread 1 quits");
}
}}).start();
// thread 2
new Thread(new Runnable() {
public void run() {
try {
Thread.currentThread().sleep(300);
System.out.println("Thread 2 starts with lookup");
RepositoryEntry repositoryEntryT2 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
System.out.println("Thread 2 starts does inc downloadcounter");
RepositoryManager.getInstance().incrementDownloadCounter(repositoryEntryT2);
System.out.println("testConcurrentIncrementLaunchCounterWithCodePoints: Thread2 incremented download-counter");
} catch (Exception ex) {
ex.printStackTrace(System.out);
exceptionHolder.add(ex);// no exception should happen
} finally {
System.out.println("Thread 2 quits");
}
}}).start();
// thread 3
new Thread(new Runnable() {
public void run() {
try {
Thread.currentThread().sleep(200);
System.out.println("Thread 3 starts with lookup");
RepositoryEntry repositoryEntryT3 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
// change repository directly and not via RepositoryManager.setAccess(...) for testing
System.out.println("Thread 3 changes repository entry directly, setAccess...");
repositoryEntryT3.setAccess(access);
System.out.println("Thread 3 changes repository entry directly, updateRepositoryEntry");
RepositoryManager.getInstance().updateRepositoryEntry(repositoryEntryT3);
System.out.println("Thread 3 changes repository entry directly, commit");
DBFactory.getInstance().closeSession();
System.out.println("testConcurrentIncrementLaunchCounterWithCodePoints: Thread3 setAccess DONE");
} catch (Exception ex) {
ex.printStackTrace(System.out);
exceptionHolder.add(ex);// no exception should happen
} finally {
System.out.println("Thread 3 quits");
}
}}).start();
try {
System.out.println("testConcurrentIncrementLaunchCounterWithCodePoints: main thread sleep 500msec");
Thread.currentThread().sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
// to see all registered code-points: comment-in next 2 lines
// List<CodepointRef> codepointList = codepointClient.listAllCodepoints();
// System.out.println("codepointList=" + codepointList);
System.out.println("testConcurrentIncrementLaunchCounterWithCodePoints start waiting for breakpoint reached");
TemporaryPausedThread[] threads = codepointRef.waitForBreakpointReached(1000);
assertTrue("Did not reach breakpoint", threads.length > 0);
System.out.println("threads[0].getCodepointRef()=" + threads[0].getCodepointRef());
codepointRef.disableBreakpoint(true);
System.out.println("testConcurrentIncrementLaunchCounterWithCodePoints breakpoint reached => continue");
} catch (BreakpointStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail("Codepoints: BreakpointStateException=" + e.getMessage());
} catch (CommunicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail("Codepoints: CommunicationException=" + e.getMessage());
}
sleep(500);
RepositoryEntry repositoryEntry2 = RepositoryManager.getInstance().lookupRepositoryEntry(keyRepo);
assertEquals("Wrong value of incrementLaunch counter",2,repositoryEntry2.getDownloadCounter());
assertEquals("Wrong access value",access,repositoryEntry2.getAccess());
assertEquals("No exception should occur: "+exceptionHolder.size(), 0, exceptionHolder.size());
codepointClient.close();
System.out.println("testConcurrentIncrementLaunchCounterWithCodePoints finish successful");
}
private RepositoryEntry createRepository(String name, final Long resourceableId) {
OLATResourceManager rm = OLATResourceManager.getInstance();
// create course and persist as OLATResourceImpl
OLATResourceable resourceable = new OLATResourceable() {
public String getResourceableTypeName() { return CourseModule.ORES_TYPE_COURSE;}
public Long getResourceableId() {return resourceableId;}
};
OLATResource r = rm.createOLATResourceInstance(resourceable);
DBFactory.getInstance().saveObject(r);
// now make a repository entry for this course
RepositoryEntry d = new RepositoryEntry();
d.setOlatResource(r);
d.setResourcename(name);
d.setInitialAuthor("Christian Guretzki");
d.setDisplayname("JunitTest_RepositoryEntry");
DBFactory.getInstance().saveObject(d);
return d;
}
/**
*
* @param milis the duration in miliseconds to sleep
*/
private void sleep(int milis) {
try {
Thread.sleep(milis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static Test suite() throws Exception {
return new TestSuite(RepositoryManagerTest.class);
}
}