package rocks.inspectit.server.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import rocks.inspectit.server.dao.StorageDataDao;
import rocks.inspectit.server.spring.aop.MethodLog;
import rocks.inspectit.server.storage.CmrStorageManager;
import rocks.inspectit.shared.all.communication.DefaultData;
import rocks.inspectit.shared.all.exception.BusinessException;
import rocks.inspectit.shared.all.exception.TechnicalException;
import rocks.inspectit.shared.all.exception.enumeration.StorageErrorCodeEnum;
import rocks.inspectit.shared.all.serializer.SerializationException;
import rocks.inspectit.shared.all.spring.logger.Log;
import rocks.inspectit.shared.cs.cmr.service.IStorageService;
import rocks.inspectit.shared.cs.communication.data.cmr.RecordingData;
import rocks.inspectit.shared.cs.storage.IStorageData;
import rocks.inspectit.shared.cs.storage.StorageData;
import rocks.inspectit.shared.cs.storage.StorageFileType;
import rocks.inspectit.shared.cs.storage.label.AbstractStorageLabel;
import rocks.inspectit.shared.cs.storage.label.management.AbstractLabelManagementAction;
import rocks.inspectit.shared.cs.storage.label.type.AbstractStorageLabelType;
import rocks.inspectit.shared.cs.storage.processor.AbstractDataProcessor;
import rocks.inspectit.shared.cs.storage.recording.RecordingProperties;
import rocks.inspectit.shared.cs.storage.recording.RecordingState;
/**
* Storage service implementation.
*
* @author Ivan Senic
*
*/
@Service
@Transactional
public class StorageService implements IStorageService {
/** The logger of this class. */
@Log
Logger log;
/**
* Storage manager.
*/
@Autowired
private CmrStorageManager storageManager;
/**
* Label data DAO.
*/
@Autowired
private StorageDataDao storageLabelDataDao;
/**
* Creates the new storage on the CMR with information given in {@link StorageData} object.
*
* @param storageData
* Information about new storage.
* @throws BusinessException
* When storage creation fails.
*/
@MethodLog
public void createStorage(StorageData storageData) throws BusinessException {
try {
storageManager.createStorage(storageData);
} catch (SerializationException e) {
throw new TechnicalException("Create the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Create the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* Opens an already existing storage in means that it prepares it for write.
*
* @param storageData
* Storage to open.
* @throws BusinessException
* When storage with provided {@link StorageData} does not exists. When storage
* opening fails.
*/
@MethodLog
public void openStorage(StorageData storageData) throws BusinessException {
if (!storageManager.isStorageExisting(storageData)) {
throw new BusinessException("Open the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_DOES_NOT_EXIST);
}
try {
storageManager.openStorage(storageData);
} catch (SerializationException e) {
throw new TechnicalException("Open the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Open the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public StorageData createAndOpenStorage(StorageData storageData) throws BusinessException {
this.createStorage(storageData);
this.openStorage(storageData);
return storageData;
}
/**
* {@inheritDoc}
*
* @throws BusinessException
*/
@Override
@MethodLog
public void closeStorage(StorageData storageData) throws BusinessException {
try {
storageManager.closeStorage(storageData);
} catch (SerializationException e) {
throw new TechnicalException("Close the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Close the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public void deleteStorage(StorageData storageData) throws BusinessException {
try {
storageManager.deleteStorage(storageData);
} catch (IOException e) {
throw new TechnicalException("Delete the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public boolean isStorageOpen(StorageData storageData) {
return storageManager.isStorageOpen(storageData);
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public List<StorageData> getOpenedStorages() {
return storageManager.getOpenedStorages();
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public List<StorageData> getExistingStorages() {
return storageManager.getExistingStorages();
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public List<StorageData> getReadableStorages() {
return storageManager.getReadableStorages();
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public RecordingState getRecordingState() {
return storageManager.getRecordingState();
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public StorageData startOrScheduleRecording(StorageData storageData, RecordingProperties recordingProperties) throws BusinessException {
if (((storageManager.getRecordingState() == RecordingState.ON) || (storageManager.getRecordingState() == RecordingState.SCHEDULED))
&& !storageData.equals(storageManager.getRecordingStorage())) {
throw new BusinessException("Start or schedule recording on the storage " + storageData + ".", StorageErrorCodeEnum.CAN_NOT_START_RECORDING);
} else if ((storageManager.getRecordingState() == RecordingState.ON) || (storageManager.getRecordingState() == RecordingState.SCHEDULED)) {
throw new BusinessException("Start or schedule recording on the storage " + storageData + ".", StorageErrorCodeEnum.CAN_NOT_START_RECORDING);
} else {
try {
storageManager.startOrScheduleRecording(storageData, recordingProperties);
return storageManager.getRecordingStorage();
} catch (SerializationException e) {
throw new TechnicalException("Start or schedule recording on the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Start or schedule recording on the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public void stopRecording() throws BusinessException {
try {
storageManager.stopRecording();
} catch (SerializationException e) {
throw new TechnicalException("Stop recording.", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Stop recording.", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@MethodLog
@Override
public RecordingData getRecordingData() {
if ((storageManager.getRecordingState() == RecordingState.ON) || (storageManager.getRecordingState() == RecordingState.SCHEDULED)) {
RecordingData recordingData = new RecordingData();
RecordingProperties recordingProperties = storageManager.getRecordingProperties();
if (null != recordingProperties) {
recordingData.setRecordStartDate(recordingProperties.getRecordStartDate());
recordingData.setRecordEndDate(recordingProperties.getRecordEndDate());
}
recordingData.setRecordingStorage(storageManager.getRecordingStorage());
recordingData.setRecordingWritingStatus(storageManager.getRecordingStatus());
return recordingData;
} else {
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public void writeToStorage(StorageData storageData, Collection<DefaultData> defaultDataCollection, Collection<AbstractDataProcessor> dataProcessors, boolean synchronously)
throws BusinessException {
if (!storageManager.isStorageOpen(storageData)) {
throw new BusinessException("Write to the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_IS_NOT_OPENED);
}
try {
storageManager.writeToStorage(storageData, defaultDataCollection, dataProcessors, synchronously);
} catch (SerializationException e) {
throw new TechnicalException("Write to the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Write to the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public StorageData copyBufferToStorage(StorageData storageData, List<Long> platformIdents, Collection<AbstractDataProcessor> dataProcessors, boolean autoFinalize) throws BusinessException {
try {
storageManager.copyBufferToStorage(storageData, platformIdents, dataProcessors, autoFinalize);
return storageData;
} catch (SerializationException e) {
throw new TechnicalException("Copy buffer to the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Copy buffer to the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
@Override
public StorageData copyDataToStorage(StorageData storageData, Collection<Long> elementIds, long platformIdent, Collection<AbstractDataProcessor> dataProcessors, boolean autoFinalize)
throws BusinessException {
try {
storageManager.copyDataToStorage(storageData, elementIds, platformIdent, dataProcessors, autoFinalize);
return storageData;
} catch (SerializationException e) {
throw new TechnicalException("Write to the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Write to the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public Map<String, Long> getIndexFilesLocations(StorageData storageData) throws BusinessException {
if (!storageManager.isStorageExisting(storageData)) {
throw new BusinessException("Load index files locations for the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_DOES_NOT_EXIST);
}
try {
return storageManager.getFilesHttpLocation(storageData, StorageFileType.INDEX_FILE.getExtension());
} catch (IOException e) {
throw new TechnicalException("Load index files locations for the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public Map<String, Long> getDataFilesLocations(StorageData storageData) throws BusinessException {
if (!storageManager.isStorageExisting(storageData)) {
throw new BusinessException("Load data files locations for the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_DOES_NOT_EXIST);
}
try {
return storageManager.getFilesHttpLocation(storageData, StorageFileType.DATA_FILE.getExtension());
} catch (IOException e) {
throw new TechnicalException("Load data files locations for the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public Map<String, Long> getCachedDataFilesLocations(StorageData storageData) throws BusinessException {
if (!storageManager.isStorageExisting(storageData)) {
throw new BusinessException("Load cached files locations for the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_DOES_NOT_EXIST);
}
try {
return storageManager.getFilesHttpLocation(storageData, StorageFileType.CACHED_DATA_FILE.getExtension());
} catch (IOException e) {
throw new TechnicalException("Load cache files locations for the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public Map<String, Long> getAgentFilesLocations(StorageData storageData) throws BusinessException {
if (!storageManager.isStorageExisting(storageData)) {
throw new BusinessException("Load agent files locations for the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_DOES_NOT_EXIST);
}
try {
return storageManager.getFilesHttpLocation(storageData, StorageFileType.AGENT_FILE.getExtension());
} catch (IOException e) {
throw new TechnicalException("Load agent files locations for the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public Map<String, Long> getBusinessContextFilesLocation(StorageData storageData) throws BusinessException {
if (!storageManager.isStorageExisting(storageData)) {
throw new BusinessException("Load business context files locations for the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_DOES_NOT_EXIST);
}
try {
return storageManager.getFilesHttpLocation(storageData, StorageFileType.BUSINESS_CONTEXT_FILE.getExtension());
} catch (IOException e) {
throw new TechnicalException("Load business context files locations for the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@MethodLog
public StorageData addLabelToStorage(StorageData storageData, AbstractStorageLabel<?> storageLabel, boolean doOverwrite) throws BusinessException {
try {
storageManager.addLabelToStorage(storageData, storageLabel, doOverwrite);
storageLabelDataDao.saveLabel(storageLabel);
return storageManager.getStorageData(storageData.getId());
} catch (SerializationException e) {
throw new TechnicalException("Add a label to the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Add a label to the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public StorageData addLabelsToStorage(StorageData storageData, Collection<AbstractStorageLabel<?>> storageLabels, boolean doOverwrite) throws BusinessException {
try {
for (AbstractStorageLabel<?> storageLabel : storageLabels) {
storageManager.addLabelToStorage(storageData, storageLabel, doOverwrite);
storageLabelDataDao.saveLabel(storageLabel);
}
return storageManager.getStorageData(storageData.getId());
} catch (SerializationException e) {
throw new TechnicalException("Add labels to the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Add labels to the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public StorageData removeLabelFromStorage(StorageData storageData, AbstractStorageLabel<?> storageLabel) throws BusinessException {
try {
storageManager.removeLabelFromStorage(storageData, storageLabel);
return storageManager.getStorageData(storageData.getId());
} catch (SerializationException e) {
throw new TechnicalException("Remove a label from the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Remove a label from the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public StorageData removeLabelsFromStorage(StorageData storageData, List<AbstractStorageLabel<?>> storageLabelList) throws BusinessException {
try {
for (AbstractStorageLabel<?> label : storageLabelList) {
storageManager.removeLabelFromStorage(storageData, label);
}
return storageManager.getStorageData(storageData.getId());
} catch (SerializationException e) {
throw new TechnicalException("Remove labels from the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Remove labels from the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public void executeLabelManagementActions(Collection<AbstractLabelManagementAction> managementActions) throws BusinessException {
for (AbstractLabelManagementAction managementAction : managementActions) {
managementAction.execute(this);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public Collection<AbstractStorageLabel<?>> getAllLabelsInStorages() {
Set<AbstractStorageLabel<?>> labels = new HashSet<>();
for (StorageData storageData : getExistingStorages()) {
labels.addAll(storageData.getLabelList());
}
return labels;
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public List<AbstractStorageLabel<?>> getAllLabels() {
return storageLabelDataDao.getAllLabels();
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public <E> List<AbstractStorageLabel<E>> getLabelSuggestions(AbstractStorageLabelType<E> labeltype) {
List<AbstractStorageLabel<E>> results = storageLabelDataDao.getAllLabelsForType(labeltype);
return results;
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public void saveLabelToCmr(AbstractStorageLabel<?> storageLabel) {
storageLabelDataDao.saveLabel(storageLabel);
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public void saveLabelsToCmr(Collection<AbstractStorageLabel<?>> storageLabels) {
for (AbstractStorageLabel<?> label : storageLabels) {
storageLabelDataDao.saveLabel(label);
}
}
/**
* {@inheritDoc}
*
*/
@Override
@Transactional
@MethodLog
public void removeLabelFromCmr(AbstractStorageLabel<?> storageLabel, boolean removeFromStoragesAlso) throws BusinessException {
storageLabelDataDao.removeLabel(storageLabel);
if (removeFromStoragesAlso) {
for (StorageData storageData : getExistingStorages()) {
removeLabelFromStorage(storageData, storageLabel);
}
}
}
/**
* {@inheritDoc}
*
*/
@Override
@Transactional
@MethodLog
public void removeLabelsFromCmr(Collection<AbstractStorageLabel<?>> storageLabels, boolean removeFromStoragesAlso) throws BusinessException {
storageLabelDataDao.removeLabels(storageLabels);
if (removeFromStoragesAlso) {
for (StorageData storageData : getExistingStorages()) {
removeLabelsFromStorage(storageData, new ArrayList<>(storageLabels));
}
}
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public void saveLabelType(AbstractStorageLabelType<?> labelType) {
storageLabelDataDao.saveLabelType(labelType);
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@MethodLog
public void removeLabelType(AbstractStorageLabelType<?> labelType) throws BusinessException {
storageLabelDataDao.removeLabelType(labelType);
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public <E extends AbstractStorageLabelType<?>> List<E> getLabelTypes(Class<E> labelTypeClass) {
return storageLabelDataDao.getLabelTypes(labelTypeClass);
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public List<AbstractStorageLabelType<?>> getAllLabelTypes() {
return storageLabelDataDao.getAllLabelTypes();
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public void updateStorageData(StorageData storageData) throws BusinessException {
try {
storageManager.updateStorageData(storageData);
} catch (SerializationException e) {
throw new TechnicalException("Update data for the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Update data for the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public long getStorageQueuedWriteTaskCount(StorageData storageData) {
return storageManager.getStorageQueuedWriteTaskCount(storageData);
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public void unpackUploadedStorage(IStorageData storageData) throws BusinessException {
try {
storageManager.unpackUploadedStorage(storageData);
} catch (IOException e) {
throw new TechnicalException("Un-pack uploaded data for the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public void createStorageFromUploadedDir(final IStorageData localStorageData) throws BusinessException {
try {
storageManager.createStorageFromUploadedDir(localStorageData);
} catch (SerializationException e) {
throw new TechnicalException("Create the storage " + localStorageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Create the storage " + localStorageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public void cacheStorageData(StorageData storageData, Collection<? extends DefaultData> data, int hash) throws BusinessException {
if (!storageManager.isStorageExisting(storageData)) {
throw new BusinessException("Data caching for the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_DOES_NOT_EXIST);
}
if (!storageManager.isStorageClosed(storageData)) {
throw new BusinessException("Data caching for the storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_IS_NOT_CLOSED);
}
try {
storageManager.cacheStorageData(storageData, data, hash);
} catch (SerializationException e) {
throw new TechnicalException("Cache data for the storage " + storageData + ".", StorageErrorCodeEnum.SERIALIZATION_FAILED, e);
} catch (IOException e) {
throw new TechnicalException("Cache data for the storage " + storageData + ".", StorageErrorCodeEnum.INPUT_OUTPUT_OPERATION_FAILED, e);
}
}
/**
* {@inheritDoc}
*/
@Override
@MethodLog
public String getCachedStorageDataFileLocation(StorageData storageData, int hash) throws BusinessException {
if (!storageManager.isStorageExisting(storageData)) {
throw new BusinessException("Load cached storage data files locations for storage " + storageData + ".", StorageErrorCodeEnum.STORAGE_DOES_NOT_EXIST);
}
return storageManager.getCachedStorageDataFileLocation(storageData, hash);
}
/**
* Is executed after dependency injection is done to perform any initialization.
*
* @throws Exception
* if an error occurs during {@link PostConstruct}
*/
@PostConstruct
public void postConstruct() throws Exception {
if (log.isInfoEnabled()) {
log.info("|-Storage Service active...");
}
}
}