Search in sources :

Example 21 with OutgoingBatch

use of org.jumpmind.symmetric.model.OutgoingBatch in project symmetric-ds by JumpMind.

the class AbstractService method readAcks.

protected List<BatchAck> readAcks(List<OutgoingBatch> batches, IOutgoingWithResponseTransport transport, ITransportManager transportManager, IAcknowledgeService acknowledgeService) throws IOException {
    Set<Long> batchIds = new HashSet<Long>(batches.size());
    for (OutgoingBatch outgoingBatch : batches) {
        if (outgoingBatch.getStatus() == OutgoingBatch.Status.LD) {
            batchIds.add(outgoingBatch.getBatchId());
        }
    }
    BufferedReader reader = transport.readResponse();
    String ackString = reader.readLine();
    String ackExtendedString = reader.readLine();
    log.debug("Reading ack: {}", ackString);
    log.debug("Reading extend ack: {}", ackExtendedString);
    String line = null;
    do {
        line = reader.readLine();
        if (line != null) {
            log.info("Read another unexpected line {}", line);
        }
    } while (line != null);
    if (StringUtils.isBlank(ackString)) {
        throw new SymmetricException("Did not receive an acknowledgement for the batches sent.  " + "The 'ack string' was: '%s' and the 'extended ack string' was: '%s'", ackString, ackExtendedString);
    }
    List<BatchAck> batchAcks = transportManager.readAcknowledgement(ackString, ackExtendedString);
    long batchIdInError = Long.MAX_VALUE;
    for (BatchAck batchInfo : batchAcks) {
        batchIds.remove(batchInfo.getBatchId());
        if (!batchInfo.isOk()) {
            batchIdInError = batchInfo.getBatchId();
        }
        log.debug("Saving ack: {}, {}", batchInfo.getBatchId(), (batchInfo.isOk() ? "OK" : "ER"));
        acknowledgeService.ack(batchInfo);
    }
    for (Long batchId : batchIds) {
        if (batchId < batchIdInError) {
            log.error("We expected but did not receive an ack for batch {}", batchId);
        }
    }
    return batchAcks;
}
Also used : BatchAck(org.jumpmind.symmetric.model.BatchAck) SymmetricException(org.jumpmind.symmetric.SymmetricException) BufferedReader(java.io.BufferedReader) OutgoingBatch(org.jumpmind.symmetric.model.OutgoingBatch) HashSet(java.util.HashSet)

Example 22 with OutgoingBatch

use of org.jumpmind.symmetric.model.OutgoingBatch in project symmetric-ds by JumpMind.

the class AcknowledgeService method ack.

public BatchAckResult ack(final BatchAck batch) {
    IRegistrationService registrationService = engine.getRegistrationService();
    IOutgoingBatchService outgoingBatchService = engine.getOutgoingBatchService();
    BatchAckResult result = new BatchAckResult(batch);
    for (IAcknowledgeEventListener listener : engine.getExtensionService().getExtensionPointList(IAcknowledgeEventListener.class)) {
        listener.onAcknowledgeEvent(batch);
    }
    if (batch.getBatchId() == Constants.VIRTUAL_BATCH_FOR_REGISTRATION) {
        if (batch.isOk()) {
            registrationService.markNodeAsRegistered(batch.getNodeId());
        }
    } else {
        OutgoingBatch outgoingBatch = outgoingBatchService.findOutgoingBatch(batch.getBatchId(), batch.getNodeId());
        Status status = batch.isOk() ? Status.OK : batch.isResend() ? Status.RS : Status.ER;
        if (outgoingBatch != null) {
            // is OK.
            if (outgoingBatch.getStatus() != Status.OK && outgoingBatch.getStatus() != Status.IG) {
                outgoingBatch.setStatus(status);
                outgoingBatch.setErrorFlag(!batch.isOk());
            } else {
                // clearing the error flag in case the user set the batch
                // status to OK
                Status oldStatus = outgoingBatch.getStatus();
                outgoingBatch.setStatus(Status.OK);
                outgoingBatch.setErrorFlag(false);
                log.info("Batch {} for {} was set to {}.  Updating the status to OK", new Object[] { batch.getBatchId(), batch.getNodeId(), oldStatus.name() });
            }
            if (batch.isIgnored()) {
                outgoingBatch.incrementIgnoreCount();
            }
            outgoingBatch.setNetworkMillis(batch.getNetworkMillis());
            outgoingBatch.setFilterMillis(batch.getFilterMillis());
            outgoingBatch.setLoadMillis(batch.getDatabaseMillis());
            outgoingBatch.setSqlCode(batch.getSqlCode());
            outgoingBatch.setSqlState(batch.getSqlState());
            outgoingBatch.setSqlMessage(batch.getSqlMessage());
            boolean isNewError = false;
            if (!batch.isOk() && batch.getErrorLine() != 0) {
                List<Number> ids = sqlTemplateDirty.query(getSql("selectDataIdSql"), new NumberMapper(), outgoingBatch.getBatchId());
                if (ids.size() >= batch.getErrorLine()) {
                    long failedDataId = ids.get((int) batch.getErrorLine() - 1).longValue();
                    if (outgoingBatch.getFailedDataId() == 0 || outgoingBatch.getFailedDataId() != failedDataId) {
                        isNewError = true;
                    }
                    outgoingBatch.setFailedDataId(failedDataId);
                }
            }
            if (status == Status.ER) {
                log.error("The outgoing batch {} failed: {}{}", outgoingBatch.getNodeBatchId(), (batch.getSqlCode() != 0 ? "[" + batch.getSqlState() + "," + batch.getSqlCode() + "] " : ""), batch.getSqlMessage());
                RouterStats routerStats = engine.getStatisticManager().getRouterStatsByBatch(batch.getBatchId());
                if (routerStats != null) {
                    log.info("Router stats for batch " + outgoingBatch.getBatchId() + ": " + routerStats.toString());
                }
                if (isNewError && outgoingBatch.getSqlCode() == ErrorConstants.FK_VIOLATION_CODE && parameterService.is(ParameterConstants.AUTO_RESOLVE_FOREIGN_KEY_VIOLATION)) {
                    Channel channel = engine.getConfigurationService().getChannel(outgoingBatch.getChannelId());
                    if (channel != null && !channel.isReloadFlag()) {
                        engine.getDataService().reloadMissingForeignKeyRows(outgoingBatch.getNodeId(), outgoingBatch.getFailedDataId());
                    }
                }
            } else if (status == Status.RS) {
                log.info("The outgoing batch {} received resend request", outgoingBatch.getNodeBatchId());
            }
            outgoingBatchService.updateOutgoingBatch(outgoingBatch);
            if (status == Status.OK) {
                Channel channel = engine.getConfigurationService().getChannel(outgoingBatch.getChannelId());
                if (channel != null && channel.isFileSyncFlag()) {
                    /* Acknowledge the file_sync in case the file needs deleted. */
                    engine.getFileSyncService().acknowledgeFiles(outgoingBatch);
                }
                engine.getStatisticManager().removeRouterStatsByBatch(batch.getBatchId());
            }
        } else {
            log.error("Could not find batch {}-{} to acknowledge as {}", new Object[] { batch.getNodeId(), batch.getBatchId(), status.name() });
            result.setOk(false);
        }
    }
    return result;
}
Also used : Status(org.jumpmind.symmetric.model.OutgoingBatch.Status) NumberMapper(org.jumpmind.db.sql.mapper.NumberMapper) IAcknowledgeEventListener(org.jumpmind.symmetric.transport.IAcknowledgeEventListener) IRegistrationService(org.jumpmind.symmetric.service.IRegistrationService) Channel(org.jumpmind.symmetric.model.Channel) BatchAckResult(org.jumpmind.symmetric.model.BatchAckResult) RouterStats(org.jumpmind.symmetric.statistic.RouterStats) IOutgoingBatchService(org.jumpmind.symmetric.service.IOutgoingBatchService) OutgoingBatch(org.jumpmind.symmetric.model.OutgoingBatch)

Example 23 with OutgoingBatch

use of org.jumpmind.symmetric.model.OutgoingBatch in project symmetric-ds by JumpMind.

the class DataExtractorService method execute.

/**
     * This is a callback method used by the NodeCommunicationService that extracts an initial load
     * in the background.
     */
public void execute(NodeCommunication nodeCommunication, RemoteNodeStatus status) {
    if (!isApplicable(nodeCommunication, status)) {
        log.debug("{} failed isApplicable check and will not run.", this);
        return;
    }
    List<ExtractRequest> requests = getExtractRequestsForNode(nodeCommunication);
    long ts = System.currentTimeMillis();
    /*
         * Process extract requests until it has taken longer than 30 seconds, and then
         * allow the process to return so progress status can be seen.
         */
    for (int i = 0; i < requests.size() && (System.currentTimeMillis() - ts) <= Constants.LONG_OPERATION_THRESHOLD; i++) {
        ExtractRequest request = requests.get(i);
        Node identity = nodeService.findIdentity();
        Node targetNode = nodeService.findNode(nodeCommunication.getNodeId());
        log.info("Extracting batches for request {}. Starting at batch {}.  Ending at batch {}", new Object[] { request.getRequestId(), request.getStartBatchId(), request.getEndBatchId() });
        List<OutgoingBatch> batches = outgoingBatchService.getOutgoingBatchRange(request.getStartBatchId(), request.getEndBatchId()).getBatches();
        ProcessInfo processInfo = statisticManager.newProcessInfo(new ProcessInfoKey(identity.getNodeId(), nodeCommunication.getQueue(), nodeCommunication.getNodeId(), getProcessType()));
        processInfo.setBatchCount(batches.size());
        try {
            boolean areBatchesOk = true;
            /*
                 * check to see if batches have been OK'd by another reload
                 * request 
                 */
            for (OutgoingBatch outgoingBatch : batches) {
                if (outgoingBatch.getStatus() != Status.OK) {
                    areBatchesOk = false;
                    break;
                }
            }
            if (!areBatchesOk) {
                Channel channel = configurationService.getChannel(batches.get(0).getChannelId());
                /*
                     * "Trick" the extractor to extract one reload batch, but we
                     * will split it across the N batches when writing it
                     */
                OutgoingBatch firstBatch = batches.get(0);
                processInfo.setCurrentLoadId(firstBatch.getLoadId());
                IStagedResource resource = getStagedResource(firstBatch);
                if (resource != null && resource.exists() && resource.getState() != State.CREATE) {
                    resource.delete();
                }
                MultiBatchStagingWriter multiBatchStatingWriter = buildMultiBatchStagingWriter(request, identity, targetNode, batches, processInfo, channel);
                extractOutgoingBatch(processInfo, targetNode, multiBatchStatingWriter, firstBatch, false, false, ExtractMode.FOR_SYM_CLIENT);
                for (OutgoingBatch outgoingBatch : batches) {
                    resource = getStagedResource(outgoingBatch);
                    if (resource != null) {
                        resource.setState(State.DONE);
                    }
                }
            } else {
                log.info("Batches already had an OK status for request {}, batches {} to {}.  Not extracting", new Object[] { request.getRequestId(), request.getStartBatchId(), request.getEndBatchId() });
            }
            /*
                 * re-query the batches to see if they have been OK'd while
                 * extracting
                 */
            List<OutgoingBatch> checkBatches = outgoingBatchService.getOutgoingBatchRange(request.getStartBatchId(), request.getEndBatchId()).getBatches();
            areBatchesOk = true;
            /*
                 * check to see if batches have been OK'd by another reload
                 * request while extracting
                 */
            for (OutgoingBatch outgoingBatch : checkBatches) {
                if (outgoingBatch.getStatus() != Status.OK) {
                    areBatchesOk = false;
                    break;
                }
            }
            ISqlTransaction transaction = null;
            try {
                transaction = sqlTemplate.startSqlTransaction();
                updateExtractRequestStatus(transaction, request.getRequestId(), ExtractStatus.OK);
                if (!areBatchesOk) {
                    for (OutgoingBatch outgoingBatch : batches) {
                        if (!parameterService.is(ParameterConstants.INITIAL_LOAD_EXTRACT_AND_SEND_WHEN_STAGED, false)) {
                            outgoingBatch.setStatus(Status.NE);
                            outgoingBatchService.updateOutgoingBatch(transaction, outgoingBatch);
                        }
                    }
                } else {
                    log.info("Batches already had an OK status for request {}, batches {} to {}.  Not updating the status to NE", new Object[] { request.getRequestId(), request.getStartBatchId(), request.getEndBatchId() });
                }
                transaction.commit();
                log.info("Done extracting {} batches for request {}", (request.getEndBatchId() - request.getStartBatchId()) + 1, request.getRequestId());
            } catch (Error ex) {
                if (transaction != null) {
                    transaction.rollback();
                }
                throw ex;
            } catch (RuntimeException ex) {
                if (transaction != null) {
                    transaction.rollback();
                }
                throw ex;
            } finally {
                close(transaction);
            }
            processInfo.setStatus(org.jumpmind.symmetric.model.ProcessInfo.Status.OK);
        } catch (CancellationException ex) {
            log.info("Cancelled extract request {}. Starting at batch {}.  Ending at batch {}", new Object[] { request.getRequestId(), request.getStartBatchId(), request.getEndBatchId() });
            processInfo.setStatus(org.jumpmind.symmetric.model.ProcessInfo.Status.OK);
        } catch (RuntimeException ex) {
            log.debug("Failed to extract batches for request {}. Starting at batch {}.  Ending at batch {}", new Object[] { request.getRequestId(), request.getStartBatchId(), request.getEndBatchId() });
            processInfo.setStatus(org.jumpmind.symmetric.model.ProcessInfo.Status.ERROR);
            throw ex;
        }
    }
}
Also used : Node(org.jumpmind.symmetric.model.Node) NodeChannel(org.jumpmind.symmetric.model.NodeChannel) Channel(org.jumpmind.symmetric.model.Channel) ProcessInfoKey(org.jumpmind.symmetric.model.ProcessInfoKey) ProcessInfo(org.jumpmind.symmetric.model.ProcessInfo) ExtractRequest(org.jumpmind.symmetric.model.ExtractRequest) TransformPoint(org.jumpmind.symmetric.io.data.transform.TransformPoint) ISqlTransaction(org.jumpmind.db.sql.ISqlTransaction) CancellationException(java.util.concurrent.CancellationException) IStagedResource(org.jumpmind.symmetric.io.stage.IStagedResource) OutgoingBatch(org.jumpmind.symmetric.model.OutgoingBatch)

Example 24 with OutgoingBatch

use of org.jumpmind.symmetric.model.OutgoingBatch in project symmetric-ds by JumpMind.

the class DataExtractorService method extractBatchRange.

public boolean extractBatchRange(Writer writer, String nodeId, long startBatchId, long endBatchId) {
    boolean foundBatch = false;
    Node sourceNode = nodeService.findIdentity();
    for (long batchId = startBatchId; batchId <= endBatchId; batchId++) {
        OutgoingBatch batch = outgoingBatchService.findOutgoingBatch(batchId, nodeId);
        if (batch != null) {
            Node targetNode = nodeService.findNode(nodeId);
            if (targetNode == null && Constants.UNROUTED_NODE_ID.equals(nodeId)) {
                targetNode = new Node();
                targetNode.setNodeId("-1");
            }
            if (targetNode != null) {
                IDataReader dataReader = new ExtractDataReader(symmetricDialect.getPlatform(), new SelectFromSymDataSource(batch, sourceNode, targetNode, new ProcessInfo()));
                DataContext ctx = new DataContext();
                ctx.put(Constants.DATA_CONTEXT_TARGET_NODE, targetNode);
                ctx.put(Constants.DATA_CONTEXT_SOURCE_NODE, nodeService.findIdentity());
                new DataProcessor(dataReader, createTransformDataWriter(nodeService.findIdentity(), targetNode, new ProtocolDataWriter(nodeService.findIdentityNodeId(), writer, targetNode.requires13Compatiblity())), "extract range").process(ctx);
                foundBatch = true;
            }
        }
    }
    return foundBatch;
}
Also used : IDataReader(org.jumpmind.symmetric.io.data.IDataReader) DataContext(org.jumpmind.symmetric.io.data.DataContext) ProtocolDataWriter(org.jumpmind.symmetric.io.data.writer.ProtocolDataWriter) Node(org.jumpmind.symmetric.model.Node) OutgoingBatch(org.jumpmind.symmetric.model.OutgoingBatch) ProcessInfo(org.jumpmind.symmetric.model.ProcessInfo) DataProcessor(org.jumpmind.symmetric.io.data.DataProcessor) ExtractDataReader(org.jumpmind.symmetric.io.data.reader.ExtractDataReader)

Example 25 with OutgoingBatch

use of org.jumpmind.symmetric.model.OutgoingBatch in project symmetric-ds by JumpMind.

the class DataExtractorService method cleanupIgnoredBatch.

protected void cleanupIgnoredBatch(Node sourceNode, Node targetNode, OutgoingBatch currentBatch, IDataWriter writer) {
    Batch batch = new Batch(BatchType.EXTRACT, currentBatch.getBatchId(), currentBatch.getChannelId(), symmetricDialect.getBinaryEncoding(), sourceNode.getNodeId(), currentBatch.getNodeId(), currentBatch.isCommonFlag());
    batch.setIgnored(true);
    try {
        IStagedResource resource = getStagedResource(currentBatch);
        if (resource != null) {
            resource.delete();
        }
        DataContext ctx = new DataContext(batch);
        ctx.put("targetNode", targetNode);
        ctx.put("sourceNode", sourceNode);
        writer.open(ctx);
        writer.start(batch);
        writer.end(batch, false);
    } finally {
        writer.close();
    }
}
Also used : DataContext(org.jumpmind.symmetric.io.data.DataContext) Batch(org.jumpmind.symmetric.io.data.Batch) OutgoingBatch(org.jumpmind.symmetric.model.OutgoingBatch) IStagedResource(org.jumpmind.symmetric.io.stage.IStagedResource)

Aggregations

OutgoingBatch (org.jumpmind.symmetric.model.OutgoingBatch)37 OutgoingBatches (org.jumpmind.symmetric.model.OutgoingBatches)12 ArrayList (java.util.ArrayList)10 ProcessInfo (org.jumpmind.symmetric.model.ProcessInfo)9 Node (org.jumpmind.symmetric.model.Node)8 IStagedResource (org.jumpmind.symmetric.io.stage.IStagedResource)6 ProcessInfoKey (org.jumpmind.symmetric.model.ProcessInfoKey)6 NodeChannel (org.jumpmind.symmetric.model.NodeChannel)5 SymmetricException (org.jumpmind.symmetric.SymmetricException)4 ProtocolDataWriter (org.jumpmind.symmetric.io.data.writer.ProtocolDataWriter)4 BatchAck (org.jumpmind.symmetric.model.BatchAck)4 Channel (org.jumpmind.symmetric.model.Channel)4 File (java.io.File)3 IOException (java.io.IOException)3 HashSet (java.util.HashSet)3 CancellationException (java.util.concurrent.CancellationException)3 IoException (org.jumpmind.exception.IoException)3 DataContext (org.jumpmind.symmetric.io.data.DataContext)3 ChannelMap (org.jumpmind.symmetric.model.ChannelMap)3 BufferedReader (java.io.BufferedReader)2