/*
* Copyright (c) 2010-2012 Grid Dynamics Consulting Services, Inc, All Rights Reserved
* http://www.griddynamics.com
*
* This library is free software; you can redistribute it and/or modify it under the terms of
* the Apache License; either
* version 2.0 of the License, or any later version.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.griddynamics.jagger.engine.e1.aggregator.session;
import static com.griddynamics.jagger.engine.e1.collector.CollectorConstants.END_TIME;
import static com.griddynamics.jagger.engine.e1.collector.CollectorConstants.ERROR_MESSAGE;
import static com.griddynamics.jagger.engine.e1.collector.CollectorConstants.FAILED;
import static com.griddynamics.jagger.engine.e1.collector.CollectorConstants.KERNELS_COUNT;
import static com.griddynamics.jagger.engine.e1.collector.CollectorConstants.SESSION;
import static com.griddynamics.jagger.engine.e1.collector.CollectorConstants.START_TIME;
import static com.griddynamics.jagger.engine.e1.collector.CollectorConstants.TASK_EXECUTED;
import com.griddynamics.jagger.coordinator.NodeId;
import com.griddynamics.jagger.coordinator.NodeType;
import com.griddynamics.jagger.dbapi.entity.SessionData;
import com.griddynamics.jagger.dbapi.entity.TagEntity;
import com.griddynamics.jagger.dbapi.entity.TaskData;
import com.griddynamics.jagger.engine.e1.services.SessionMetaDataStorage;
import com.griddynamics.jagger.master.DistributionListener;
import com.griddynamics.jagger.master.TaskExecutionStatusProvider;
import com.griddynamics.jagger.master.configuration.SessionExecutionStatus;
import com.griddynamics.jagger.master.configuration.SessionListener;
import com.griddynamics.jagger.master.configuration.Task;
import com.griddynamics.jagger.monitoring.MonitoringTask;
import com.griddynamics.jagger.storage.KeyValueStorage;
import com.griddynamics.jagger.storage.Namespace;
import org.hibernate.HibernateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* Aggregates generic session/task data from key-value storage and stores to
* relation structure. See {@link com.griddynamics.jagger.dbapi.entity.SessionData},
* {@link com.griddynamics.jagger.dbapi.entity.TaskData} for table structure.
*
* @author Mairbek Khadikov
*/
public class BasicAggregator extends HibernateDaoSupport implements DistributionListener, SessionListener {
private static final Logger log = LoggerFactory.getLogger(BasicAggregator.class);
private KeyValueStorage keyValueStorage;
private SessionMetaDataStorage sessionMetaDataStorage;
TaskExecutionStatusProvider taskExecutionStatusProvider;
public void setTaskExecutionStatusProvider(TaskExecutionStatusProvider taskExecutionStatusProvider) {
this.taskExecutionStatusProvider = taskExecutionStatusProvider;
}
@Override
public void onSessionStarted(String sessionId, Multimap<NodeType, NodeId> nodes) {
log.debug("onSessionStarted invoked");
}
@Override
public void onSessionExecuted(String sessionId, String sessionComment) {
onSessionExecuted(sessionId, sessionComment, SessionExecutionStatus.EMPTY);
}
@Override
public void onSessionExecuted(String sessionId, String sessionComment, SessionExecutionStatus status) {
log.debug("onSessionExecuted invoked");
Namespace namespace = Namespace.of(SESSION, sessionId);
Multimap<String, Object> all = keyValueStorage.fetchAll(namespace);
SessionData sessionData = new SessionData();
sessionData.setSessionId(sessionId);
sessionData.setComment(sessionComment);
Long startTime = (Long) getFirst(all, START_TIME);
sessionData.setStartTime(new Date(startTime));
Long endTime = (Long) getFirst(all, END_TIME);
sessionData.setEndTime(new Date(endTime));
Integer taskExecuted = (Integer) getFirst(all, TASK_EXECUTED);
sessionData.setTaskExecuted(taskExecuted);
Integer tasksFailed = (Integer) getFirst(all, FAILED);
sessionData.setTaskFailed(tasksFailed);
Integer activeKernels = (Integer) getFirst(all, KERNELS_COUNT);
sessionData.setActiveKernels(activeKernels);
String errorMessage = (String) getFirst(all, ERROR_MESSAGE);
sessionData.setErrorMessage(errorMessage);
getHibernateTemplate().persist(sessionData);
persistTags(sessionId, sessionMetaDataStorage);
}
public void setKeyValueStorage(KeyValueStorage keyValueStorage) {
this.keyValueStorage = keyValueStorage;
}
public void setSessionMetaDataStorage(SessionMetaDataStorage sessionMetaDataStorage) {
this.sessionMetaDataStorage = sessionMetaDataStorage;
}
private static Object getFirst(Multimap<String, Object> all, String key) {
Iterator<Object> iterator = all.get(key).iterator();
if (!iterator.hasNext()) {
throw new IllegalStateException("key " + key + " has not been saved during test execution");
}
return iterator.next();
}
@Override
public void onDistributionStarted(String sessionId, String taskId, Task task, Collection<NodeId> capableNodes) {
log.debug("onTaskStarted invoked");
}
@Override
public void onTaskDistributionCompleted(String sessionId, String taskId, Task task) {
if (task instanceof MonitoringTask){
return;
}
log.debug("onTaskFinished invoked {} {}", sessionId, taskId);
persistData(sessionId, taskId, task);
}
private void persistData(String sessionId, String taskId, Task task) {
TaskData taskData = new TaskData();
taskData.setTaskId(taskId);
taskData.setSessionId(sessionId);
taskData.setTaskName(task.getTaskName());
taskData.setNumber(task.getNumber());
taskData.setStatus(taskExecutionStatusProvider.getStatus(taskId));
getHibernateTemplate().persist(taskData);
}
public void persistTags(String sessionId, SessionMetaDataStorage metaDataStorage) {
HibernateTemplate hibernateTemplate = getHibernateTemplate();
for (TagEntity tagEntity : metaDataStorage.getTagsForSaveOrUpdate()) {
try {
hibernateTemplate.saveOrUpdate(tagEntity);
} catch (HibernateException e) {
log.error("Cannot add new tag", e);
}
}
if (!metaDataStorage.getSessionTags().isEmpty()) {
Set<TagEntity> sessionTagList = new HashSet<TagEntity>();
sessionTagList.addAll((Collection<? extends TagEntity>) hibernateTemplate.findByNamedParam("select tags from TagEntity as tags " +
"where tags.name in (:sTagsName)", "sTagsName", metaDataStorage.getSessionTags()));
if (!sessionTagList.isEmpty()) {
List<SessionData> sessionsById = (List<SessionData>) hibernateTemplate.find("from SessionData s where s.sessionId=?", sessionId);
if (sessionsById.size()==1)
for (SessionData sessionData : sessionsById) {
sessionData.setTags(sessionTagList);
hibernateTemplate.saveOrUpdate(sessionData);
}
else
log.error("Must be one session's id which is equals {}, but got {} ids",sessionId,sessionsById.size());
} else
log.info("No tags for mark session {}", sessionId);
}
}
}