package org.peerbox.forcesync;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hive2hive.core.exceptions.NoPeerConnectionException;
import org.hive2hive.core.exceptions.NoSessionException;
import org.hive2hive.core.processes.files.list.FileNode;
import org.hive2hive.processframework.exceptions.InvalidProcessStateException;
import org.hive2hive.processframework.exceptions.ProcessExecutionException;
import org.peerbox.app.ClientContext;
import org.peerbox.app.manager.file.FileInfo;
import org.peerbox.app.manager.file.IFileManager;
import org.peerbox.watchservice.FileEventManager;
import org.peerbox.watchservice.PathUtils;
import org.peerbox.watchservice.filetree.FileTreeInitializer;
import org.peerbox.watchservice.filetree.composite.FileComponent;
import org.peerbox.watchservice.filetree.persistency.LocalFileDao;
import org.peerbox.watchservice.filetree.persistency.RemoteFileDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ForceSync {
private static final Logger logger = LoggerFactory.getLogger(ForceSync.class);
private ClientContext context;
private FileEventManager fileEventManager;
private IFileManager fileManager;
private LocalFileDao localFileDao;
private RemoteFileDao remoteFileDao;
private Path topLevel;
public ForceSync(ClientContext currentClientContext) {
this.context = currentClientContext;
fileEventManager = context.getFileEventManager();
fileManager = context.getFileManager();
localFileDao = context.getLocalFileDao();
remoteFileDao = context.getRemoteFileDao();
}
public void forceSync(Path topLevel) {
this.topLevel = topLevel;
try {
logger.trace("Start forced synchronization on {}", topLevel);
FileTreeInitializer fileTreeInitializer = new FileTreeInitializer(context);
fileTreeInitializer.initialize(topLevel);
Set<Path> pendingEvents = fileEventManager.getPendingEvents();
if(pendingEvents.size() > 0){
logger.trace("New events happened during force sync. Redo.");
pendingEvents.clear();
Path newTopLevel = null;
for(Path next : pendingEvents){
if(newTopLevel == null){
newTopLevel = next;
} else {
newTopLevel = PathUtils.getCommonPath(newTopLevel, next);
}
}
forceSync(newTopLevel);
// Path topLevel = pendingEvents.
// for(Path path : pendingEvents){
// if(path.startsWith(other))
// }
} else {
fileEventManager.setCleanupRunning(false);
try {
synchronize(topLevel);
} catch(Exception e) {
logger.warn("Could not complete forced sync due to exception.", e);
}
context.getActionExecutor().setForceSyncRunning(false);
}
} catch(Exception e) {
e.printStackTrace();
}
}
private void synchronize(Path topLevel) throws Exception {
// local view
Map<Path, FileInfo> localDisk = createLocalViewDisk();
Map<Path, FileInfo> localDb = createLocalViewDb();
// remote view
Map<Path, FileInfo> remoteNetwork = createRemoteViewNetwork();
Map<Path, FileInfo> remoteDb = createRemoteViewDb();
ListSync listSync = new ListSync(fileEventManager, topLevel);
listSync.sync(localDisk, localDb, remoteNetwork, remoteDb);
}
private Map<Path, FileInfo> createLocalViewDisk() throws IOException {
Map<Path, FileInfo> local = new HashMap<>();
Files.walkFileTree(topLevel, new LocalFileWalker(local));
return local;
}
private Map<Path, FileInfo> createLocalViewDb() {
Map<Path, FileInfo> localDb = new HashMap<>();
List<FileComponent> fileList = localFileDao.getAllFiles();
for (FileComponent c : fileList) {
FileInfo a = new FileInfo(c);
localDb.put(a.getPath(), a);
}
return localDb;
}
private Map<Path, FileInfo> createRemoteViewNetwork()
throws InvalidProcessStateException, ProcessExecutionException, NoSessionException, NoPeerConnectionException {
Map<Path, FileInfo> remoteNow = new HashMap<>();
FileNode root = fileManager.listFiles().execute();
List<FileNode> nodes = FileNode.getNodeList(root, true, true);
for (FileNode node : nodes) {
FileInfo a = new FileInfo(node);
remoteNow.put(a.getPath(), a);
}
return remoteNow;
}
private Map<Path, FileInfo> createRemoteViewDb() {
Map<Path, FileInfo> remoteDb = new HashMap<>();
List<FileInfo> fileList = remoteFileDao.getAllFileNodeAttributes();
for (FileInfo a : fileList) {
remoteDb.put(a.getPath(), a);
}
return remoteDb;
}
}