/*******************************************************************************
* Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University
* as Operator of the SLAC National Accelerator Laboratory.
* Copyright (c) 2011 Brookhaven National Laboratory.
* EPICS archiver appliance is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*******************************************************************************/
package org.epics.archiverappliance.engine.bpl;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.epics.archiverappliance.EventStream;
import org.epics.archiverappliance.common.BPLAction;
import org.epics.archiverappliance.common.TimeUtils;
import org.epics.archiverappliance.config.ConfigService;
import org.epics.archiverappliance.engine.membuf.ArrayListEventStream;
import org.epics.archiverappliance.engine.model.ArchiveChannel;
import org.epics.archiverappliance.engine.pv.EngineContext;
import org.epics.archiverappliance.retrieval.RemotableEventStreamDesc;
import org.epics.archiverappliance.utils.ui.StreamPBIntoOutput;
/**
* PV for getting the data for a PV from the engine's buffers
* @author mshankar
*
*/
public class GetEngineDataAction implements BPLAction {
private static final Logger logger = Logger.getLogger(GetEngineDataAction.class);
@Override
public void execute(HttpServletRequest req, HttpServletResponse resp,
ConfigService configService) throws IOException {
String pvName = req.getParameter("pv");
if(pvName == null || pvName.equals("")) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String startTimeStr = req.getParameter("from");
String endTimeStr = req.getParameter("to");
// ISO datetimes are of the form "2011-02-02T08:00:00.000Z"
Timestamp start = null;
if(startTimeStr != null) {
start = TimeUtils.convertFromISO8601String(startTimeStr);
}
Timestamp end = null;
if(endTimeStr != null) {
end = TimeUtils.convertFromISO8601String(endTimeStr);
}
EngineContext engineContext = configService.getEngineContext();
if(engineContext.getChannelList().containsKey(pvName)){
ArchiveChannel archiveChannel = engineContext.getChannelList().get(pvName);
ArrayListEventStream st = archiveChannel.getPVData();
HashMap<String, String> metaFields = archiveChannel.getCurrentCopyOfMetaFields();
if(st != null && metaFields != null) {
mergeMetaFieldsIntoStream(st, metaFields);
}
if(st != null && !st.isEmpty()) {
OutputStream os = resp.getOutputStream();
try {
long s = System.currentTimeMillis();
int totalEvents = StreamPBIntoOutput.streamPBIntoOutputStream(st, os, start, end);
long e = System.currentTimeMillis();
logger.info("Found a total of " + totalEvents + " in " + (e-s) + "(ms)");
} finally {
try { os.flush(); os.close(); } catch(Throwable t) {}
}
return;
} else {
if(metaFields != null && archiveChannel.getPVMetrics() != null) {
logger.debug("Inserting empty header with latest meta fields from engine");
OutputStream os = resp.getOutputStream();
try {
RemotableEventStreamDesc desc = new RemotableEventStreamDesc(archiveChannel.getPVMetrics().getArchDBRTypes(), pvName, TimeUtils.getCurrentYear());
if(!archiveChannel.isConnected() && archiveChannel.getPVMetrics() != null) {
long connectionLastLostEpochSeconds = archiveChannel.getPVMetrics().getConnectionLastLostEpochSeconds();
if(connectionLastLostEpochSeconds != 0) {
logger.debug("Adding a cnxlostepsecs header");
metaFields.put("cnxlostepsecs", Long.toString(connectionLastLostEpochSeconds));
}
}
desc.addHeaders(metaFields);
StreamPBIntoOutput.writeHeaderOnly(os, desc);
} finally {
try { os.flush(); os.close(); } catch(Throwable t) {}
}
return;
}
}
}
logger.debug("No data for PV " + pvName + " in this engine.");
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
private void mergeMetaFieldsIntoStream(EventStream st, HashMap<String, String> metaFields) {
logger.debug("Merging meta fields from channel into engine's stream");
RemotableEventStreamDesc desc = (RemotableEventStreamDesc) st.getDescription();
try {
desc.addHeaders(metaFields);
} catch(Exception ex) {
logger.error("Exception merging meta fields into stream", ex);
}
}
}