diff --git a/symmetric-assemble/src/asciidoc/configuration/file-routing.ad b/symmetric-assemble/src/asciidoc/configuration/file-routing.ad index 2e9415c091..1c23fe6e8f 100644 --- a/symmetric-assemble/src/asciidoc/configuration/file-routing.ad +++ b/symmetric-assemble/src/asciidoc/configuration/file-routing.ad @@ -86,6 +86,12 @@ Conflict Strategy:: The strategy to employ when a file has been modified at both |manual|If a conflict occurs the batch will be put in ER (error) status and require manual intervention to resolve the issue. +ifdef::pro[] +|newer_wins|If a conflict occurs, a comparison between last modified date of the file incoming and the file currently on disk will be compared and the newest will win. This assumes the system clocks on each machine are in sync to perform an accurate comparison. + +|older_wins|If a conflict occurs, a comparison between last modified date of the file incoming and the file currently on disk will be compared and the oldest will win. This assumes the system clocks on each machine are in sync to perform an accurate comparison. +endif::pro[] + |=== ifdef::pro[] diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/file/BeanShellFileSyncZipScript.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/file/BeanShellFileSyncZipScript.java index 86944aff19..5dba8cf330 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/file/BeanShellFileSyncZipScript.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/file/BeanShellFileSyncZipScript.java @@ -30,9 +30,16 @@ import org.jumpmind.symmetric.model.FileSnapshot.LastEventType; import org.jumpmind.symmetric.model.FileTrigger; import org.jumpmind.symmetric.model.FileTriggerRouter; +import org.jumpmind.symmetric.service.IExtensionService; public class BeanShellFileSyncZipScript extends FileSyncZipScript { + protected IExtensionService extensionService; + + public BeanShellFileSyncZipScript(IExtensionService extensionService) { + this.extensionService = extensionService; + } + @Override public String getScriptFileName(Batch batch) { return "sync.bsh"; @@ -118,7 +125,15 @@ public void buildScriptFileSnapshot(Batch batch, FileSnapshot snapshot, FileTrig } command.append(" }\n"); command.append(" }\n"); - } + } else { + if (triggerRouter.getConflictStrategyString() != null) { + for (IFileConflictResolver resolver : extensionService.getExtensionPointList(IFileConflictResolver.class)) { + if (triggerRouter.getConflictStrategyString().equals(resolver.getName())) { + command.append(resolver.getResolveCommand(snapshot)); + } + } + } + } command.append(" if (processFile) {\n"); command.append(" if (sourceFile.isDirectory()) {\n"); diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/file/FileSyncZipDataWriter.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/file/FileSyncZipDataWriter.java index 70f792af71..01dac544db 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/file/FileSyncZipDataWriter.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/file/FileSyncZipDataWriter.java @@ -48,6 +48,7 @@ import org.jumpmind.symmetric.model.FileTrigger; import org.jumpmind.symmetric.model.FileTriggerRouter; import org.jumpmind.symmetric.model.Node; +import org.jumpmind.symmetric.service.IExtensionService; import org.jumpmind.symmetric.service.IFileSyncService; import org.jumpmind.symmetric.service.INodeService; import org.jumpmind.util.Statistics; @@ -69,13 +70,15 @@ public class FileSyncZipDataWriter implements IDataWriter { protected List snapshotEvents; protected DataContext context; protected INodeService nodeService; - + protected IExtensionService extensionService; + public FileSyncZipDataWriter(long maxBytesToSync, IFileSyncService fileSyncService, - INodeService nodeService, IStagedResource stagedResource) { + INodeService nodeService, IStagedResource stagedResource, IExtensionService extensionService) { this.maxBytesToSync = maxBytesToSync; this.fileSyncService = fileSyncService; this.stagedResource = stagedResource; this.nodeService = nodeService; + this.extensionService = extensionService; } public void open(DataContext context) { @@ -290,7 +293,7 @@ protected FileSyncZipScript createFileSyncZipScript(String targetNodeId) { if (isCClient(targetNodeId)) { return new BashFileSyncZipScript(); } else { - return new BeanShellFileSyncZipScript(); + return new BeanShellFileSyncZipScript(extensionService); } } diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/file/IFileConflictResolver.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/file/IFileConflictResolver.java new file mode 100644 index 0000000000..bccf556975 --- /dev/null +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/file/IFileConflictResolver.java @@ -0,0 +1,11 @@ +package org.jumpmind.symmetric.file; + +import org.jumpmind.extension.IExtensionPoint; +import org.jumpmind.symmetric.model.FileSnapshot; + +public interface IFileConflictResolver extends IExtensionPoint { + + public String getName(); + + public String getResolveCommand(FileSnapshot snapshot); +} diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/model/FileTriggerRouter.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/model/FileTriggerRouter.java index d7db384613..a2e6e10cd8 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/model/FileTriggerRouter.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/model/FileTriggerRouter.java @@ -39,6 +39,8 @@ public class FileTriggerRouter implements Serializable { private FileConflictStrategy conflictStrategy = FileConflictStrategy.SOURCE_WINS; + private String conflictStrategyString; + private Date createTime = new Date(); private String lastUpdateBy; @@ -125,6 +127,14 @@ public void setLastUpdateTime(Date lastUpdateTime) { this.lastUpdateTime = lastUpdateTime; } + public String getConflictStrategyString() { + return conflictStrategyString; + } + + public void setConflictStrategyString(String conflictStrategyString) { + this.conflictStrategyString = conflictStrategyString; + } + @Override public int hashCode() { final int prime = 31; diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/FileSyncExtractorService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/FileSyncExtractorService.java index 740948e765..a723a108e8 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/FileSyncExtractorService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/FileSyncExtractorService.java @@ -41,6 +41,7 @@ import org.jumpmind.symmetric.model.RemoteNodeStatuses; import org.jumpmind.symmetric.model.Trigger; import org.jumpmind.symmetric.service.IConfigurationService; +import org.jumpmind.symmetric.service.IExtensionService; import org.jumpmind.symmetric.service.IFileSyncService; import org.jumpmind.symmetric.service.INodeCommunicationService; import org.jumpmind.symmetric.service.INodeService; @@ -54,7 +55,8 @@ public class FileSyncExtractorService extends DataExtractorService { private IConfigurationService configurationService; private INodeCommunicationService nodeCommunicationService; private ITriggerRouterService triggerRouterService; - + private IExtensionService extensionService; + public FileSyncExtractorService(ISymmetricEngine engine) { super(engine); this.fileSyncService = engine.getFileSyncService(); @@ -63,6 +65,7 @@ public FileSyncExtractorService(ISymmetricEngine engine) { this.configurationService = engine.getConfigurationService(); this.nodeCommunicationService = engine.getNodeCommunicationService(); this.triggerRouterService = engine.getTriggerRouterService(); + this.extensionService = engine.getExtensionService(); } @Override @@ -125,7 +128,7 @@ protected IDataWriter buildWriter(long memoryThresholdInBytes) { .getLong(ParameterConstants.TRANSPORT_MAX_BYTES_TO_SYNC); FileSyncZipDataWriter fileSyncWriter = new FileSyncZipDataWriter(maxBytesToSync, fileSyncService, - nodeService, stagedResource) { + nodeService, stagedResource, extensionService) { @Override public void close() { super.finish(); diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/FileSyncService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/FileSyncService.java index 3ae27b5423..bf9bb5027a 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/FileSyncService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/FileSyncService.java @@ -393,7 +393,7 @@ public void saveFileTriggerRouter(FileTriggerRouter fileTriggerRouter) { new Object[] { fileTriggerRouter.isEnabled() ? 1 : 0, fileTriggerRouter.isInitialLoadEnabled() ? 1 : 0, fileTriggerRouter.getTargetBaseDir(), - fileTriggerRouter.getConflictStrategy().name(), + fileTriggerRouter.getConflictStrategyString(), fileTriggerRouter.getLastUpdateBy(), fileTriggerRouter.getLastUpdateTime(), fileTriggerRouter.getFileTrigger().getTriggerId(), fileTriggerRouter.getRouter().getRouterId() }, new int[] { Types.SMALLINT, @@ -405,7 +405,7 @@ public void saveFileTriggerRouter(FileTriggerRouter fileTriggerRouter) { new Object[] { fileTriggerRouter.isEnabled() ? 1 : 0, fileTriggerRouter.isInitialLoadEnabled() ? 1 : 0, fileTriggerRouter.getTargetBaseDir(), - fileTriggerRouter.getConflictStrategy().name(), + fileTriggerRouter.getConflictStrategyString(), fileTriggerRouter.getCreateTime(), fileTriggerRouter.getLastUpdateBy(), fileTriggerRouter.getLastUpdateTime(), fileTriggerRouter.getFileTrigger().getTriggerId(), @@ -588,7 +588,7 @@ public List sendFiles(ProcessInfo processInfo, Node targetNode, Constants.STAGING_CATEGORY_OUTGOING, processInfo.getSourceNodeId(), targetNode.getNodeId(), "filesync.zip"); dataWriter = new FileSyncZipDataWriter(maxBytesToSync, this, - engine.getNodeService(), stagedResource); + engine.getNodeService(), stagedResource, engine.getExtensionService()); } log.debug("Extracting batch {} for filesync.", currentBatch.getNodeBatchId()); @@ -1223,8 +1223,14 @@ public FileTriggerRouter mapRow(Row rs) { String triggerId = rs.getString("trigger_id"); FileTrigger fileTrigger = getFileTrigger(triggerId); fileTriggerRouter.setFileTrigger(fileTrigger); - fileTriggerRouter.setConflictStrategy(FileConflictStrategy.valueOf(rs.getString( + try { + fileTriggerRouter.setConflictStrategy(FileConflictStrategy.valueOf(rs.getString( "conflict_strategy").toUpperCase())); + } + catch (Exception e) { + } + fileTriggerRouter.setConflictStrategyString(rs.getString( + "conflict_strategy").toUpperCase()); fileTriggerRouter.setCreateTime(rs.getDateTime("create_time")); fileTriggerRouter.setLastUpdateBy(rs.getString("last_update_by")); fileTriggerRouter.setLastUpdateTime(rs.getDateTime("last_update_time"));