package network.thunder.core.communication.processor.implementations.sync; import network.thunder.core.communication.Message; import network.thunder.core.communication.objects.messages.MessageExecutor; import network.thunder.core.communication.objects.messages.impl.message.gossip.objects.P2PDataObject; import network.thunder.core.communication.objects.messages.impl.message.sync.SyncGetMessage; import network.thunder.core.communication.objects.messages.impl.message.sync.SyncSendMessage; import network.thunder.core.communication.objects.messages.impl.results.SyncSuccessResult; import network.thunder.core.communication.objects.messages.interfaces.factories.ContextFactory; import network.thunder.core.communication.objects.messages.interfaces.factories.SyncMessageFactory; import network.thunder.core.communication.objects.messages.interfaces.helper.LNEventHelper; import network.thunder.core.communication.objects.messages.interfaces.message.sync.Sync; import network.thunder.core.communication.processor.ChannelIntent; import network.thunder.core.communication.processor.interfaces.SyncProcessor; import network.thunder.core.mesh.NodeClient; import java.util.List; /** * Created by matsjerratsch on 30/11/2015. */ public class SyncProcessorImpl extends SyncProcessor { SyncMessageFactory messageFactory; SynchronizationHelper syncStructure; LNEventHelper eventHelper; NodeClient node; MessageExecutor messageExecutor; int lastIndex; public SyncProcessorImpl (ContextFactory contextFactory, NodeClient node) { this.messageFactory = contextFactory.getSyncMessageFactory(); this.syncStructure = contextFactory.getSyncHelper(); this.eventHelper = contextFactory.getEventHelper(); this.node = node; } @Override public void onLayerActive (MessageExecutor messageExecutor) { this.messageExecutor = messageExecutor; if (shouldSync()) { startSyncing(); } else { syncComplete(); } } @Override public void onInboundMessage (Message message) { if (message instanceof SyncSendMessage) { processSyncSendMessage(message); } else if (message instanceof SyncGetMessage) { processSyncGetMessage(message); } } @Override public boolean consumesInboundMessage (Object object) { return (object instanceof Sync); } @Override public boolean consumesOutboundMessage (Object object) { return false; } public boolean shouldSync () { return !node.isServer && !synchronizationComplete(); } private void startSyncing () { sendGetNextSyncData(); } private void syncComplete () { if (node.intent == ChannelIntent.GET_SYNC_DATA) { node.resultCallback.execute(new SyncSuccessResult()); messageExecutor.closeConnection(); } else { messageExecutor.sendNextLayerActive(); } } private void processSyncSendMessage (Message message) { SyncSendMessage syncMessage = (SyncSendMessage) message; syncStructure.newFragment(lastIndex, syncMessage.getDataList()); eventHelper.onP2PDataReceived(); //TODO cancel the connection with some other condition as well.. if (!syncStructure.fullySynchronized()) { sendGetNextSyncData(); } else { syncComplete(); } } private void processSyncGetMessage (Message message) { SyncGetMessage syncMessage = (SyncGetMessage) message; sendSyncData(syncMessage.fragmentIndex); } private void sendGetNextSyncData () { lastIndex = syncStructure.getNextFragmentIndexToSynchronize(); SyncGetMessage getMessage = messageFactory.getSyncGetMessage(lastIndex); messageExecutor.sendMessageUpwards(getMessage); } private void sendSyncData (int fragmentIndex) { List<P2PDataObject> dataObjects = syncStructure.getFragment(fragmentIndex); Message syncSendMessage = messageFactory.getSyncSendMessage(dataObjects); messageExecutor.sendMessageUpwards(syncSendMessage); } private boolean synchronizationComplete () { return syncStructure.fullySynchronized(); } }