/** * License Agreement for OpenSearchServer * <p> * Copyright (C) 2010-2012 Emmanuel Keller / Jaeksoft * <p> * http://www.open-search-server.com * <p> * This file is part of OpenSearchServer. * <p> * OpenSearchServer 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. * <p> * OpenSearchServer 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. * <p> * You should have received a copy of the GNU General Public License * along with OpenSearchServer. * If not, see <http://www.gnu.org/licenses/>. **/ package com.jaeksoft.searchlib.replication; import com.jaeksoft.searchlib.Client; import com.jaeksoft.searchlib.SearchLibException; import com.jaeksoft.searchlib.process.ThreadAbstract; import com.jaeksoft.searchlib.scheduler.TaskLog; import com.jaeksoft.searchlib.util.*; import com.jaeksoft.searchlib.web.PushServlet; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class ReplicationThread extends ThreadAbstract<ReplicationThread> implements RecursiveDirectoryBrowser.CallBack { final private ReadWriteLock rwl = new ReadWriteLock(); private volatile Client client; private volatile double totalSize; private volatile int filesSent; private volatile long bytesSent; private volatile double checkedSize; private volatile InfoCallback infoCallback; private volatile List<File> filesNotPushed; private volatile List<File> dirsNotPushed; private volatile File sourceDirectory; private final ReplicationType replicationType; private final long initVersion; protected ReplicationThread(Client client, ReplicationMaster replicationMaster, ReplicationItem replicationItem, InfoCallback infoCallback) throws SearchLibException { super(client, replicationMaster, replicationItem, infoCallback); this.sourceDirectory = replicationItem.getDirectory(client); this.replicationType = replicationItem.getReplicationType(); this.client = client; initVersion = client.getIndex().getVersion(); totalSize = 0; filesSent = 0; checkedSize = 0; filesNotPushed = null; dirsNotPushed = null; this.infoCallback = infoCallback; } public int getProgress() { rwl.r.lock(); try { if (checkedSize == 0 || totalSize == 0) return 0; int p = (int) ((checkedSize / totalSize) * 100); return p; } finally { rwl.r.unlock(); } } private void incFilesSent(long bytesSent) { rwl.w.lock(); try { filesSent++; this.bytesSent += bytesSent; } finally { rwl.w.unlock(); } } public ReplicationItem getReplicationItem() { return (ReplicationItem) getThreadItem(); } private void initNotPushedList() { filesNotPushed = new ArrayList<>(0); dirsNotPushed = new ArrayList<>(0); getReplicationItem().getReplicationType().addNotPushedPath(sourceDirectory, filesNotPushed, dirsNotPushed); } @Override public void runner() throws Exception { setInfo("Running"); if (replicationType == ReplicationType.MAIN_DATA_COPY) throw new Exception("Not yet implemented"); else { initNotPushedList(); client.push(this); } } @Override public void release() { Exception e = getException(); if (e != null) setInfo("Error: " + e.getMessage() != null ? e.getMessage() : e.toString()); else if (isAborted()) setInfo("Aborted"); else setInfo("Completed"); } public void push() throws SearchLibException { ReplicationItem replicationItem = getReplicationItem(); try { setTotalSize(new LastModifiedAndSize(sourceDirectory, false).getSize()); addCheckedSize(sourceDirectory.length()); PushServlet.call_init(getReplicationItem()); new RecursiveDirectoryBrowser(sourceDirectory, this); checkVersion(); switch (replicationItem.getReplicationType().getFinalMode()) { case MERGE: PushServlet.call_merge(replicationItem); break; case SWITCH: PushServlet.call_switch(replicationItem); break; } } catch (Exception e) { PushServlet.call_abort(replicationItem); if (e instanceof SearchLibException) throw (SearchLibException) e; else throw new SearchLibException(e); } } private void setTotalSize(long size) { rwl.w.lock(); try { totalSize = size; } finally { rwl.w.unlock(); } } private void addCheckedSize(long length) { rwl.w.lock(); try { checkedSize += length; } finally { rwl.w.unlock(); } } final private boolean checkFilePush(final File file) throws IOException { if (!checkDirPush(file)) return false; for (File fileNotPushed : filesNotPushed) if (file.equals(fileNotPushed)) return false; return true; } final private boolean checkDirPush(final File dir) throws IOException { for (File dirNotPushed : dirsNotPushed) { if (dir.equals(dirNotPushed)) return false; if (FileUtils.isSubDirectory(dirNotPushed, dir)) return false; } return true; } public String getStatInfo() { rwl.r.lock(); try { return getProgress() + "% completed - " + filesSent + " file(s) sent - " + FileUtils .byteCountToDisplaySize(bytesSent) + " sent"; } finally { rwl.r.unlock(); } } private void checkVersion() throws SearchLibException { if (initVersion != client.getIndex().getVersion()) throw new SearchLibException("Replication process aborted. The index has changed."); } @Override public void file(File file) throws SearchLibException { try { checkVersion(); ReplicationItem replicationItem = getReplicationItem(); long length = file.length(); if (file.isFile()) { if (checkFilePush(file)) { if (!PushServlet.call_file_exist(client, replicationItem, file)) { PushServlet.call_file(client, replicationItem, file); incFilesSent(length); } } } else { if (replicationType.isNotPushedFolder(file)) dirsNotPushed.add(file); if (checkDirPush(file)) PushServlet.call_directory(client, replicationItem, file); } addCheckedSize(length); if (infoCallback != null) { infoCallback.setInfo(getStatInfo()); if (infoCallback instanceof TaskLog) if (((TaskLog) infoCallback).isAbortRequested()) throw new SearchLibException.AbortException(); } } catch (IllegalStateException e) { throw new SearchLibException(e); } catch (IOException e) { throw new SearchLibException(e); } } }