/******************************************************************************* * Copyright (c) 2008 Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * File: $Source$ * Created by: Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>) * Created on: Oct 9, 2008 * Revision: $Id$ * * Contributors: * Cambridge Semantics Incorporated - initial API and implementation *******************************************************************************/ package org.openanzo.combus.listeners; import java.io.StringWriter; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; import org.openanzo.analysis.RequestAnalysis; import org.openanzo.analysis.RequestRecorder; import org.openanzo.combus.MessageUtils; import org.openanzo.combus.endpoint.BaseServiceListener; import org.openanzo.exceptions.AnzoException; import org.openanzo.exceptions.ExceptionConstants; import org.openanzo.exceptions.LogUtils; import org.openanzo.rdf.Constants; import org.openanzo.rdf.Resource; import org.openanzo.rdf.URI; import org.openanzo.rdf.Value; import org.openanzo.rdf.utils.SerializationConstants; import org.openanzo.services.serialization.IReplicationHandler; import org.openanzo.services.serialization.JSONReplicationWriter; import org.openanzo.services.serialization.XMLReplicationWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Batch replication handler * * @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com</a>) * */ public class BatchedReplicationHandler implements IReplicationHandler { private static final Logger log = LoggerFactory.getLogger(BaseServiceListener.class); private StringWriter outputWriter; private IReplicationHandler writer; private final boolean xml; private final int batchSize; private final Destination replyTo; private final String operation; private final Session session; private final MessageProducer mp; private final TextMessage request; private int size = 0; private int totalSize = 0; private int totalSeen = 0; private int sequence = 0; private URI lastNamedGraphUri; private URI lastUuid; private Long lastRevision = null; private long totalWriteTime = 0; protected RequestRecorder recorder = null; BatchedReplicationHandler(int batchSize, Destination replyTo, String resultFormat, String operation, TextMessage request, Session session, MessageProducer mp, RequestRecorder recorder) { this.xml = (SerializationConstants.MIMETYPE_ANZO_XML.equals(resultFormat)); this.batchSize = batchSize; this.replyTo = replyTo; this.operation = operation; this.session = session; this.mp = mp; this.request = request; this.recorder = recorder; } public void start(int totalSize) throws AnzoException { this.totalWriteTime = 0; this.totalSize = totalSize; startMessage(); } public void end() throws AnzoException { endMessage(true); if (RequestAnalysis.isAnalysisEnabled()) { RequestAnalysis.addAnalysisProperty("replicationWriteResults", totalWriteTime); } } public boolean handleNamedGraph(URI namedGraphUri, URI uuid, long revision) throws AnzoException { lastNamedGraphUri = namedGraphUri; lastUuid = uuid; lastRevision = revision; long start = 0; if (RequestAnalysis.isAnalysisEnabled()) { start = System.currentTimeMillis(); } boolean ret = writer.handleNamedGraph(namedGraphUri, uuid, revision); if (RequestAnalysis.isAnalysisEnabled()) { long end = System.currentTimeMillis(); long time = end - start; totalWriteTime += time; } return ret; } public boolean handleStatement(boolean metadata, boolean addition, Resource subject, URI predicate, Value object, URI namedGraphURI) throws AnzoException { long start = 0; if (RequestAnalysis.isAnalysisEnabled()) { start = System.currentTimeMillis(); } writer.handleStatement(metadata, addition, subject, predicate, object, namedGraphURI); if (RequestAnalysis.isAnalysisEnabled()) { long end = System.currentTimeMillis(); long time = end - start; totalWriteTime += time; } totalSeen++; if (batchSize > 0 && (size++ > batchSize)) { endMessage(false); startMessage(); size = 0; } return true; } private void startMessage() throws AnzoException { outputWriter = new StringWriter(); if (xml) { writer = new XMLReplicationWriter(outputWriter); } else { writer = new JSONReplicationWriter(outputWriter); } writer.start(this.totalSize); if (lastNamedGraphUri != null) { writer.handleNamedGraph(lastNamedGraphUri, lastUuid, lastRevision); } } private void endMessage(boolean done) throws AnzoException { if (writer != null) { writer.end(); try { TextMessage response = session.createTextMessage(); response.setIntProperty(SerializationConstants.protocolVersion, Constants.VERSION); response.setBooleanProperty(SerializationConstants.operationFailed, false); long start = 0; if (RequestAnalysis.isAnalysisEnabled()) { start = System.currentTimeMillis(); } String out = outputWriter.toString(); if (RequestAnalysis.isAnalysisEnabled()) { long end = System.currentTimeMillis(); long time = end - start; totalWriteTime += time; } if (out.length() > 0) { response.setText(out); } if (replyTo != null) { response.setJMSCorrelationID(request.getJMSCorrelationID()); if (operation != null) { response.setStringProperty(SerializationConstants.operation, operation); } if (log.isDebugEnabled()) { log.debug(MessageUtils.prettyPrint(response, "Sending Response to [" + replyTo + "]")); } response.setBooleanProperty("done", done); if (!done || sequence > 0) { response.setIntProperty("sequence", sequence); response.setIntProperty("totalSize", totalSize); } if (RequestAnalysis.isAnalysisEnabled()) { start = System.currentTimeMillis(); } mp.send(replyTo, response); if (RequestAnalysis.isAnalysisEnabled()) { long end = System.currentTimeMillis(); long time = end - start; RequestAnalysis.addAnalysisProperty("sendReplicationBatch", time); } if (recorder != null) { recorder.recordResponse(response); } } } catch (JMSException jmsex) { log.error(LogUtils.COMBUS_MARKER, "Error sending batched replication service end message", jmsex); throw new AnzoException(ExceptionConstants.COMBUS.JMS_SERVICE_EXCEPTION, jmsex); } } sequence++; } }