001: /*
002: * This file is part of DrFTPD, Distributed FTP Daemon.
003: *
004: * DrFTPD is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * DrFTPD is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with DrFTPD; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018: package org.drftpd.mirroring.archivetypes;
019:
020: import java.util.ArrayList;
021: import java.util.HashMap;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.Map;
025: import java.util.Properties;
026: import java.util.Map.Entry;
027:
028: import net.sf.drftpd.mirroring.Job;
029:
030: import org.apache.log4j.Logger;
031: import org.drftpd.PropertyHelper;
032: import org.drftpd.master.RemoteSlave;
033: import org.drftpd.mirroring.ArchiveType;
034: import org.drftpd.plugins.Archive;
035: import org.drftpd.remotefile.LinkedRemoteFileInterface;
036: import org.drftpd.sections.SectionInterface;
037:
038: /**
039: * Moves a "release" so that it resides only on the .numOfSlaves slaves with most files.
040: *
041: * @author zubov
042: * @version $Id: FinishReleaseOnSlaves.java 1398 2006-01-14 20:54:51Z zubov $
043: */
044: public class FinishReleaseOnSlaves extends ArchiveType {
045: private static final Logger logger = Logger
046: .getLogger(FinishReleaseOnSlaves.class);
047:
048: public FinishReleaseOnSlaves(Archive archive,
049: SectionInterface section, Properties props) {
050: super (archive, section, props);
051:
052: if (_numOfSlaves < 1) {
053: throw new IllegalArgumentException(
054: "numOfSlaves has to be > 0 for section "
055: + section.getName());
056: }
057: }
058:
059: public void findDestinationSlavesRecursive(
060: LinkedRemoteFileInterface lrf,
061: HashMap<RemoteSlave, SlaveCount> slaveMap) {
062: for (Iterator iter = lrf.getFiles().iterator(); iter.hasNext();) {
063: LinkedRemoteFileInterface file = null;
064: file = (LinkedRemoteFileInterface) iter.next();
065:
066: if (file.isDirectory()) {
067: findDestinationSlavesRecursive(file, slaveMap);
068: continue;
069: }
070:
071: for (Iterator iter2 = file.getSlaves().iterator(); iter2
072: .hasNext();) {
073: RemoteSlave rslave = (RemoteSlave) iter2.next();
074:
075: if (rslave.isMemberOf("incoming"))
076: continue;
077: SlaveCount i = (SlaveCount) slaveMap.get(rslave);
078: if (i == null) {
079: slaveMap.put(rslave, new SlaveCount());
080: } else {
081: i.addOne();
082: }
083: }
084: }
085: }
086:
087: public HashSet<RemoteSlave> findDestinationSlaves() {
088: HashMap<RemoteSlave, SlaveCount> slaveMap = new HashMap<RemoteSlave, SlaveCount>();
089: findDestinationSlavesRecursive(getDirectory(), slaveMap);
090:
091: HashSet<RemoteSlave> returnMe = new HashSet<RemoteSlave>();
092:
093: RemoteSlave minslave = null;
094: // the value of the lowest count in the ret HashSet
095: int mincount = 0;
096: Map.Entry<RemoteSlave, SlaveCount> entry;
097: Iterator<Map.Entry<RemoteSlave, SlaveCount>> iter = slaveMap
098: .entrySet().iterator();
099:
100: for (int i = 0; i < _numOfSlaves; i++) {
101: entry = iter.next();
102: returnMe.add(entry.getKey());
103: // overwrite mincount if count of added is lower.
104: if (minslave == null
105: || mincount > entry.getValue().getValue()) {
106: minslave = entry.getKey();
107: mincount = entry.getValue().getValue();
108: }
109: }
110:
111: while (iter.hasNext()) {
112: entry = iter.next();
113: // has higher value, replace
114: if (mincount < entry.getValue().getValue()) {
115: if (!returnMe.remove(minslave))
116: throw new RuntimeException();
117: minslave = entry.getKey();
118: mincount = Integer.MAX_VALUE;
119:
120: //calculated new minCount
121: //could have the returnMe sorted so that lowest value is always at bottom.
122: for (RemoteSlave rslave : returnMe) {
123: int count = slaveMap.get(rslave).getValue();
124: //if count is less than mincount, we have a new minslave
125: if (count < mincount) {
126: mincount = count;
127: minslave = rslave;
128: }
129: }
130: returnMe.add(entry.getKey());
131: }
132: }
133: return returnMe;
134: }
135:
136: protected boolean isArchivedDir(LinkedRemoteFileInterface lrf)
137: throws IncompleteDirectoryException, OfflineSlaveException {
138: return isArchivedToXSlaves(lrf, _numOfSlaves);
139: }
140:
141: public String toString() {
142: return "FinishReleaseOnSlaves[directory="
143: + getDirectory().getPath() + ",dest="
144: + outputSlaves(getRSlaves()) + "]";
145: }
146:
147: public class SlaveCount implements Comparable {
148: private int _value = 1;
149:
150: public SlaveCount() {
151: }
152:
153: public int compareTo(Object o) {
154: SlaveCount count = (SlaveCount) o;
155:
156: return getValue() - count.getValue();
157: }
158:
159: public void addOne() {
160: _value++;
161: }
162:
163: public int getValue() {
164: return _value;
165: }
166: }
167: }
|