/*
* Copyright 2010-2012 henryzhao81-at-gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.orientechnologies.orient.core.schedule;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.exception.ODatabaseException;
import com.orientechnologies.orient.core.exception.OValidationException;
import com.orientechnologies.orient.core.hook.ODocumentHookAbstract;
import com.orientechnologies.orient.core.hook.ORecordHook;
import com.orientechnologies.orient.core.metadata.schema.OImmutableClass;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.record.impl.ODocumentInternal;
import com.orientechnologies.orient.core.schedule.OScheduler.STATUS;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Keeps synchronized the scheduled events in memory.
*
* @author Luca Garulli
* @author henryzhao81-at-gmail.com
* @since Mar 28, 2013
*/
public class OSchedulerTrigger extends ODocumentHookAbstract implements ORecordHook.Scoped {
private static final SCOPE[] SCOPES = { SCOPE.CREATE, SCOPE.UPDATE, SCOPE.DELETE };
public OSchedulerTrigger(ODatabaseDocument database) {
super(database);
}
@Override
public SCOPE[] getScopes() {
return SCOPES;
}
public DISTRIBUTED_EXECUTION_MODE getDistributedExecutionMode() {
return DISTRIBUTED_EXECUTION_MODE.BOTH;
}
@Override
public RESULT onTrigger(TYPE iType, ORecord iRecord) {
OImmutableClass clazz = null;
if (iRecord instanceof ODocument)
clazz = ODocumentInternal.getImmutableSchemaClass((ODocument) iRecord);
if (clazz == null || !clazz.isScheduler())
return RESULT.RECORD_NOT_CHANGED;
return super.onTrigger(iType, iRecord);
}
@Override
public RESULT onRecordBeforeCreate(final ODocument iDocument) {
String name = iDocument.field(OScheduledEvent.PROP_NAME);
final OScheduledEvent event = database.getMetadata().getScheduler().getEvent(name);
if (event != null && event.getDocument() != iDocument) {
throw new ODatabaseException("Scheduled event with name '" + name + "' already exists in database");
}
iDocument.field(OScheduledEvent.PROP_STATUS, STATUS.STOPPED.name());
return RESULT.RECORD_CHANGED;
}
@Override
public void onRecordAfterCreate(final ODocument iDocument) {
database.getMetadata().getScheduler().scheduleEvent(new OScheduledEvent(iDocument));
}
@Override
public RESULT onRecordBeforeUpdate(final ODocument iDocument) {
try {
final String schedulerName = iDocument.field(OScheduledEvent.PROP_NAME);
OScheduledEvent event = database.getMetadata().getScheduler().getEvent(schedulerName);
if (event != null) {
// UPDATED EVENT
final Set<String> dirtyFields = new HashSet<String>(Arrays.asList(iDocument.getDirtyFields()));
if (dirtyFields.contains(OScheduledEvent.PROP_NAME))
throw new OValidationException("Scheduled event cannot change name");
if (dirtyFields.contains(OScheduledEvent.PROP_RULE)) {
// RULE CHANGED, STOP CURRENT EVENT AND RESCHEDULE IT
database.getMetadata().getScheduler().updateEvent(new OScheduledEvent(iDocument));
} else {
iDocument.field(OScheduledEvent.PROP_STATUS, STATUS.STOPPED.name());
event.fromStream(iDocument);
}
return RESULT.RECORD_CHANGED;
}
} catch (Exception ex) {
OLogManager.instance().error(this, "Error on updating scheduled event", ex);
}
return RESULT.RECORD_NOT_CHANGED;
}
@Override
public void onRecordAfterDelete(final ODocument iDocument) {
final String eventName = iDocument.field(OScheduledEvent.PROP_NAME);
database.getMetadata().getScheduler().removeEvent(eventName);
}
}