001: /*
002: * This file is part of DrFTPD, Distributed FTP Daemon.
003: *
004: * DrFTPD is free software; you can redistribute it and/or modify it under the
005: * terms of the GNU General Public License as published by the Free Software
006: * Foundation; either version 2 of the License, or (at your option) any later
007: * version.
008: *
009: * DrFTPD is distributed in the hope that it will be useful, but WITHOUT ANY
010: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
011: * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
012: *
013: * You should have received a copy of the GNU General Public License along with
014: * DrFTPD; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
015: * Suite 330, Boston, MA 02111-1307 USA
016: */
017: package net.sf.drftpd.mirroring;
018:
019: import java.io.FileNotFoundException;
020: import java.util.ArrayList;
021: import java.util.Comparator;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.StringTokenizer;
026: import java.util.TreeSet;
027:
028: import net.sf.drftpd.ObjectNotFoundException;
029: import net.sf.drftpd.master.BaseFtpConnection;
030: import net.sf.drftpd.master.command.CommandManager;
031: import net.sf.drftpd.master.command.CommandManagerFactory;
032:
033: import org.drftpd.Bytes;
034: import org.drftpd.commands.CommandHandler;
035: import org.drftpd.commands.CommandHandlerFactory;
036: import org.drftpd.commands.ImproperUsageException;
037: import org.drftpd.commands.Reply;
038: import org.drftpd.commands.ReplyException;
039: import org.drftpd.commands.UnhandledCommandException;
040: import org.drftpd.master.RemoteSlave;
041: import org.drftpd.remotefile.LinkedRemoteFileInterface;
042: import org.tanesha.replacer.ReplacerEnvironment;
043:
044: /**
045: * CommandHandler plugin for viewing and manipulating the JobManager queue.
046: *
047: * @author mog
048: * @version $Id: JobManagerCommandHandler.java,v 1.19 2004/07/09 17:08:38 zubov
049: * Exp $
050: */
051: public class JobManagerCommandHandler implements CommandHandler,
052: CommandHandlerFactory {
053:
054: public JobManagerCommandHandler() {
055: super ();
056: }
057:
058: /**
059: * USAGE: <file><priority>[destslave ...]
060: *
061: * @param conn
062: * @return
063: * @throws ImproperUsageException
064: */
065: private Reply doADDJOB(BaseFtpConnection conn)
066: throws ImproperUsageException {
067:
068: if (!conn.getRequest().hasArgument()) {
069: throw new ImproperUsageException();
070: }
071:
072: StringTokenizer st = new StringTokenizer(conn.getRequest()
073: .getArgument());
074: LinkedRemoteFileInterface lrf;
075:
076: try {
077: lrf = conn.getCurrentDirectory().lookupFile(st.nextToken());
078: } catch (FileNotFoundException e) {
079: return new Reply(500, "File does not exist");
080: }
081: if (!lrf.isFile()) {
082: throw new ImproperUsageException(
083: "addjob does not handle directories or links");
084: }
085:
086: int priority;
087:
088: try {
089: priority = Integer.parseInt(st.nextToken());
090: } catch (NumberFormatException e) {
091: throw new ImproperUsageException();
092: }
093:
094: int timesToMirror;
095:
096: try {
097: timesToMirror = Integer.parseInt(st.nextToken());
098: } catch (NumberFormatException e) {
099: throw new ImproperUsageException();
100: }
101:
102: HashSet<RemoteSlave> destSlaves = new HashSet<RemoteSlave>();
103: Reply reply = new Reply(200);
104:
105: while (st.hasMoreTokens()) {
106: String slaveName = st.nextToken();
107: RemoteSlave rslave;
108:
109: try {
110: rslave = conn.getGlobalContext().getSlaveManager()
111: .getRemoteSlave(slaveName);
112: } catch (ObjectNotFoundException e1) {
113: reply
114: .addComment(slaveName
115: + "was not found, cannot add to destination slave list");
116:
117: continue;
118: }
119:
120: destSlaves.add(rslave);
121: }
122:
123: if (destSlaves.size() == 0) {
124: throw new ImproperUsageException();
125: }
126:
127: Job job = new Job(lrf, destSlaves, priority, timesToMirror);
128: conn.getGlobalContext().getJobManager().addJobToQueue(job);
129:
130: ReplacerEnvironment env = new ReplacerEnvironment();
131: env.add("job", job);
132: reply.addComment(conn.jprintf(JobManagerCommandHandler.class,
133: "addjob.success", env));
134:
135: return reply;
136: }
137:
138: private Reply doLISTJOBS(BaseFtpConnection conn) {
139:
140: Reply reply = new Reply(200);
141: ReplacerEnvironment env = new ReplacerEnvironment();
142: TreeSet<Job> treeSet = new TreeSet<Job>(
143: new JobIndexComparator());
144: treeSet.addAll(conn.getGlobalContext().getJobManager()
145: .getAllJobsFromQueue());
146:
147: for (Job job : treeSet) {
148: env.add("job", job);
149: env.add("count", job.getIndex());
150: synchronized (job) {
151: if (job.isTransferring()) {
152: env.add("speed", Bytes.formatBytes(job.getSpeed()));
153: env.add("progress", Bytes.formatBytes(job
154: .getProgress()));
155: env.add("total", Bytes.formatBytes(job.getFile()
156: .length()));
157: env.add("srcslave", job.getSourceSlave().getName());
158: env.add("destslave", job.getDestinationSlave()
159: .getName());
160: reply.addComment(conn.jprintf(
161: JobManagerCommandHandler.class,
162: "listjobrunning", env));
163: } else {
164: reply.addComment(conn.jprintf(
165: JobManagerCommandHandler.class,
166: "listjobwaiting", env));
167: }
168: }
169: }
170: env = new ReplacerEnvironment();
171: env.add("total", treeSet.size());
172: reply.addComment(conn.jprintf(JobManagerCommandHandler.class,
173: "sizeofjobs", env));
174: return reply;
175: }
176:
177: private Reply doREMOVEJOB(BaseFtpConnection conn)
178: throws ReplyException, ImproperUsageException {
179:
180: if (!conn.getRequest().hasArgument()) {
181: throw new ImproperUsageException();
182: }
183: class Range {
184: long _low, _high;
185:
186: Range(long low, long high) {
187: if (0 >= low || low > high) {
188: throw new IllegalArgumentException(
189: "0 < low <= high");
190: }
191: _low = low;
192: _high = high;
193: }
194:
195: public boolean contains(long val) {
196: return _low <= val && val <= _high;
197: }
198: }
199:
200: ArrayList<Range> rangeList = new ArrayList<Range>();
201: String rangeString = conn.getRequest().getArgument();
202: String[] ranges = rangeString.split(" ");
203: for (String range : ranges) {
204: if (range.indexOf("-") == -1) {
205: long val = Long.parseLong(range);
206: rangeList.add(new Range(val, val));
207: } else {
208: String[] vals = range.split("-");
209: rangeList.add(new Range(Long.parseLong(vals[0]), Long
210: .parseLong(vals[1])));
211: }
212: }
213: TreeSet<Job> treeSet = new TreeSet<Job>(
214: new JobIndexComparator());
215: treeSet.addAll(conn.getGlobalContext().getJobManager()
216: .getAllJobsFromQueue());
217: ReplacerEnvironment env = new ReplacerEnvironment();
218:
219: Reply r = new Reply(200);
220: for (Job job : treeSet) {
221: for (Range range : rangeList) {
222: if (range.contains(job.getIndex())) {
223: env.add("job", job);
224: conn.getGlobalContext().getJobManager()
225: .stopJob(job);
226: r.addComment(conn.jprintf(
227: JobManagerCommandHandler.class,
228: "removejob.success", env));
229: }
230: }
231: }
232: return r;
233: }
234:
235: private Reply doSTARTJOBS(BaseFtpConnection conn) {
236:
237: conn.getGlobalContext().getJobManager().startJobs();
238:
239: return new Reply(200, "JobTransfers will now start");
240: }
241:
242: private Reply doSTOPJOBS(BaseFtpConnection conn) {
243:
244: conn.getGlobalContext().getJobManager().stopJobs();
245:
246: return new Reply(200,
247: "All JobTransfers will stop after their current transfer");
248: }
249:
250: public Reply execute(BaseFtpConnection conn) throws ReplyException,
251: ImproperUsageException {
252: String cmd = conn.getRequest().getCommand();
253:
254: if ("SITE LISTJOBS".equals(cmd)) {
255: return doLISTJOBS(conn);
256: }
257:
258: if ("SITE REMOVEJOB".equals(cmd)) {
259: return doREMOVEJOB(conn);
260: }
261:
262: if ("SITE ADDJOB".equals(cmd)) {
263: return doADDJOB(conn);
264: }
265:
266: if ("SITE STOPJOBS".equals(cmd)) {
267: return doSTOPJOBS(conn);
268: }
269:
270: if ("SITE STARTJOBS".equals(cmd)) {
271: return doSTARTJOBS(conn);
272: }
273:
274: throw UnhandledCommandException.create(
275: JobManagerCommandHandler.class, conn.getRequest());
276: }
277:
278: // public String getHelp(String cmd) {
279: // ResourceBundle bundle = ResourceBundle.getBundle(Misc.class.getName());
280: // if ("".equals(cmd))
281: // return bundle.getString("help.general")+"\n";
282: // else if("listjobs".equals(cmd) ||
283: // "addjob".equals(cmd) ||
284: // "removejob".equals(cmd) ||
285: // "startjob".equals(cmd) ||
286: // "stopjob".equals(cmd))
287: // return bundle.getString("help."+cmd)+"\n";
288: // else
289: // return "";
290: // }
291:
292: public String[] getFeatReplies() {
293: return null;
294: }
295:
296: public CommandHandler initialize(BaseFtpConnection conn,
297: CommandManager initializer) {
298: return this ;
299: }
300:
301: public void load(CommandManagerFactory initializer) {
302: }
303:
304: public void unload() {
305: }
306: }
|