use of org.jumpmind.symmetric.model.NodeGroupLink in project symmetric-ds by JumpMind.
the class SymmetricEngineHolder method install.
public ISymmetricEngine install(Properties passedInProperties) throws Exception {
TypedProperties properties = new TypedProperties(passedInProperties);
String password = properties.getProperty(BasicDataSourcePropertyConstants.DB_POOL_PASSWORD);
if (StringUtils.isNotBlank(password) && !password.startsWith(SecurityConstants.PREFIX_ENC)) {
try {
ISecurityService service = SecurityServiceFactory.create(SecurityServiceType.CLIENT, properties);
properties.setProperty(BasicDataSourcePropertyConstants.DB_POOL_PASSWORD, SecurityConstants.PREFIX_ENC + service.encrypt(password));
} catch (Exception ex) {
log.warn("Could not encrypt password", ex);
}
}
String engineName = validateRequiredProperties(properties);
passedInProperties.setProperty(ParameterConstants.ENGINE_NAME, engineName);
if (engines.get(engineName) != null) {
try {
engines.get(engineName).stop();
} catch (Exception e) {
log.error("", e);
}
engines.remove(engineName);
}
File enginesDir = new File(AbstractCommandLauncher.getEnginesDir());
File symmetricProperties = new File(enginesDir, engineName + ".properties");
FileOutputStream fileOs = null;
try {
fileOs = new FileOutputStream(symmetricProperties);
properties.store(fileOs, "Updated by SymmetricDS Pro");
} catch (IOException ex) {
throw new RuntimeException("Failed to write symmetric.properties to engine directory", ex);
} finally {
IOUtils.closeQuietly(fileOs);
}
ISymmetricEngine engine = null;
try {
String registrationUrl = properties.getProperty(ParameterConstants.REGISTRATION_URL);
if (StringUtils.isNotBlank(registrationUrl)) {
Collection<ServerSymmetricEngine> all = getEngines().values();
for (ISymmetricEngine currentEngine : all) {
if (currentEngine.getParameterService().getSyncUrl().equals(registrationUrl)) {
String serverNodeGroupId = currentEngine.getParameterService().getNodeGroupId();
String clientNodeGroupId = properties.getProperty(ParameterConstants.NODE_GROUP_ID);
String externalId = properties.getProperty(ParameterConstants.EXTERNAL_ID);
IConfigurationService configurationService = currentEngine.getConfigurationService();
ITriggerRouterService triggerRouterService = currentEngine.getTriggerRouterService();
List<NodeGroup> groups = configurationService.getNodeGroups();
boolean foundGroup = false;
for (NodeGroup nodeGroup : groups) {
if (nodeGroup.getNodeGroupId().equals(clientNodeGroupId)) {
foundGroup = true;
}
}
if (!foundGroup) {
configurationService.saveNodeGroup(new NodeGroup(clientNodeGroupId));
}
boolean foundLink = false;
List<NodeGroupLink> links = configurationService.getNodeGroupLinksFor(serverNodeGroupId, false);
for (NodeGroupLink nodeGroupLink : links) {
if (nodeGroupLink.getTargetNodeGroupId().equals(clientNodeGroupId)) {
foundLink = true;
}
}
if (!foundLink) {
configurationService.saveNodeGroupLink(new NodeGroupLink(serverNodeGroupId, clientNodeGroupId, NodeGroupLinkAction.W));
triggerRouterService.syncTriggers();
}
IRegistrationService registrationService = currentEngine.getRegistrationService();
if (!registrationService.isAutoRegistration() && !registrationService.isRegistrationOpen(clientNodeGroupId, externalId)) {
Node node = new Node(properties);
registrationService.openRegistration(node);
}
}
}
}
engine = create(symmetricProperties.getAbsolutePath());
if (engine != null) {
engineCount++;
engine.start();
} else {
FileUtils.deleteQuietly(symmetricProperties);
log.warn("The engine could not be created. It will not be started");
}
return engine;
} catch (RuntimeException ex) {
if (engine != null) {
engine.destroy();
}
FileUtils.deleteQuietly(symmetricProperties);
throw ex;
}
}
use of org.jumpmind.symmetric.model.NodeGroupLink in project symmetric-ds by JumpMind.
the class RegistrationService method processRegistration.
protected Node processRegistration(Node nodePriorToRegistration, String remoteHost, String remoteAddress, boolean isRequestedRegistration, String deploymentType) throws IOException {
Node processedNode = new Node();
processedNode.setSyncEnabled(false);
Node identity = nodeService.findIdentity();
if (identity == null) {
RegistrationRequest req = new RegistrationRequest(nodePriorToRegistration, RegistrationStatus.ER, remoteHost, remoteAddress);
req.setErrorMessage("Cannot register a client node until this node is registered");
saveRegistrationRequest(req);
log.warn(req.getErrorMessage());
return processedNode;
}
try {
if (!nodeService.isRegistrationServer()) {
/*
* registration is not allowed until this node has an identity
* and an initial load
*/
NodeSecurity security = nodeService.findNodeSecurity(identity.getNodeId());
if (security == null || security.getInitialLoadTime() == null) {
RegistrationRequest req = new RegistrationRequest(nodePriorToRegistration, RegistrationStatus.ER, remoteHost, remoteAddress);
req.setErrorMessage("Cannot register a client node until this node has an initial load (ie. node_security.initial_load_time is a non null value)");
saveRegistrationRequest(req);
log.warn(req.getErrorMessage());
return processedNode;
}
}
String redirectUrl = getRedirectionUrlFor(nodePriorToRegistration.getExternalId());
if (redirectUrl != null) {
log.info("Redirecting {} to {} for registration.", nodePriorToRegistration.getExternalId(), redirectUrl);
saveRegistrationRequest(new RegistrationRequest(nodePriorToRegistration, RegistrationStatus.RR, remoteHost, remoteAddress));
throw new RegistrationRedirectException(redirectUrl);
}
/*
* Check to see if there is a link that exists to service the node
* that is requesting registration
*/
NodeGroupLink link = configurationService.getNodeGroupLinkFor(identity.getNodeGroupId(), nodePriorToRegistration.getNodeGroupId(), false);
if (link == null && parameterService.is(ParameterConstants.REGISTRATION_REQUIRE_NODE_GROUP_LINK, true)) {
RegistrationRequest req = new RegistrationRequest(nodePriorToRegistration, RegistrationStatus.ER, remoteHost, remoteAddress);
req.setErrorMessage(String.format("Cannot register a client node unless a node group link exists so the registering node can receive configuration updates. Please add a group link where the source group id is %s and the target group id is %s", identity.getNodeGroupId(), nodePriorToRegistration.getNodeGroupId()));
saveRegistrationRequest(req);
log.warn(req.getErrorMessage());
return processedNode;
}
String nodeId = StringUtils.isBlank(nodePriorToRegistration.getNodeId()) ? extensionService.getExtensionPoint(INodeIdCreator.class).selectNodeId(nodePriorToRegistration, remoteHost, remoteAddress) : nodePriorToRegistration.getNodeId();
Node foundNode = nodeService.findNode(nodeId);
NodeSecurity security = nodeService.findNodeSecurity(nodeId);
if ((foundNode == null || security == null || !security.isRegistrationEnabled()) && parameterService.is(ParameterConstants.AUTO_REGISTER_ENABLED)) {
openRegistration(nodePriorToRegistration, remoteHost, remoteAddress);
nodeId = StringUtils.isBlank(nodePriorToRegistration.getNodeId()) ? extensionService.getExtensionPoint(INodeIdCreator.class).selectNodeId(nodePriorToRegistration, remoteHost, remoteAddress) : nodePriorToRegistration.getNodeId();
security = nodeService.findNodeSecurity(nodeId);
foundNode = nodeService.findNode(nodeId);
} else if (foundNode == null || security == null || !security.isRegistrationEnabled()) {
saveRegistrationRequest(new RegistrationRequest(nodePriorToRegistration, RegistrationStatus.RQ, remoteHost, remoteAddress));
return processedNode;
}
foundNode.setSyncEnabled(true);
if (Constants.DEPLOYMENT_TYPE_REST.equalsIgnoreCase(deploymentType)) {
foundNode.setSymmetricVersion(null);
foundNode.setDeploymentType(deploymentType);
}
foundNode.setSyncUrl(nodePriorToRegistration.getSyncUrl());
foundNode.setDatabaseType(nodePriorToRegistration.getDatabaseType());
foundNode.setDatabaseVersion(nodePriorToRegistration.getDatabaseVersion());
foundNode.setSymmetricVersion(nodePriorToRegistration.getSymmetricVersion());
nodeService.save(foundNode);
/**
* Only send automatic initial load once or if the client is really
* re-registering
*/
if ((security != null && security.getInitialLoadTime() == null) || isRequestedRegistration) {
if (parameterService.is(ParameterConstants.AUTO_RELOAD_ENABLED)) {
nodeService.setInitialLoadEnabled(nodeId, true, false, -1, "registration");
}
if (parameterService.is(ParameterConstants.AUTO_RELOAD_REVERSE_ENABLED)) {
nodeService.setReverseInitialLoadEnabled(nodeId, true, false, -1, "registration");
}
}
saveRegistrationRequest(new RegistrationRequest(foundNode, RegistrationStatus.OK, remoteHost, remoteAddress));
statisticManager.incrementNodesRegistered(1);
return foundNode;
} catch (RegistrationNotOpenException ex) {
if (StringUtils.isNotBlank(ex.getMessage())) {
log.warn("Registration not allowed for {} because {}", nodePriorToRegistration.toString(), ex.getMessage());
}
return processedNode;
}
}
use of org.jumpmind.symmetric.model.NodeGroupLink in project symmetric-ds by JumpMind.
the class RouterService method findAvailableNodes.
protected Set<Node> findAvailableNodes(TriggerRouter triggerRouter, ChannelRouterContext context) {
Set<Node> nodes = context.getAvailableNodes().get(triggerRouter);
if (nodes == null) {
nodes = new HashSet<Node>();
Router router = triggerRouter.getRouter();
NodeGroupLink link = engine.getConfigurationService().getNodeGroupLinkFor(router.getNodeGroupLink().getSourceNodeGroupId(), router.getNodeGroupLink().getTargetNodeGroupId(), false);
if (link != null) {
nodes.addAll(engine.getNodeService().findEnabledNodesFromNodeGroup(router.getNodeGroupLink().getTargetNodeGroupId()));
} else {
log.error("The router {} has no node group link configured from {} to {}", new Object[] { router.getRouterId(), router.getNodeGroupLink().getSourceNodeGroupId(), router.getNodeGroupLink().getTargetNodeGroupId() });
}
context.getAvailableNodes().put(triggerRouter, nodes);
}
return engine.getGroupletService().getTargetEnabled(triggerRouter, nodes);
}
use of org.jumpmind.symmetric.model.NodeGroupLink in project symmetric-ds by JumpMind.
the class RouterService method insertInitialLoadEvents.
/**
* If a load has been queued up by setting the initial load enabled or
* reverse initial load enabled flags, then the router service will insert
* the reload events. This process will not run at the same time sync
* triggers is running.
*/
protected void insertInitialLoadEvents() {
ProcessInfo processInfo = engine.getStatisticManager().newProcessInfo(new ProcessInfoKey(engine.getNodeService().findIdentityNodeId(), null, ProcessType.INSERT_LOAD_EVENTS));
processInfo.setStatus(ProcessInfo.Status.PROCESSING);
try {
INodeService nodeService = engine.getNodeService();
Node identity = nodeService.findIdentity();
if (identity != null) {
boolean isClusteringEnabled = parameterService.is(ParameterConstants.CLUSTER_LOCKING_ENABLED);
NodeSecurity identitySecurity = nodeService.findNodeSecurity(identity.getNodeId(), !isClusteringEnabled);
if (engine.getParameterService().isRegistrationServer() || (identitySecurity != null && !identitySecurity.isRegistrationEnabled() && identitySecurity.getRegistrationTime() != null)) {
List<NodeSecurity> nodeSecurities = findNodesThatAreReadyForInitialLoad();
if (nodeSecurities != null && nodeSecurities.size() > 0) {
gapDetector.setFullGapAnalysis(true);
boolean reverseLoadFirst = parameterService.is(ParameterConstants.INITIAL_LOAD_REVERSE_FIRST);
boolean isInitialLoadQueued = false;
for (NodeSecurity security : nodeSecurities) {
if (engine.getTriggerRouterService().getActiveTriggerHistories().size() > 0) {
boolean thisMySecurityRecord = security.getNodeId().equals(identity.getNodeId());
boolean reverseLoadQueued = security.isRevInitialLoadEnabled();
boolean initialLoadQueued = security.isInitialLoadEnabled();
boolean registered = security.getRegistrationTime() != null;
if (thisMySecurityRecord && reverseLoadQueued && (reverseLoadFirst || !initialLoadQueued)) {
sendReverseInitialLoad(processInfo);
} else if (!thisMySecurityRecord && registered && initialLoadQueued && (!reverseLoadFirst || !reverseLoadQueued)) {
long ts = System.currentTimeMillis();
engine.getDataService().insertReloadEvents(engine.getNodeService().findNode(security.getNodeId()), false, processInfo);
isInitialLoadQueued = true;
ts = System.currentTimeMillis() - ts;
if (ts > Constants.LONG_OPERATION_THRESHOLD) {
log.warn("Inserted reload events for node {} took longer than expected. It took {} ms", security.getNodeId(), ts);
} else {
log.info("Inserted reload events for node {} in {} ms", security.getNodeId(), ts);
}
}
} else {
List<NodeGroupLink> links = engine.getConfigurationService().getNodeGroupLinksFor(parameterService.getNodeGroupId(), false);
if (links == null || links.size() == 0) {
log.warn("Could not queue up a load for {} because a node group link is NOT configured over which a load could be delivered", security.getNodeId());
} else {
log.warn("Could not queue up a load for {} because sync triggers has not yet run", security.getNodeId());
if (!syncTriggersBeforeInitialLoadAttempted) {
syncTriggersBeforeInitialLoadAttempted = true;
engine.getTriggerRouterService().syncTriggers();
}
}
}
}
if (isInitialLoadQueued) {
gapDetector.setFullGapAnalysis(true);
}
}
processTableRequestLoads(identity, processInfo);
}
}
processInfo.setStatus(ProcessInfo.Status.OK);
} catch (Exception ex) {
processInfo.setStatus(ProcessInfo.Status.ERROR);
log.error("", ex);
}
}
use of org.jumpmind.symmetric.model.NodeGroupLink in project symmetric-ds by JumpMind.
the class ConfigurationChangedDataRouter method routeNodeTables.
protected void routeNodeTables(Set<String> nodeIds, Map<String, String> columnValues, NetworkedNode rootNetworkedNode, Node me, SimpleRouterContext routingContext, DataMetaData dataMetaData, Set<Node> possibleTargetNodes, boolean initialLoad) {
String nodeIdForRecordBeingRouted = columnValues.get("NODE_ID");
if (dataMetaData.getData().getDataEventType() == DataEventType.DELETE) {
String createAtNodeId = columnValues.get("CREATED_AT_NODE_ID");
for (Node nodeThatMayBeRoutedTo : possibleTargetNodes) {
if (!Constants.DEPLOYMENT_TYPE_REST.equals(nodeThatMayBeRoutedTo.getDeploymentType()) && !nodeIdForRecordBeingRouted.equals(nodeThatMayBeRoutedTo.getNodeId()) && !nodeThatMayBeRoutedTo.getNodeId().equals(createAtNodeId) && (nodeThatMayBeRoutedTo.getCreatedAtNodeId() == null || !nodeThatMayBeRoutedTo.getCreatedAtNodeId().equals(nodeIdForRecordBeingRouted))) {
nodeIds.add(nodeThatMayBeRoutedTo.getNodeId());
}
}
} else {
IConfigurationService configurationService = engine.getConfigurationService();
List<NodeGroupLink> nodeGroupLinks = getNodeGroupLinksFromContext(routingContext);
for (Node nodeThatMayBeRoutedTo : possibleTargetNodes) {
if (!Constants.DEPLOYMENT_TYPE_REST.equals(nodeThatMayBeRoutedTo.getDeploymentType()) && !nodeThatMayBeRoutedTo.requires13Compatiblity() && isLinked(nodeIdForRecordBeingRouted, nodeThatMayBeRoutedTo, rootNetworkedNode, me, nodeGroupLinks) && (!isSameNumberOfLinksAwayFromRoot(nodeThatMayBeRoutedTo, rootNetworkedNode, me) || configurationService.isMasterToMaster()) || (nodeThatMayBeRoutedTo.getNodeId().equals(me.getNodeId()) && initialLoad)) {
nodeIds.add(nodeThatMayBeRoutedTo.getNodeId());
}
}
if (!initialLoad && nodeIds != null) {
if (tableMatches(dataMetaData, TableConstants.SYM_NODE_SECURITY)) {
routeSymNodeSecurity(me, nodeIdForRecordBeingRouted, dataMetaData, nodeIds, columnValues);
}
/*
* Don't route insert events for a node to itself. They will be
* loaded during registration. If we route them, then an old
* state can override the correct state
*
* Don't send deletes to a node. A node should be responsible
* for deleting itself.
*/
if (dataMetaData.getData().getDataEventType() == DataEventType.INSERT) {
nodeIds.remove(nodeIdForRecordBeingRouted);
}
}
}
}
Aggregations