use of org.jumpmind.symmetric.model.Node in project symmetric-ds by JumpMind.
the class PullService method execute.
public void execute(NodeCommunication nodeCommunication, RemoteNodeStatus status) {
Node node = nodeCommunication.getNode();
if (StringUtils.isNotBlank(node.getSyncUrl()) || !parameterService.isRegistrationServer()) {
int pullCount = 0;
long batchesProcessedCount = 0;
do {
batchesProcessedCount = status.getBatchesProcessed();
pullCount++;
log.debug("Pull requested for {}", node.toString());
if (pullCount > 1) {
log.info("Immediate pull requested while in reload mode");
}
try {
dataLoaderService.loadDataFromPull(node, status);
fireOnline(node, status);
} catch (Exception ex) {
fireOffline(ex, node, status);
}
if (!status.failed() && (status.getDataProcessed() > 0 || status.getBatchesProcessed() > 0)) {
log.info("Pull data received from {} {}. {} rows and {} batches were processed", new Object[] { node.toString(), "on channel thread " + nodeCommunication.getQueue(), status.getDataProcessed(), status.getBatchesProcessed() });
} else if (status.failed()) {
log.debug("There was a failure while pulling data from {} {}. {} rows and {} batches were processed", new Object[] { node.toString(), "on channel thread " + nodeCommunication.getQueue(), status.getDataProcessed(), status.getBatchesProcessed() });
}
/*
* Re-pull immediately if we are in the middle of an initial
* load so that the initial load completes as quickly as
* possible.
*/
} while (nodeService.isDataLoadStarted() && !status.failed() && status.getBatchesProcessed() > batchesProcessedCount);
} else {
log.warn("Cannot pull node '{}' in the group '{}'. The sync url is blank", node.getNodeId(), node.getNodeGroupId());
}
}
use of org.jumpmind.symmetric.model.Node in project symmetric-ds by JumpMind.
the class PullService method pullData.
public synchronized RemoteNodeStatuses pullData(boolean force) {
final RemoteNodeStatuses statuses = new RemoteNodeStatuses(configurationService.getChannels(false));
Node identity = nodeService.findIdentity();
if (identity == null || identity.isSyncEnabled()) {
long minimumPeriodMs = parameterService.getLong(ParameterConstants.PULL_MINIMUM_PERIOD_MS, -1);
if (force || !clusterService.isInfiniteLocked(ClusterConstants.PULL)) {
// register if we haven't already been registered
registrationService.registerWithServer();
identity = nodeService.findIdentity();
if (identity != null) {
List<NodeCommunication> nodes = nodeCommunicationService.list(CommunicationType.PULL);
int availableThreads = nodeCommunicationService.getAvailableThreads(CommunicationType.PULL);
for (NodeCommunication nodeCommunication : nodes) {
boolean meetsMinimumTime = true;
if (minimumPeriodMs > 0 && nodeCommunication.getLastLockTime() != null && (System.currentTimeMillis() - nodeCommunication.getLastLockTime().getTime()) < minimumPeriodMs) {
meetsMinimumTime = false;
}
if (availableThreads > 0 && meetsMinimumTime) {
if (nodeCommunicationService.execute(nodeCommunication, statuses, this)) {
availableThreads--;
}
}
}
}
} else {
log.debug("Did not run the pull process because it has been stopped");
}
}
return statuses;
}
use of org.jumpmind.symmetric.model.Node in project symmetric-ds by JumpMind.
the class RegistrationService method reOpenRegistration.
protected synchronized void reOpenRegistration(String nodeId, String remoteHost, String remoteAddress) {
Node node = nodeService.findNode(nodeId);
NodeSecurity security = nodeService.findNodeSecurity(nodeId);
String password = null;
if (security != null && parameterService.is(ParameterConstants.REGISTRATION_REOPEN_USE_SAME_PASSWORD, true)) {
password = security.getNodePassword();
} else {
password = extensionService.getExtensionPoint(INodeIdCreator.class).generatePassword(node);
password = filterPasswordOnSaveIfNeeded(password);
}
if (node != null) {
int updateCount = sqlTemplate.update(getSql("reopenRegistrationSql"), new Object[] { password, nodeId });
if (updateCount == 0 && nodeService.findNodeSecurity(nodeId) == null) {
// if the update count was 0, then we probably have a row in the
// node table, but not in node security.
// lets go ahead and try to insert into node security.
sqlTemplate.update(getSql("openRegistrationNodeSecuritySql"), new Object[] { nodeId, password, nodeService.findNode(nodeId).getNodeId() });
log.info("Registration was opened for {}", nodeId);
} else if (updateCount == 0) {
log.warn("Registration was already enabled for {}. No need to reenable it", nodeId);
} else {
log.info("Registration was reopened for {}", nodeId);
}
if (isNotBlank(remoteHost)) {
NodeHost nodeHost = new NodeHost(node.getNodeId());
nodeHost.setHeartbeatTime(new Date());
nodeHost.setIpAddress(remoteAddress);
nodeHost.setHostName(remoteHost);
nodeService.updateNodeHost(nodeHost);
}
nodeService.flushNodeAuthorizedCache();
} else {
log.warn("There was no row with a node id of {} to 'reopen' registration for", nodeId);
}
}
use of org.jumpmind.symmetric.model.Node in project symmetric-ds by JumpMind.
the class RestServiceTest method testRestPullApi.
protected void testRestPullApi() throws Exception {
loadConfigAtRegistrationServer();
RestService restService = getRegServer().getRestService();
ISymmetricEngine engine = getRegServer().getEngine();
IParameterService parameterService = engine.getParameterService();
INodeService nodeService = engine.getNodeService();
parameterService.saveParameter(ParameterConstants.REST_API_ENABLED, Boolean.TRUE, "unit_test");
assertNotNull("Could not find the rest service in the application context", restService);
List<Node> nodes = nodeService.findAllNodes();
assertEquals("Expected there to only be one node registered", 1, nodes.size());
assertEquals("The only node we expected to be registered is a server node", "server", nodes.get(0).getNodeGroupId());
RegistrationInfo registrationInfo = restService.postRegisterNode("client", "client", DatabaseNamesConstants.SQLITE, "3.0", "hostName");
assertNotNull("Registration should have returned a result object", registrationInfo);
assertFalse("Registration should not have been open", registrationInfo.isRegistered());
assertEquals("Expected there to only be one node registered", 1, nodes.size());
engine.openRegistration("client", "client");
registrationInfo = restService.postRegisterNode("client", "client", DatabaseNamesConstants.SQLITE, "3.0", "hostName");
assertNotNull("Registration should have returned a result object", registrationInfo);
assertTrue("Registration should have been open", registrationInfo.isRegistered());
assertEquals("client", registrationInfo.getNodeId());
try {
restService.getPullData(registrationInfo.getNodeId(), "wrong password", false, false, true, null);
fail("We should have received an exception");
} catch (NotAllowedException ex) {
}
PullDataResults results = null;
assertPullReturnsNoData(restService, registrationInfo);
engine.getSqlTemplate().update("insert into a values(?, ?, ?)", 1, "this is a test", FormatUtils.parseDate("2013-06-08 00:00:00.000", FormatUtils.TIMESTAMP_PATTERNS));
engine.route();
results = restService.getPullData("server", registrationInfo.getNodeId(), registrationInfo.getNodePassword(), false, false, true, null);
assertNotNull("Should have a non null results object", results);
assertEquals(1, results.getNbrBatches());
assertEquals(4, results.getBatches().get(0).getBatchId());
log.info(results.getBatches().get(0).getSqlStatements().get(0));
// pull a second time without acking. should get the same results
results = restService.getPullData("server", registrationInfo.getNodeId(), registrationInfo.getNodePassword(), false, false, false, null);
assertNotNull("Should have a non null results object", results);
assertEquals(1, results.getNbrBatches());
// test that when we don't request jdbc timestamp format sql statements come back in that format
assertFalse(results.getBatches().get(0).getSqlStatements().get(0).contains("{ts '"));
// make sure we have no delimited identifiers
assertFalse(results.getBatches().get(0).getSqlStatements().get(0).contains("\""));
engine.getSqlTemplate().update("update a set notes=? where id=?", "changed", 1);
engine.getSqlTemplate().update("update a set notes=? where id=?", "changed again", 1);
engine.route();
results = restService.getPullData("server", registrationInfo.getNodeId(), registrationInfo.getNodePassword(), true, false, true, null);
assertNotNull("Should have a non null results object", results);
assertEquals(2, results.getNbrBatches());
assertNotSame(results.getBatches().get(1).getBatchId(), results.getBatches().get(0).getBatchId());
assertEquals(2, results.getBatches().get(1).getSqlStatements().size());
// test that when we request jdbc timestamp format sql statements come back in that format
String testSql = results.getBatches().get(1).getSqlStatements().get(0);
assertTrue("The following sql was supposed to contain '{ts '" + testSql, testSql.contains("{ts '"));
// make sure we have delimited identifiers
assertTrue(results.getBatches().get(1).getSqlStatements().get(0).contains("\""));
log.info(results.getBatches().get(1).getSqlStatements().get(0));
log.info(results.getBatches().get(1).getSqlStatements().get(1));
ackBatches(restService, registrationInfo, results, buildBatchResults(registrationInfo, results));
engine.getSqlTemplate().update("insert into a values(?, ?, ?)", 2, "this is a test", FormatUtils.parseDate("2073-06-08 00:00:00.000", FormatUtils.TIMESTAMP_PATTERNS));
engine.getSqlTemplate().update("insert into a values(?, ?, ?)", 3, "this is a test", FormatUtils.parseDate("2073-06-08 00:00:00.000", FormatUtils.TIMESTAMP_PATTERNS));
engine.getSqlTemplate().update("update a set notes=? where id=?", "update to 2", 2);
engine.getSqlTemplate().update("update a set notes=? where id=?", "update to 3", 3);
engine.getSqlTemplate().update("update a set notes=? where id=?", "update 2 again", 2);
engine.route();
results = restService.getPullData("server", registrationInfo.getNodeId(), registrationInfo.getNodePassword(), false, true, true, null);
assertNotNull("Should have a non null results object", results);
assertEquals(1, results.getNbrBatches());
List<String> sqls = results.getBatches().get(0).getSqlStatements();
assertEquals(5, sqls.size());
for (String sql : sqls) {
log.info(sql);
assertTrue(sql, sql.toLowerCase().startsWith("insert or replace"));
}
ackBatches(restService, registrationInfo, results, buildBatchResults(registrationInfo, results));
Channel channel = engine.getConfigurationService().getChannel("default");
channel.setBatchAlgorithm("nontransactional");
channel.setMaxBatchSize(1);
engine.getConfigurationService().saveChannel(channel, true);
engine.getSqlTemplate().update("delete from a");
engine.route();
results = restService.getPullData("server", registrationInfo.getNodeId(), registrationInfo.getNodePassword(), false, false, true, null);
assertNotNull("Should have a non null results object", results);
assertEquals(3, results.getNbrBatches());
List<Batch> batches = results.getBatches();
for (Batch batch : batches) {
assertEquals(1, batch.getSqlStatements().size());
assertTrue(batch.getSqlStatements().get(0).toLowerCase().startsWith("delete from"));
}
ackBatches(restService, registrationInfo, results, buildBatchResults(registrationInfo, results));
}
use of org.jumpmind.symmetric.model.Node in project symmetric-ds by JumpMind.
the class SymmetricAdmin method sendSchema.
private void sendSchema(CommandLine line, List<String> args) {
String catalog = line.getOptionValue(OPTION_CATALOG);
String schema = line.getOptionValue(OPTION_SCHEMA);
Collection<Node> nodes = getNodes(line);
if (args.size() == 0) {
for (TriggerHistory hist : engine.getTriggerRouterService().getActiveTriggerHistories()) {
for (Node node : nodes) {
if ((catalog == null || catalog.equals(hist.getSourceCatalogName())) && (schema == null || schema.equals(hist.getSourceSchemaName()))) {
getSymmetricEngine().getDataService().sendSchema(node.getNodeId(), hist.getSourceCatalogName(), hist.getSourceSchemaName(), hist.getSourceTableName(), false);
}
}
}
} else {
for (String tableName : args) {
for (Node node : nodes) {
getSymmetricEngine().getDataService().sendSchema(node.getNodeId(), catalog, schema, tableName, false);
}
}
}
}
Aggregations