PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/client/hadoop/ceph/CephFaker.java

https://github.com/stass/ceph
Java | 483 lines | 362 code | 68 blank | 53 comment | 28 complexity | a2e026776f4d54e33862dcc7d1490b44 MD5 | raw file
  1. // -*- mode:Java; tab-width:2; c-basic-offset:2; indent-tabs-mode:t -*-
  2. /**
  3. *
  4. * Licensed under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  13. * implied. See the License for the specific language governing
  14. * permissions and limitations under the License.
  15. *
  16. *
  17. * This uses the local Filesystem but pretends to be communicating
  18. * with a Ceph deployment, for unit testing the CephFileSystem.
  19. */
  20. package org.apache.hadoop.fs.ceph;
  21. import java.net.URI;
  22. import java.util.Hashtable;
  23. import java.io.Closeable;
  24. import java.io.FileNotFoundException;
  25. import java.io.IOException;
  26. import org.apache.commons.logging.Log;
  27. import org.apache.commons.logging.LogFactory;
  28. import org.apache.hadoop.conf.Configuration;
  29. import org.apache.hadoop.fs.BlockLocation;
  30. import org.apache.hadoop.fs.FileStatus;
  31. import org.apache.hadoop.fs.FileSystem;
  32. import org.apache.hadoop.fs.FSDataInputStream;
  33. import org.apache.hadoop.fs.FSDataOutputStream;
  34. import org.apache.hadoop.fs.Path;
  35. import org.apache.hadoop.fs.permission.FsPermission;
  36. class CephFaker extends CephFS {
  37. private static final Log LOG = LogFactory.getLog(CephFaker.class);
  38. FileSystem localFS;
  39. String localPrefix;
  40. int blockSize;
  41. Configuration conf;
  42. Hashtable<Integer, Object> files;
  43. Hashtable<Integer, String> filenames;
  44. int fileCount = 0;
  45. boolean initialized = false;
  46. public CephFaker(Configuration con, Log log) {
  47. conf = con;
  48. files = new Hashtable<Integer, Object>();
  49. filenames = new Hashtable<Integer, String>();
  50. }
  51. protected boolean ceph_initializeClient(String args, int block_size) {
  52. if (!initialized) {
  53. // let's remember the default block_size
  54. blockSize = block_size;
  55. /* for a real Ceph deployment, this starts up the client,
  56. * sets debugging levels, etc. We just need to get the
  57. * local FileSystem to use, and we'll ignore any
  58. * command-line arguments. */
  59. try {
  60. localFS = FileSystem.getLocal(conf);
  61. localFS.initialize(URI.create("file://localhost"), conf);
  62. localFS.setVerifyChecksum(false);
  63. String testDir = conf.get("hadoop.tmp.dir");
  64. localPrefix = localFS.getWorkingDirectory().toString();
  65. int testDirLoc = localPrefix.indexOf(testDir) - 1;
  66. if (-2 == testDirLoc) {
  67. testDirLoc = localPrefix.length();
  68. }
  69. localPrefix = localPrefix.substring(0, testDirLoc) + "/"
  70. + conf.get("hadoop.tmp.dir");
  71. localFS.setWorkingDirectory(
  72. new Path(localPrefix + "/user/" + System.getProperty("user.name")));
  73. // I don't know why, but the unit tests expect the default
  74. // working dir to be /user/username, so satisfy them!
  75. // debug("localPrefix is " + localPrefix, INFO);
  76. } catch (IOException e) {
  77. return false;
  78. }
  79. initialized = true;
  80. }
  81. return true;
  82. }
  83. protected String ceph_getcwd() {
  84. return sanitize_path(localFS.getWorkingDirectory().toString());
  85. }
  86. protected boolean ceph_setcwd(String path) {
  87. localFS.setWorkingDirectory(new Path(prepare_path(path)));
  88. return true;
  89. }
  90. // the caller is responsible for ensuring empty dirs
  91. protected boolean ceph_rmdir(String pth) {
  92. Path path = new Path(prepare_path(pth));
  93. boolean ret = false;
  94. try {
  95. if (localFS.listStatus(path).length <= 1) {
  96. ret = localFS.delete(path, true);
  97. }
  98. } catch (IOException e) {}
  99. return ret;
  100. }
  101. // this needs to work on (empty) directories too
  102. protected boolean ceph_unlink(String path) {
  103. path = prepare_path(path);
  104. boolean ret = false;
  105. if (ceph_isdirectory(path)) {
  106. ret = ceph_rmdir(path);
  107. } else {
  108. try {
  109. ret = localFS.delete(new Path(path), false);
  110. } catch (IOException e) {}
  111. }
  112. return ret;
  113. }
  114. protected boolean ceph_rename(String oldName, String newName) {
  115. oldName = prepare_path(oldName);
  116. newName = prepare_path(newName);
  117. try {
  118. Path parent = new Path(newName).getParent();
  119. Path newPath = new Path(newName);
  120. if (localFS.exists(parent) && !localFS.exists(newPath)) {
  121. return localFS.rename(new Path(oldName), newPath);
  122. }
  123. return false;
  124. } catch (IOException e) {
  125. return false;
  126. }
  127. }
  128. protected boolean ceph_exists(String path) {
  129. path = prepare_path(path);
  130. boolean ret = false;
  131. try {
  132. ret = localFS.exists(new Path(path));
  133. } catch (IOException e) {}
  134. return ret;
  135. }
  136. protected long ceph_getblocksize(String path) {
  137. path = prepare_path(path);
  138. try {
  139. FileStatus status = localFS.getFileStatus(new Path(path));
  140. return status.getBlockSize();
  141. } catch (FileNotFoundException e) {
  142. return -CephFS.ENOENT;
  143. } catch (IOException e) {
  144. return -1; // just fail generically
  145. }
  146. }
  147. protected boolean ceph_isdirectory(String path) {
  148. path = prepare_path(path);
  149. try {
  150. FileStatus status = localFS.getFileStatus(new Path(path));
  151. return status.isDir();
  152. } catch (IOException e) {
  153. return false;
  154. }
  155. }
  156. protected boolean ceph_isfile(String path) {
  157. path = prepare_path(path);
  158. boolean ret = false;
  159. try {
  160. FileStatus status = localFS.getFileStatus(new Path(path));
  161. ret = !status.isDir();
  162. } catch (Exception e) {}
  163. return ret;
  164. }
  165. protected String[] ceph_getdir(String path) {
  166. path = prepare_path(path);
  167. if (!ceph_isdirectory(path)) {
  168. return null;
  169. }
  170. try {
  171. FileStatus[] stats = localFS.listStatus(new Path(path));
  172. String[] names = new String[stats.length];
  173. String name;
  174. for (int i = 0; i < stats.length; ++i) {
  175. name = stats[i].getPath().toString();
  176. names[i] = name.substring(name.lastIndexOf(Path.SEPARATOR) + 1);
  177. }
  178. return names;
  179. } catch (IOException e) {}
  180. return null;
  181. }
  182. protected int ceph_mkdirs(String path, int mode) {
  183. path = prepare_path(path);
  184. // debug("ceph_mkdirs on " + path, INFO);
  185. try {
  186. if (localFS.mkdirs(new Path(path), new FsPermission((short) mode))) {
  187. return 0;
  188. }
  189. } catch (IOException e) {}
  190. if (ceph_isdirectory(path)) { // apparently it already existed
  191. return -EEXIST;
  192. } else if (ceph_isfile(path)) {
  193. return -ENOTDIR;
  194. }
  195. return -1;
  196. }
  197. /*
  198. * Unlike a real Ceph deployment, you can't do opens on a directory.
  199. * Since that has unpredictable behavior and you shouldn't do it anyway,
  200. * it's okay.
  201. */
  202. protected int ceph_open_for_append(String path) {
  203. path = prepare_path(path);
  204. FSDataOutputStream stream;
  205. try {
  206. stream = localFS.append(new Path(path));
  207. files.put(new Integer(fileCount), stream);
  208. filenames.put(new Integer(fileCount), path);
  209. return fileCount++;
  210. } catch (IOException e) {}
  211. return -1; // failure
  212. }
  213. protected int ceph_open_for_read(String path) {
  214. path = prepare_path(path);
  215. FSDataInputStream stream;
  216. try {
  217. stream = localFS.open(new Path(path));
  218. files.put(new Integer(fileCount), stream);
  219. filenames.put(new Integer(fileCount), path);
  220. LOG.info("ceph_open_for_read fh:" + fileCount + ", pathname:" + path);
  221. return fileCount++;
  222. } catch (IOException e) {}
  223. return -1; // failure
  224. }
  225. protected int ceph_open_for_overwrite(String path, int mode) {
  226. path = prepare_path(path);
  227. FSDataOutputStream stream;
  228. try {
  229. stream = localFS.create(new Path(path));
  230. files.put(new Integer(fileCount), stream);
  231. filenames.put(new Integer(fileCount), path);
  232. LOG.info("ceph_open_for_overwrite fh:" + fileCount + ", pathname:" + path);
  233. return fileCount++;
  234. } catch (IOException e) {}
  235. return -1; // failure
  236. }
  237. protected int ceph_close(int filehandle) {
  238. LOG.info("ceph_close(filehandle " + filehandle + ")");
  239. try {
  240. ((Closeable) files.get(new Integer(filehandle))).close();
  241. if (null == files.get(new Integer(filehandle))) {
  242. return -ENOENT; // this isn't quite the right error code,
  243. // but the important part is it's negative
  244. }
  245. return 0; // hurray, success
  246. } catch (NullPointerException ne) {
  247. LOG.warn("ceph_close caught NullPointerException!" + ne);
  248. } // err, how?
  249. catch (IOException ie) {
  250. LOG.warn("ceph_close caught IOException!" + ie);
  251. }
  252. return -1; // failure
  253. }
  254. protected boolean ceph_setPermission(String pth, int mode) {
  255. pth = prepare_path(pth);
  256. Path path = new Path(pth);
  257. boolean ret = false;
  258. try {
  259. localFS.setPermission(path, new FsPermission((short) mode));
  260. ret = true;
  261. } catch (IOException e) {}
  262. return ret;
  263. }
  264. // rather than try and match a Ceph deployment's behavior exactly,
  265. // just make bad things happen if they try and call methods after this
  266. protected boolean ceph_kill_client() {
  267. // debug("ceph_kill_client", INFO);
  268. localFS.setWorkingDirectory(new Path(localPrefix));
  269. // debug("working dir is now " + localFS.getWorkingDirectory(), INFO);
  270. try {
  271. localFS.close();
  272. } catch (Exception e) {}
  273. localFS = null;
  274. files = null;
  275. filenames = null;
  276. return true;
  277. }
  278. protected boolean ceph_stat(String pth, CephFileSystem.Stat fill) {
  279. pth = prepare_path(pth);
  280. Path path = new Path(pth);
  281. boolean ret = false;
  282. try {
  283. FileStatus status = localFS.getFileStatus(path);
  284. fill.size = status.getLen();
  285. fill.is_dir = status.isDir();
  286. fill.block_size = status.getBlockSize();
  287. fill.mod_time = status.getModificationTime();
  288. fill.access_time = status.getAccessTime();
  289. fill.mode = status.getPermission().toShort();
  290. ret = true;
  291. } catch (IOException e) {}
  292. return ret;
  293. }
  294. protected int ceph_replication(String path) {
  295. path = prepare_path(path);
  296. int ret = -1; // -1 for failure
  297. try {
  298. ret = localFS.getFileStatus(new Path(path)).getReplication();
  299. } catch (IOException e) {}
  300. return ret;
  301. }
  302. protected String[] ceph_hosts(int fh, long offset) {
  303. String[] ret = null;
  304. try {
  305. BlockLocation[] locs = localFS.getFileBlockLocations(
  306. localFS.getFileStatus(new Path(filenames.get(new Integer(fh)))),
  307. offset, 1);
  308. ret = locs[0].getNames();
  309. } catch (IOException e) {} catch (NullPointerException f) {}
  310. return ret;
  311. }
  312. protected int ceph_setTimes(String pth, long mtime, long atime) {
  313. pth = prepare_path(pth);
  314. Path path = new Path(pth);
  315. int ret = -1; // generic fail
  316. try {
  317. localFS.setTimes(path, mtime, atime);
  318. ret = 0;
  319. } catch (IOException e) {}
  320. return ret;
  321. }
  322. protected long ceph_getpos(int fh) {
  323. long ret = -1; // generic fail
  324. try {
  325. Object stream = files.get(new Integer(fh));
  326. if (stream instanceof FSDataInputStream) {
  327. ret = ((FSDataInputStream) stream).getPos();
  328. } else if (stream instanceof FSDataOutputStream) {
  329. ret = ((FSDataOutputStream) stream).getPos();
  330. }
  331. } catch (IOException e) {} catch (NullPointerException f) {}
  332. return ret;
  333. }
  334. protected int ceph_write(int fh, byte[] buffer,
  335. int buffer_offset, int length) {
  336. LOG.info(
  337. "ceph_write fh:" + fh + ", buffer_offset:" + buffer_offset + ", length:"
  338. + length);
  339. long ret = -1; // generic fail
  340. try {
  341. FSDataOutputStream os = (FSDataOutputStream) files.get(new Integer(fh));
  342. LOG.info("ceph_write got outputstream");
  343. long startPos = os.getPos();
  344. os.write(buffer, buffer_offset, length);
  345. ret = os.getPos() - startPos;
  346. } catch (IOException e) {
  347. LOG.warn("ceph_write caught IOException!");
  348. } catch (NullPointerException f) {
  349. LOG.warn("ceph_write caught NullPointerException!");
  350. }
  351. return (int) ret;
  352. }
  353. protected int ceph_read(int fh, byte[] buffer,
  354. int buffer_offset, int length) {
  355. long ret = -1; // generic fail
  356. try {
  357. FSDataInputStream is = (FSDataInputStream) files.get(new Integer(fh));
  358. long startPos = is.getPos();
  359. is.read(buffer, buffer_offset, length);
  360. ret = is.getPos() - startPos;
  361. } catch (IOException e) {} catch (NullPointerException f) {}
  362. return (int) ret;
  363. }
  364. protected long ceph_seek_from_start(int fh, long pos) {
  365. LOG.info("ceph_seek_from_start(fh " + fh + ", pos " + pos + ")");
  366. long ret = -1; // generic fail
  367. try {
  368. LOG.info("ceph_seek_from_start filename is " + filenames.get(new Integer(fh)));
  369. if (null == files.get(new Integer(fh))) {
  370. LOG.warn("ceph_seek_from_start: is is null!");
  371. }
  372. FSDataInputStream is = (FSDataInputStream) files.get(new Integer(fh));
  373. LOG.info("ceph_seek_from_start retrieved is!");
  374. is.seek(pos);
  375. ret = is.getPos();
  376. } catch (IOException e) {
  377. LOG.warn("ceph_seek_from_start caught IOException!");
  378. } catch (NullPointerException f) {
  379. LOG.warn("ceph_seek_from_start caught NullPointerException!");
  380. }
  381. return (int) ret;
  382. }
  383. /*
  384. * We need to remove the localFS file prefix before returning to Ceph
  385. */
  386. private String sanitize_path(String path) {
  387. // debug("sanitize_path(" + path + ")", INFO);
  388. /* if (path.startsWith("file:"))
  389. path = path.substring("file:".length()); */
  390. if (path.startsWith(localPrefix)) {
  391. path = path.substring(localPrefix.length());
  392. if (path.length() == 0) { // it was a root path
  393. path = "/";
  394. }
  395. }
  396. // debug("sanitize_path returning " + path, INFO);
  397. return path;
  398. }
  399. /*
  400. * If it's an absolute path we need to shove the
  401. * test dir onto the front as a prefix.
  402. */
  403. private String prepare_path(String path) {
  404. // debug("prepare_path(" + path + ")", INFO);
  405. if (path.startsWith("/")) {
  406. path = localPrefix + path;
  407. } else if (path.equals("..")) {
  408. if (ceph_getcwd().equals("/")) {
  409. path = ".";
  410. } // you can't go up past root!
  411. }
  412. // debug("prepare_path returning" + path, INFO);
  413. return path;
  414. }
  415. }