KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > drftpd > slave > SlaveImpl


1 /*
2  * This file is part of DrFTPD, Distributed FTP Daemon.
3  *
4  * DrFTPD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * DrFTPD is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with DrFTPD; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package net.sf.drftpd.slave;
19
20 import java.io.BufferedReader JavaDoc;
21 import java.io.EOFException JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.FileNotFoundException JavaDoc;
24 import java.io.FileReader JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.net.InetSocketAddress JavaDoc;
28 import java.rmi.ConnectIOException JavaDoc;
29 import java.rmi.Naming JavaDoc;
30 import java.rmi.NotBoundException JavaDoc;
31 import java.rmi.RemoteException JavaDoc;
32 import java.rmi.server.RMISocketFactory JavaDoc;
33 import java.rmi.server.UnicastRemoteObject JavaDoc;
34 import java.rmi.server.Unreferenced JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.Collection JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Properties JavaDoc;
39 import java.util.Vector JavaDoc;
40 import java.util.zip.CRC32 JavaDoc;
41 import java.util.zip.CheckedInputStream JavaDoc;
42
43 import javax.net.ssl.SSLContext;
44
45 import net.sf.drftpd.Bytes;
46 import net.sf.drftpd.FatalException;
47 import net.sf.drftpd.FileExistsException;
48 import net.sf.drftpd.PermissionDeniedException;
49 import net.sf.drftpd.SFVFile;
50 import net.sf.drftpd.master.SlaveManager;
51 import net.sf.drftpd.master.config.FtpConfig;
52 import net.sf.drftpd.remotefile.FileRemoteFile;
53 import net.sf.drftpd.remotefile.LinkedRemoteFile;
54 import net.sf.drftpd.util.PortRange;
55 import net.sf.drftpd.util.SSLGetContext;
56
57 import org.apache.log4j.BasicConfigurator;
58 import org.apache.log4j.Level;
59 import org.apache.log4j.Logger;
60
61 import se.mog.io.File;
62
63 /**
64  * @author mog
65  * @version $Id: SlaveImpl.java,v 1.94.2.2 2004/07/10 18:12:45 mog Exp $
66  */

67 public class SlaveImpl
68     extends UnicastRemoteObject JavaDoc
69     implements Slave, Unreferenced JavaDoc {
70     private int _bufferSize;
71     static final boolean isWin32 =
72         System.getProperty("os.name").startsWith("Windows");
73     private static final Logger logger =
74         Logger.getLogger(SlaveImpl.class.getName());
75     
76     public static final String JavaDoc VERSION = "DrFTPD 1.1.4";
77
78     /**
79      * returns the {LinkedRemoteFile} directory that will be serialized and registered at the master.
80      * they all end up here
81      */

82     public static LinkedRemoteFile getDefaultRoot(RootBasket rootBasket)
83         throws IOException JavaDoc {
84
85         LinkedRemoteFile linkedroot =
86             new LinkedRemoteFile(new FileRemoteFile(rootBasket), null);
87
88         return linkedroot;
89     }
90
91     public static RootBasket getDefaultRootBasket(Properties JavaDoc cfg) throws IOException JavaDoc {
92         RootBasket roots;
93         // START: RootBasket
94
long defaultMinSpaceFree =
95             Bytes.parseBytes(cfg.getProperty("slave.minspacefree", "50mb"));
96         ArrayList JavaDoc rootStrings = new ArrayList JavaDoc();
97         for (int i = 1; true; i++) {
98             String JavaDoc rootString = cfg.getProperty("slave.root." + i);
99             if (rootString == null)
100                 break;
101             System.out.println("slave.root." + i + ": " + rootString);
102
103             long minSpaceFree;
104             try {
105                 minSpaceFree =
106                     Long.parseLong(
107                         cfg.getProperty("slave.root." + i + ".minspacefree"));
108             } catch (NumberFormatException JavaDoc ex) {
109                 minSpaceFree = defaultMinSpaceFree;
110             }
111
112             int priority;
113             try {
114                 priority =
115                     Integer.parseInt(
116                         cfg.getProperty("slave.root." + i + ".priority"));
117             } catch (NumberFormatException JavaDoc ex) {
118                 priority = 0;
119             }
120
121             rootStrings.add(new Root(rootString, minSpaceFree, priority));
122         }
123
124         try {
125             roots = new RootBasket(rootStrings);
126         } catch (IOException JavaDoc e) {
127             throw new FatalException(e);
128         }
129         // END: RootBasket
130
return roots;
131     }
132
133     public static void main(String JavaDoc args[]) {
134         BasicConfigurator.configure();
135         System.out.println(SlaveImpl.VERSION + " slave server starting");
136         String JavaDoc slaveconf;
137         if (args.length >= 1) {
138             slaveconf = args[0];
139         } else {
140             slaveconf = "slave.conf";
141         }
142         try {
143
144             Properties JavaDoc cfg = new Properties JavaDoc();
145             try {
146                 cfg.load(new FileInputStream JavaDoc(slaveconf));
147             } catch (Throwable JavaDoc ex) {
148                 ex.printStackTrace();
149                 System.err.println(
150                     "Could not open " + slaveconf + ", exiting.");
151                 System.exit(0);
152                 return;
153             }
154             if (cfg.getProperty("slave.portfrom") != null) {
155                 RMISocketFactory.setSocketFactory(
156                     new PortRangeServerSocketFactory(
157                         Integer.parseInt(cfg.getProperty("slave.portfrom")),
158                         Integer.parseInt(
159                             FtpConfig.getProperty(cfg, "slave.portto"))));
160             }
161
162             new SlaveImpl(cfg);
163
164         } catch (Throwable JavaDoc e) {
165             logger.warn("Error registering", e);
166             System.exit(0);
167             return;
168         }
169     }
170     private SSLContext _ctx;
171     private boolean _downloadChecksums;
172     private String JavaDoc _name;
173     private PortRange _portRange = new PortRange();
174     private long _receivedBytes = 0;
175     //private String root;
176
private RootBasket _roots;
177     private long _sentBytes = 0;
178
179     private Vector JavaDoc _transfers = new Vector JavaDoc();
180     private boolean _uploadChecksums;
181     
182     public LinkedRemoteFile getSlaveRoot() throws IOException JavaDoc {
183             return SlaveImpl.getDefaultRoot(_roots);
184     }
185
186     public SlaveImpl(Properties JavaDoc cfg) throws RemoteException JavaDoc, IOException JavaDoc {
187         super(0);
188         try {
189             _ctx = SSLGetContext.getSSLContext();
190         } catch (Exception JavaDoc e) {
191             logger.warn("Error loading SSLContext", e);
192         }
193         _uploadChecksums = cfg.getProperty("enableuploadchecksums", "true").equals("true");
194         _downloadChecksums = cfg.getProperty("enabledownloadchecksums", "true").equals("true");
195         _bufferSize = Integer.parseInt(cfg.getProperty("bufferSize","0"));
196
197         String JavaDoc slavemanagerurl;
198         slavemanagerurl =
199             "//"
200                 + FtpConfig.getProperty(cfg, "master.host")
201                 + ":"
202                 + cfg.getProperty("master.bindport", "1099")
203                 + "/"
204                 + cfg.getProperty("master.bindname", "slavemanager");
205         _name = FtpConfig.getProperty(cfg, "slave.name");
206
207         _roots = getDefaultRootBasket(cfg);
208         try {
209             SlaveManager manager;
210             logger.log(Level.INFO, "Getting master reference");
211             manager = (SlaveManager) Naming.lookup(slavemanagerurl);
212
213             logger.log(
214                 Level.INFO,
215                 "Registering with master and sending filelist");
216
217             manager.addSlave(_name, this, getSlaveStatus(), _roots.getMaxPath());
218
219             logger.log(
220                 Level.INFO,
221                 "Finished registered with master, awaiting commands.");
222         } catch (RuntimeException JavaDoc t) {
223             logger.warn("Error registering with slave", t);
224             System.exit(0);
225         } catch (IOException JavaDoc e) {
226             if (e instanceof ConnectIOException JavaDoc
227                 && e.getCause() instanceof EOFException JavaDoc) {
228                 logger.info(
229                     "Check slaves.xml on the master that you are allowed to connect.");
230             }
231             logger.info("", e);
232             System.exit(0);
233         } catch (NotBoundException JavaDoc e) {
234             logger.warn("", e);
235         }
236         System.gc();
237     }
238         
239     public void addTransfer(TransferImpl transfer) {
240         synchronized (_transfers) {
241             _transfers.add(transfer);
242         }
243     }
244
245     /**
246      * @see net.sf.drftpd.slave.Slave#checkSum(String)
247      */

248     public long checkSum(String JavaDoc path) throws IOException JavaDoc {
249         logger.debug("Checksumming: " + path);
250         CRC32 JavaDoc crc32 = new CRC32 JavaDoc();
251         FileInputStream JavaDoc fis = new FileInputStream JavaDoc(_roots.getFile(path));
252         try {
253             InputStream JavaDoc in = new CheckedInputStream JavaDoc(fis, crc32);
254             byte buf[] = new byte[4096];
255             while (in.read(buf) != -1);
256         } finally {
257             fis.close();
258         }
259         return crc32.getValue();
260     }
261
262     public Transfer connect(InetSocketAddress JavaDoc addr, boolean encrypted)
263         throws RemoteException JavaDoc {
264         //TODO connect?
265
return new TransferImpl(
266             new ActiveConnection(encrypted ? _ctx : null, addr),
267             this);
268     }
269
270     public void delete(String JavaDoc path) throws IOException JavaDoc {
271         Collection JavaDoc files = _roots.getMultipleRootsForFile(path);
272         for (Iterator JavaDoc iter = files.iterator(); iter.hasNext();) {
273             Root root = (Root) iter.next();
274             File file = root.getFile(path);
275             if (!file.exists()) {
276                 throw new FileNotFoundException JavaDoc(
277                     file.getAbsolutePath() + " does not exist.");
278             }
279             if (!file.delete())
280                 throw new PermissionDeniedException("delete failed on " + path);
281             File dir = new File(file.getParentFile());
282
283             //TODO don't go above empty root
284
logger.debug("DELETE: "+path);
285             while (dir.list().length == 0) {
286                 file.delete();
287                 logger.debug("DELETEFS: "+file.getPath());
288                 java.io.File JavaDoc tmpFile = dir.getParentFile();
289                 if (tmpFile == null)
290                     break;
291                 if (tmpFile.getPath().length() < root.getPath().length()) {
292                     throw new SecurityException JavaDoc("Attempt to break out of root");
293                 }
294                 dir = new File(tmpFile);
295             }
296         }
297     }
298
299     public boolean getDownloadChecksums() {
300         return _downloadChecksums;
301     }
302
303     public RootBasket getRoots() {
304         return _roots;
305     }
306
307     public SFVFile getSFVFile(String JavaDoc path) throws IOException JavaDoc {
308         return new SFVFile(
309             new BufferedReader JavaDoc(new FileReader JavaDoc(_roots.getFile(path))));
310     }
311
312     public SlaveStatus getSlaveStatus() {
313         int throughputUp = 0, throughputDown = 0;
314         int transfersUp = 0, transfersDown = 0;
315         long bytesReceived, bytesSent;
316         synchronized (_transfers) {
317             bytesReceived = _receivedBytes;
318             bytesSent = _sentBytes;
319             for (Iterator JavaDoc i = _transfers.iterator(); i.hasNext();) {
320                 TransferImpl transfer = (TransferImpl) i.next();
321                 switch (transfer.getDirection()) {
322                     case Transfer.TRANSFER_RECEIVING_UPLOAD :
323                         throughputUp += transfer.getXferSpeed();
324                         transfersUp += 1;
325                         bytesReceived += transfer.getTransfered();
326                         break;
327                     case Transfer.TRANSFER_SENDING_DOWNLOAD :
328                         throughputDown += transfer.getXferSpeed();
329                         transfersDown += 1;
330                         bytesSent += transfer.getTransfered();
331                         break;
332                     default :
333                         throw new FatalException("unrecognized direction");
334                 }
335             }
336         }
337         try {
338             return new SlaveStatus(
339                 _roots.getTotalDiskSpaceAvailable(),
340                 _roots.getTotalDiskSpaceCapacity(),
341                 bytesSent,
342                 bytesReceived,
343                 throughputUp,
344                 transfersUp,
345                 throughputDown,
346                 transfersDown);
347         } catch (Exception JavaDoc ex) {
348             ex.printStackTrace();
349             throw new RuntimeException JavaDoc(ex.toString());
350         }
351     }
352
353     public boolean getUploadChecksums() {
354         return _uploadChecksums;
355     }
356
357     public Transfer listen(boolean encrypted)
358         throws RemoteException JavaDoc, IOException JavaDoc {
359         return new TransferImpl(
360             new PassiveConnection(
361                 encrypted ? _ctx : null,
362                 _portRange,
363                 new InetSocketAddress JavaDoc(0)),
364             this);
365     }
366
367     public void ping() {
368     }
369
370     public void removeTransfer(TransferImpl transfer) {
371         synchronized (_transfers) {
372             switch (transfer.getDirection()) {
373                 case Transfer.TRANSFER_RECEIVING_UPLOAD :
374                     _receivedBytes += transfer.getTransfered();
375                     break;
376                 case Transfer.TRANSFER_SENDING_DOWNLOAD :
377                     _sentBytes += transfer.getTransfered();
378                     break;
379                 default :
380                     throw new IllegalArgumentException JavaDoc();
381             }
382             if (!_transfers.remove(transfer))
383                 throw new IllegalStateException JavaDoc();
384         }
385     }
386
387     public void rename(String JavaDoc from, String JavaDoc toDirPath, String JavaDoc toName)
388         throws IOException JavaDoc {
389         for (Iterator JavaDoc iter = _roots.iterator(); iter.hasNext();) {
390             Root root = (Root) iter.next();
391
392             File fromfile = root.getFile(from);
393             if (!fromfile.exists())
394                 continue;
395
396             File toDir = root.getFile(toDirPath);
397             toDir.mkdirs();
398             File tofile = new File(toDir.getPath() + File.separator + toName);
399             //!win32 == true on linux
400
//!win32 && equalsignore == true on win32
401
if (tofile.exists()
402                 && !(isWin32 && fromfile.getName().equalsIgnoreCase(toName))) {
403                 throw new FileExistsException(
404                     "cannot rename from "
405                         + fromfile
406                         + " to "
407                         + tofile
408                         + ", destination exists");
409             }
410
411             if (!fromfile.renameTo(tofile)) {
412                 throw new IOException JavaDoc(
413                     "renameTo(" + fromfile + ", " + tofile + ") failed");
414             }
415         }
416     }
417
418     public void unreferenced() {
419         logger.info("unreferenced");
420         System.exit(0);
421     }
422
423     /**
424      * @return
425      */

426     public int getBufferSize() {
427         return _bufferSize;
428     }
429
430 }
431
Popular Tags