Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
SymmetricDS is an open source database synchronization solution. It is platform-independent,
web-enabled, and database-agnostic. SymmetricDS was first built to replicate changes between 'retail store'
databases and ad centralized 'corporate' database.
/*
* Licensed to JumpMind Inc under one or more contributor
* license agreements. See the NOTICE file distributed
* with this work for additional information regarding
* copyright ownership. JumpMind Inc licenses this file
* to you under the GNU Lesser General Public License (the
* "License"); you may not use this file except in compliance
* with the License.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* .
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jumpmind.symmetric.service.impl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.jumpmind.symmetric.Version;
import org.jumpmind.symmetric.common.Constants;
import org.jumpmind.symmetric.common.Message;
import org.jumpmind.symmetric.common.ParameterConstants;
import org.jumpmind.symmetric.common.TableConstants;
import org.jumpmind.symmetric.csv.CsvWriter;
import org.jumpmind.symmetric.db.JdbcBatchPreparedStatementCallback;
import org.jumpmind.symmetric.db.SequenceIdentifier;
import org.jumpmind.symmetric.ddl.model.Table;
import org.jumpmind.symmetric.ext.IHeartbeatListener;
import org.jumpmind.symmetric.load.IReloadListener;
import org.jumpmind.symmetric.model.Data;
import org.jumpmind.symmetric.model.DataEvent;
import org.jumpmind.symmetric.model.DataEventType;
import org.jumpmind.symmetric.model.DataGap;
import org.jumpmind.symmetric.model.DataRef;
import org.jumpmind.symmetric.model.Node;
import org.jumpmind.symmetric.model.NodeGroupLink;
import org.jumpmind.symmetric.model.NodeGroupLinkAction;
import org.jumpmind.symmetric.model.OutgoingBatch;
import org.jumpmind.symmetric.model.Trigger;
import org.jumpmind.symmetric.model.TriggerHistory;
import org.jumpmind.symmetric.model.TriggerRouter;
import org.jumpmind.symmetric.model.OutgoingBatch.Status;
import org.jumpmind.symmetric.service.IConfigurationService;
import org.jumpmind.symmetric.service.IDataService;
import org.jumpmind.symmetric.service.INodeService;
import org.jumpmind.symmetric.service.IOutgoingBatchService;
import org.jumpmind.symmetric.service.IPurgeService;
import org.jumpmind.symmetric.service.ITriggerRouterService;
import org.jumpmind.symmetric.util.AppUtils;
import org.jumpmind.symmetric.util.CsvUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
/**
*
*/
public class DataService extends AbstractService implements IDataService {
private ITriggerRouterService triggerRouterService;
private INodeService nodeService;
private IPurgeService purgeService;
private IConfigurationService configurationService;
private IOutgoingBatchService outgoingBatchService;
private List reloadListeners;
private List heartbeatListeners;
protected Map lastHeartbeatTimestamps = new HashMap();
@Transactional
public void insertReloadEvent(final Node targetNode, final TriggerRouter triggerRouter) {
insertReloadEvent(targetNode, triggerRouter, null);
}
@Transactional
public void insertReloadEvent(final Node targetNode, final TriggerRouter triggerRouter,
final String overrideInitialLoadSelect) {
TriggerHistory history = lookupTriggerHistory(triggerRouter.getTrigger());
// initial_load_select for table can be overridden by populating the
// row_data
Data data = new Data(history.getSourceTableName(), DataEventType.RELOAD,
overrideInitialLoadSelect != null ? overrideInitialLoadSelect : triggerRouter
.getInitialLoadSelect(), null, history, triggerRouter.getTrigger().getChannelId(), null,
null);
insertDataAndDataEventAndOutgoingBatch(data, targetNode.getNodeId(), triggerRouter
.getRouter().getRouterId(), true);
}
private TriggerHistory lookupTriggerHistory(Trigger trigger) {
TriggerHistory history = triggerRouterService.getNewestTriggerHistoryForTrigger(trigger
.getTriggerId());
if (history == null) {
triggerRouterService.syncTriggers();
history = triggerRouterService.getNewestTriggerHistoryForTrigger(trigger
.getTriggerId());
}
if (history == null) {
throw new RuntimeException("Cannot find history for trigger " + trigger.getTriggerId()
+ ", " + trigger.getSourceTableName());
}
return history;
}
public void insertPurgeEvent(final Node targetNode, final TriggerRouter triggerRouter, boolean isLoad) {
String sql = dbDialect.createPurgeSqlFor(targetNode, triggerRouter);
insertSqlEvent(targetNode, triggerRouter.getTrigger(), sql, isLoad);
}
public void insertSqlEvent(final Node targetNode, final Trigger trigger, String sql, boolean isLoad) {
TriggerHistory history = triggerRouterService.getNewestTriggerHistoryForTrigger(trigger
.getTriggerId());
Data data = new Data(trigger.getSourceTableName(), DataEventType.SQL, CsvUtils
.escapeCsvData(sql), null, history, trigger.getChannelId(), null, null);
insertDataAndDataEventAndOutgoingBatch(data, targetNode.getNodeId(),
Constants.UNKNOWN_ROUTER_ID, isLoad);
}
public void insertSqlEvent(final Node targetNode, String sql, boolean isLoad) {
Data data = new Data(Constants.NA, DataEventType.SQL, CsvUtils.escapeCsvData(sql), null,
null, Constants.CHANNEL_CONFIG, null, null);
insertDataAndDataEventAndOutgoingBatch(data, targetNode.getNodeId(),
Constants.UNKNOWN_ROUTER_ID, isLoad);
}
public int countDataInRange(long firstDataId, long secondDataId) {
return jdbcTemplate.queryForInt(getSql("countDataInRangeSql"), firstDataId, secondDataId);
}
public void insertCreateEvent(final Node targetNode, final TriggerRouter triggerRouter,
String xml, boolean isLoad) {
TriggerHistory history = triggerRouterService
.getNewestTriggerHistoryForTrigger(triggerRouter.getTrigger().getTriggerId());
Data data = new Data(triggerRouter.getTrigger().getSourceTableName(), DataEventType.CREATE,
CsvUtils.escapeCsvData(xml), null, history,
parameterService.is(ParameterConstants.INITIAL_LOAD_USE_RELOAD_CHANNEL) && isLoad ? Constants.CHANNEL_RELOAD : triggerRouter.getTrigger().getChannelId(), null, null);
insertDataAndDataEventAndOutgoingBatch(data, targetNode.getNodeId(),
Constants.UNKNOWN_ROUTER_ID, isLoad);
}
public long insertData(final Data data) {
long id = dbDialect.insertWithGeneratedKey(getSql("insertIntoDataSql"),
SequenceIdentifier.DATA, new PreparedStatementCallback