/*
* Syncany, www.syncany.org
* Copyright (C) 2011-2015 Philipp C. Heckel <philipp.heckel@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.syncany.operations.daemon;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.simpleframework.xml.core.Persister;
import org.syncany.config.Config;
import org.syncany.config.ConfigException;
import org.syncany.config.LocalEventBus;
import org.syncany.config.to.PortTO;
import org.syncany.operations.daemon.messages.AlreadySyncingResponse;
import org.syncany.operations.daemon.messages.BadRequestResponse;
import org.syncany.operations.daemon.messages.api.FolderRequest;
import org.syncany.operations.daemon.messages.api.FolderRequestHandler;
import org.syncany.operations.daemon.messages.api.Response;
import org.syncany.operations.watch.WatchOperation;
import org.syncany.operations.watch.WatchOperationOptions;
import org.syncany.operations.watch.WatchOperationResult;
import com.google.common.eventbus.Subscribe;
/**
* The watch operation thread runs a {@link WatchOperation} in a thread. The
* underlying thred can be started using the {@link #start()} method, and stopped
* gracefully using {@link #stop()}.
*
* @author Philipp C. Heckel <philipp.heckel@gmail.com>
*/
public class WatchRunner {
private static final Logger logger = Logger.getLogger(WatchRunner.class.getSimpleName());
private Config config;
private PortTO portTO;
private Thread watchThread;
private WatchOperation watchOperation;
private WatchOperationResult watchOperationResult;
private LocalEventBus eventBus;
public WatchRunner(Config config, WatchOperationOptions watchOperationOptions, PortTO portTO) throws ConfigException {
this.config = config;
this.portTO = portTO;
this.watchOperation = new WatchOperation(config, watchOperationOptions);
this.eventBus = LocalEventBus.getInstance();
this.eventBus.register(this);
}
public void start() {
watchThread = new Thread(new Runnable() {
@Override
public void run() {
try {
logger.log(Level.INFO, "STARTING watch at" + config.getLocalDir());
watchOperationResult = null;
// Write port to portFile
File portFile = config.getPortFile();
portFile.createNewFile();
portFile.deleteOnExit();
new Persister().write(portTO, portFile);
// Start operation (blocks!)
watchOperationResult = watchOperation.execute();
logger.log(Level.INFO, "STOPPED watch at " + config.getLocalDir());
}
catch (Exception e) {
logger.log(Level.SEVERE, "ERROR while running watch at " + config.getLocalDir(), e);
}
}
}, "WR/" + config.getLocalDir().getName());
watchThread.start();
}
public void stop() {
watchOperation.stop();
config.getPortFile().delete();
watchThread = null;
}
public boolean hasStopped() {
return watchOperationResult != null;
}
public boolean isSyncRunning() {
return watchOperation.isSyncRunning();
}
@Subscribe
public void onRequestReceived(FolderRequest folderRequest) {
File requestRootFolder = new File(folderRequest.getRoot());
boolean localDirMatches = requestRootFolder.equals(config.getLocalDir());
if (localDirMatches) {
logger.log(Level.INFO, "Received " + folderRequest);
try {
if (!watchOperation.isSyncRunning() && !watchOperation.isSyncRequested()) {
watchOperation.pause();
FolderRequestHandler handler = FolderRequestHandler.createFolderRequestHandler(folderRequest, config);
Response response = handler.handleRequest(folderRequest);
if (response != null) {
eventBus.post(response);
}
watchOperation.resume();
}
else {
logger.log(Level.WARNING, "FolderRequest discarded : ", folderRequest);
eventBus.post(new AlreadySyncingResponse(folderRequest.getId(), "FolderRequest discarded."));
}
}
catch (Exception e) {
logger.log(Level.FINE, "Failed to process request", e);
eventBus.post(new BadRequestResponse(folderRequest.getId(), "Invalid request."));
}
}
}
}