use of org.olat.core.util.coordinate.SyncerExecutor in project OpenOLAT by OpenOLAT.
the class CoordinatorTest method testDoInSyncWithSyncerExecutor.
/**
* Test with 2 threads T1 & T2.
* T1 T2
* doInSync T1-1 sleep 5sec
* sleep 10sec ...
* ... ...
* ... doInSync T2-1
* ... sleep 10sec
* ... ...
* doInSync T1-2 ...
* finished ...
* doInSync T2-2
* finished
*/
@Test
public void testDoInSyncWithSyncerExecutor() {
final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
final List<Boolean> statusList = Collections.synchronizedList(new ArrayList<Boolean>(1));
final CountDownLatch finishCount = new CountDownLatch(2);
final OLATResourceable ores = OresHelper.createOLATResourceableInstance("testDoInSync", new Long("123"));
// thread 1
new Thread(new Runnable() {
public void run() {
try {
// do something in sync
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor() {
public void execute() {
log.info("Thread-1: execute doInSync 1");
}
});
// end syncerCallback
// sleep
sleep(1000);
// do again do something in sync
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor() {
public void execute() {
log.info("Thread-1: execute doInSync 2");
}
});
// end syncerCallback
log.info("Thread-1: finished");
statusList.add(Boolean.TRUE);
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
try {
DBFactory.getInstance().closeSession();
} catch (Exception e) {
// ignore
}
finishCount.countDown();
}
}
}).start();
// thread 2
new Thread(new Runnable() {
public void run() {
try {
// sleep
sleep(500);
// do something in sync
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor() {
public void execute() {
log.info("Thread-2: execute doInSync 1");
}
});
// end syncerCallback
// sleep
sleep(1000);
// do again do something in sync
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(ores, new SyncerExecutor() {
public void execute() {
log.info("Thread-2: execute doInSync 2");
}
});
// end syncerCallback
log.info("Thread-2: finished");
statusList.add(Boolean.TRUE);
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
try {
DBFactory.getInstance().closeSession();
} catch (Exception e) {
// ignore
}
finishCount.countDown();
}
}
}).start();
// sleep until t1 and t2 should have terminated/excepted
try {
finishCount.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Assert.fail("Threads did not finish in 10sec");
}
// if not -> they are in deadlock and the db did not detect it
for (Exception exception : exceptionHolder) {
log.error("exception: ", exception);
}
Assert.assertEquals("It throws an exception in test", 0, exceptionHolder.size());
}
use of org.olat.core.util.coordinate.SyncerExecutor in project OpenOLAT by OpenOLAT.
the class ProfileFormController method formOK.
@Override
protected void formOK(final UserRequest ureq) {
User user = identityToModify.getUser();
// update each user field
for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
FormItem formItem = formItems.get(userPropertyHandler.getName());
if (formItem.isEnabled()) {
userPropertyHandler.updateUserFromFormItem(user, formItem);
}
}
if (portraitDeleted) {
File img = dps.getLargestPortrait(identityToModify.getName());
if (img != null) {
dps.deletePortrait(identityToModify);
notifyPortraitChanged();
}
}
File uploadedImage = portraitUpload.getUploadFile();
String uploadedFilename = portraitUpload.getUploadFileName();
if (uploadedImage != null) {
dps.setPortrait(uploadedImage, uploadedFilename, identityToModify.getName());
notifyPortraitChanged();
}
if (logoDeleted) {
File img = dps.getLargestLogo(identityToModify.getName());
if (img != null) {
dps.deleteLogo(identityToModify);
notifyPortraitChanged();
}
}
if (logoUpload != null) {
File uploadedLogo = logoUpload.getUploadFile();
String uploadedLogoname = logoUpload.getUploadFileName();
if (uploadedLogo != null) {
dps.setLogo(uploadedLogo, uploadedLogoname, identityToModify.getName());
notifyPortraitChanged();
}
}
// Store the "about me" text.
HomePageConfig conf = hpcm.loadConfigFor(identityToModify.getName());
conf.setTextAboutMe(textAboutMe.getValue());
hpcm.saveConfigTo(identityToModify.getName(), conf);
// fire the appropriate event
fireEvent(ureq, Event.DONE_EVENT);
// update the user profile data
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(OresHelper.createOLATResourceableInstance(Identity.class, identityToModify.getKey()), new SyncerExecutor() {
@Override
public void execute() {
UserManager um = UserManager.getInstance();
identityToModify = (Identity) DBFactory.getInstance().loadObject(identityToModify);
currentEmail = identityToModify.getUser().getProperty("email", null);
identityToModify = updateIdentityFromFormData(identityToModify);
changedEmail = identityToModify.getUser().getProperty("email", null);
emailChanged = false;
if ((currentEmail == null && StringHelper.containsNonWhitespace(changedEmail)) || (currentEmail != null && !currentEmail.equals(changedEmail))) {
if (isAllowedToChangeEmailWithoutVerification(ureq) || !StringHelper.containsNonWhitespace(changedEmail)) {
String key = identityToModify.getUser().getProperty("emchangeKey", null);
TemporaryKey tempKey = rm.loadTemporaryKeyByRegistrationKey(key);
if (tempKey != null) {
rm.deleteTemporaryKey(tempKey);
}
securityManager.deleteInvalidAuthenticationsByEmail(currentEmail);
} else {
emailChanged = true;
// change email address to old address until it is verified
identityToModify.getUser().setProperty("email", currentEmail);
}
}
if (!um.updateUserFromIdentity(identityToModify)) {
getWindowControl().setInfo(translate("profile.unsuccessful"));
// reload user data from db
identityToModify = BaseSecurityManager.getInstance().loadIdentityByKey(identityToModify.getKey());
}
OLATResourceable modRes = OresHelper.createOLATResourceableInstance(Identity.class, identityToModify.getKey());
CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new MultiUserEvent("changed"), modRes);
if (!emailChanged) {
fireEvent(ureq, Event.FAILED_EVENT);
}
}
});
if (emailChanged) {
removeAsListenerAndDispose(dialogCtr);
String dialogText = "";
if (identityToModify.equals(ureq.getIdentity())) {
dialogText = translate("email.change.dialog.text");
} else {
dialogText = translate("email.change.dialog.text.usermanager");
}
dialogCtr = DialogBoxUIFactory.createYesNoDialog(ureq, getWindowControl(), translate("email.change.dialog.title"), dialogText);
listenTo(dialogCtr);
dialogCtr.activate();
}
}
use of org.olat.core.util.coordinate.SyncerExecutor in project OpenOLAT by OpenOLAT.
the class NewCachePersistingAssessmentManager method saveNodeCoachComment.
/**
* @see org.olat.course.assessment.AssessmentManager#saveNodeCoachComment(org.olat.course.nodes.CourseNode,
* org.olat.core.id.Identity, java.lang.String)
*/
public void saveNodeCoachComment(final CourseNode courseNode, final Identity assessedIdentity, final String comment) {
ICourse course = CourseFactory.loadCourse(ores);
final CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager();
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(createOLATResourceableForLocking(assessedIdentity), new SyncerExecutor() {
public void execute() {
Property commentProperty = cpm.findCourseNodeProperty(courseNode, assessedIdentity, null, COACH_COMMENT);
if (commentProperty == null) {
commentProperty = cpm.createCourseNodePropertyInstance(courseNode, assessedIdentity, null, COACH_COMMENT, null, null, null, comment);
cpm.saveProperty(commentProperty);
} else {
commentProperty.setTextValue(comment);
cpm.updateProperty(commentProperty);
}
// add to cache
putPropertyIntoCache(assessedIdentity, commentProperty);
}
});
// olat::: no node log here? (because what we did above is a node log with custom text AND by a coach)?
// notify about changes
AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_COACH_COMMENT_CHANGED, assessedIdentity);
CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, course);
// user activity logging
ThreadLocalUserActivityLogger.log(AssessmentLoggingAction.ASSESSMENT_COACHCOMMENT_UPDATED, getClass(), LoggingResourceable.wrap(assessedIdentity), LoggingResourceable.wrapNonOlatResource(StringResourceableType.qtiCoachComment, "", StringHelper.stripLineBreaks(comment)));
}
use of org.olat.core.util.coordinate.SyncerExecutor in project OpenOLAT by OpenOLAT.
the class NewCachePersistingAssessmentManager method saveNodeAttempts.
/**
* @see org.olat.course.assessment.AssessmentManager#saveNodeAttempts(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity, org.olat.core.id.Identity,
* java.lang.Integer)
*/
public void saveNodeAttempts(final CourseNode courseNode, final Identity identity, final Identity assessedIdentity, final Integer attempts) {
// A note on updating the EfficiencyStatement:
// In the equivalent method incrementNodeAttempts() in this class, the following code is executed:
// // Update users efficiency statement
// EfficiencyStatementManager esm = EfficiencyStatementManager.getInstance();
// esm.updateUserEfficiencyStatement(userCourseEnv);
// One would expect that saveNodeAttempts would also have to update the EfficiencyStatement - or
// the caller of this method would have to make sure that this happens in the same transaction.
// While this is not explicitly so, implicitly it is: currently the only user this method is
// the AssessmentEditController - which as the 2nd last method calls into saveScoreEvaluation
// - which in turn does update the EfficiencyStatement - at which point we're happy and everything works fine.
// But it seems like this mechanism is a bit unobvious and might well be worth some refactoring...
ICourse course = CourseFactory.loadCourse(ores);
final CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager();
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(createOLATResourceableForLocking(assessedIdentity), new SyncerExecutor() {
public void execute() {
Property attemptsProperty = cpm.findCourseNodeProperty(courseNode, assessedIdentity, null, ATTEMPTS);
if (attemptsProperty == null) {
attemptsProperty = cpm.createCourseNodePropertyInstance(courseNode, assessedIdentity, null, ATTEMPTS, null, new Long(attempts.intValue()), null, null);
cpm.saveProperty(attemptsProperty);
} else {
attemptsProperty.setLongValue(new Long(attempts.intValue()));
cpm.updateProperty(attemptsProperty);
}
// add to cache
putPropertyIntoCache(assessedIdentity, attemptsProperty);
}
});
// node log
UserNodeAuditManager am = course.getCourseEnvironment().getAuditManager();
am.appendToUserNodeLog(courseNode, identity, assessedIdentity, ATTEMPTS + " set to: " + String.valueOf(attempts));
// notify about changes
AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_ATTEMPTS_CHANGED, assessedIdentity);
CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, course);
// user activity logging
ThreadLocalUserActivityLogger.log(AssessmentLoggingAction.ASSESSMENT_ATTEMPTS_UPDATED, getClass(), LoggingResourceable.wrap(assessedIdentity), LoggingResourceable.wrapNonOlatResource(StringResourceableType.qtiAttempts, "", String.valueOf(attempts)));
}
use of org.olat.core.util.coordinate.SyncerExecutor in project OpenOLAT by OpenOLAT.
the class NewCachePersistingAssessmentManager method saveNodeComment.
/**
* @see org.olat.course.assessment.AssessmentManager#saveNodeComment(org.olat.course.nodes.CourseNode,
* org.olat.core.id.Identity, org.olat.core.id.Identity,
* java.lang.String)
*/
public void saveNodeComment(final CourseNode courseNode, final Identity identity, final Identity assessedIdentity, final String comment) {
ICourse course = CourseFactory.loadCourse(ores);
final CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager();
CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(createOLATResourceableForLocking(assessedIdentity), new SyncerExecutor() {
public void execute() {
Property commentProperty = cpm.findCourseNodeProperty(courseNode, assessedIdentity, null, COMMENT);
if (commentProperty == null) {
commentProperty = cpm.createCourseNodePropertyInstance(courseNode, assessedIdentity, null, COMMENT, null, null, null, comment);
cpm.saveProperty(commentProperty);
} else {
commentProperty.setTextValue(comment);
cpm.updateProperty(commentProperty);
}
// add to cache
putPropertyIntoCache(assessedIdentity, commentProperty);
}
});
// node log
UserNodeAuditManager am = course.getCourseEnvironment().getAuditManager();
am.appendToUserNodeLog(courseNode, identity, assessedIdentity, COMMENT + " set to: " + comment);
// notify about changes
AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_USER_COMMENT_CHANGED, assessedIdentity);
CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, course);
// user activity logging
ThreadLocalUserActivityLogger.log(AssessmentLoggingAction.ASSESSMENT_USERCOMMENT_UPDATED, getClass(), LoggingResourceable.wrap(assessedIdentity), LoggingResourceable.wrapNonOlatResource(StringResourceableType.qtiUserComment, "", StringHelper.stripLineBreaks(comment)));
}
Aggregations