PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/playground/netcache/Netcache.java

https://code.google.com/
Java | 279 lines | 227 code | 40 blank | 12 comment | 41 complexity | cdd61719c3c0fdc9174c7618621ac078 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Thomas Nagy, 2011
  2. // TODO handle all exceptions properly
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import java.util.List;
  6. import java.util.Date;
  7. import java.util.ArrayList;
  8. import java.util.Comparator;
  9. import java.util.Collections;
  10. import java.lang.Math;
  11. import java.lang.StringBuilder;
  12. import java.io.*;
  13. import java.net.*;
  14. import java.security.*;
  15. public class Netcache implements Runnable, Comparator<Object[]> {
  16. private static int PORT_UPLOAD = 11001;
  17. private static int PORT_DOWNLOAD = 12001;
  18. private static String CACHEDIR = "/tmp/wafcache/";
  19. private static long MAX = 10l * 1024l * 1024l * 1024l;
  20. private static double CLEANRATIO = 0.8;
  21. private static int BUF = 16 * 8192;
  22. private final static HashMap<String, Object[]> flist = new HashMap<String, Object[]>();
  23. private Socket sock = null;
  24. private int port = 0;
  25. public Netcache(Socket sock, int port) {
  26. this.sock = sock;
  27. this.port = port;
  28. }
  29. public void run () {
  30. try {
  31. if (sock != null)
  32. {
  33. while (true) {
  34. InputStream in = sock.getInputStream();
  35. OutputStream out = sock.getOutputStream();
  36. byte b[] = new byte[128];
  37. int off = 0;
  38. while (off < b.length) {
  39. off += in.read(b, off, b.length - off);
  40. }
  41. //System.out.println(new String(b));
  42. String[] args = new String(b).split(",");
  43. if (args[0].equals("LST")) {
  44. lst(args, in, out);
  45. }
  46. else if (args[0].equals("PUT") && port == PORT_UPLOAD) {
  47. put(args, in, out);
  48. }
  49. else if (args[0].equals("GET") && port == PORT_DOWNLOAD) {
  50. get(args, in, out);
  51. }
  52. else if (args[0].equals("CLEAN") && port == PORT_UPLOAD) {
  53. clean(args, in, out);
  54. }
  55. else if (args[0].equals("BYE")) {
  56. sock.close();
  57. break;
  58. }
  59. else {
  60. System.out.println("Invalid command " + new String(b) + " on port " + this.port);
  61. sock.close();
  62. break;
  63. }
  64. }
  65. } else {
  66. // magic trick to avoid creating a new inner class
  67. ServerSocket server = new ServerSocket(port);
  68. server.setReuseAddress(true);
  69. while(true) {
  70. Netcache tmp = new Netcache(server.accept(), port);
  71. Thread t = new Thread(tmp);
  72. t.start();
  73. }
  74. }
  75. } catch (IOException e) {
  76. e.printStackTrace();
  77. }
  78. }
  79. public void lst(String[] args, InputStream in, OutputStream out) throws IOException {
  80. StringBuilder b = new StringBuilder();
  81. int k = 0;
  82. synchronized(flist) {
  83. for (String name : flist.keySet()) {
  84. b.append(name);
  85. if (k <= flist.size()) {
  86. k++;
  87. b.append("\n");
  88. }
  89. }
  90. }
  91. byte[] ret = b.toString().getBytes();
  92. String header = String.format("%-128s", String.format("%d,", ret.length));
  93. out.write(header.getBytes());
  94. out.write(ret);
  95. }
  96. public void put(String[] args, InputStream in, OutputStream out) throws IOException {
  97. File cachedir = new File(CACHEDIR);
  98. File temp = File.createTempFile("foo", ".suffix", cachedir);
  99. long size = new Long(args[3].trim());
  100. //System.out.println("" + args[1] + " " + args[2] + " " + args[3] + " " + args.length);
  101. byte[] buf = new byte[BUF];
  102. long cnt = 0;
  103. OutputStream w = new FileOutputStream(temp);
  104. try {
  105. while (cnt < size) {
  106. int c = in.read(buf, 0, (int) Math.min(BUF, size-cnt));
  107. if (c == 0) {
  108. throw new RuntimeException("Connection closed too early");
  109. }
  110. w.write(buf, 0, c);
  111. cnt += c;
  112. }
  113. } finally {
  114. w.close();
  115. }
  116. /*if (cnt != size) {
  117. System.out.println("error!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  118. }*/
  119. File parent = new File(new File(new File(CACHEDIR), args[1].substring(0, 2)), args[1]);
  120. File dest = new File(parent, args[2]);
  121. try {
  122. dest.getParentFile().mkdirs();
  123. } catch (Exception e) {
  124. }
  125. if (!temp.renameTo(dest)) {
  126. throw new RuntimeException("Could not rename the file");
  127. }
  128. long total = 0;
  129. for (File f : parent.listFiles()) {
  130. total += f.length();
  131. }
  132. synchronized(flist) {
  133. if (flist.containsKey(parent.getName())) {
  134. flist.get(parent.getName())[0] = parent.lastModified();
  135. }
  136. else
  137. {
  138. flist.put(parent.getName(), new Object[] {parent.lastModified(), total, parent.getName()});
  139. }
  140. }
  141. }
  142. public void get(String[] args, InputStream in, OutputStream out) throws IOException {
  143. File f = new File(new File(new File(new File(CACHEDIR), args[1].substring(0, 2)), args[1]), args[2].trim());
  144. long fsize = -1;
  145. try {
  146. fsize = f.length();
  147. } catch (Exception e) {
  148. // return -1 to the client
  149. }
  150. String ret = String.format("%-128s", String.format("%d,", fsize));
  151. out.write(ret.getBytes());
  152. byte[] buf = new byte[BUF];
  153. long cnt = 0;
  154. InputStream s = new FileInputStream(f);
  155. try {
  156. while (cnt < fsize) {
  157. long c = s.read(buf);
  158. cnt += c;
  159. out.write(buf, 0, (int) c);
  160. }
  161. } finally {
  162. s.close();
  163. }
  164. File parent = f.getParentFile();
  165. Date d = new Date();
  166. parent.setLastModified(d.getTime());
  167. synchronized(flist) {
  168. flist.get(parent.getName())[0] = parent.lastModified();
  169. }
  170. }
  171. public void clean(String[] args, InputStream in, OutputStream out) throws IOException {
  172. synchronized(flist) {
  173. long total = 0;
  174. for (Map.Entry<String, Object[]> entry : flist.entrySet()) {
  175. total += (Long) entry.getValue()[1];
  176. }
  177. List<Object[]> k = new ArrayList<Object[]>(flist.values());
  178. Collections.sort(k, this);
  179. int cur = 0;
  180. while (total > MAX * CLEANRATIO) {
  181. Object[] kk = k.get(cur);
  182. String name = (String) kk[2];
  183. File f = new File(new File(new File(CACHEDIR), name.substring(0, 2)), name);
  184. //System.out.println("removing " + cur + " " + kk[0] + " " + kk[1] + " " + f.getAbsolutePath());
  185. rm(f);
  186. total -= (Long) kk[1];
  187. flist.remove(name);
  188. cur++;
  189. }
  190. }
  191. }
  192. public static void init_flist() {
  193. synchronized(flist) {
  194. flist.clear();
  195. File dir = new File(CACHEDIR);
  196. try {
  197. dir.mkdirs();
  198. } catch (Exception e) {
  199. }
  200. for (File d : dir.listFiles()) {
  201. if (!d.isDirectory()) continue;
  202. for (File sd : d.listFiles()) {
  203. if (!sd.isDirectory()) continue;
  204. long total = 0;
  205. for (File f : sd.listFiles()) {
  206. total += f.length();
  207. }
  208. //System.out.println(sd.getName());
  209. flist.put(sd.getName(), new Object[] {sd.lastModified(), total, sd.getName()});
  210. }
  211. }
  212. }
  213. }
  214. public int compare(Object[] a, Object[] b) {
  215. return ((Long) a[0]).compareTo((Long) b[0]);
  216. }
  217. public static void rm(File dir) {
  218. if (dir.isDirectory()) {
  219. for (File f: dir.listFiles())
  220. {
  221. rm(f);
  222. }
  223. }
  224. dir.delete();
  225. }
  226. public static void main(String[] args) {
  227. init_flist();
  228. System.out.println("ready (" + flist.keySet().size() + " dirs)");
  229. // different ports for upload and download, another port could be added for the clean command
  230. Thread upload = null;
  231. if (PORT_UPLOAD != PORT_DOWNLOAD) {
  232. Netcache tmp = new Netcache(null, PORT_UPLOAD);
  233. upload = new Thread(tmp);
  234. upload.start();
  235. }
  236. Netcache tmp = new Netcache(null, PORT_DOWNLOAD);
  237. tmp.run();
  238. }
  239. }