TrackerClient.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. /**
  2. * Copyright (C) 2008 Happy Fish / YuQing
  3. * <p>
  4. * FastDFS Java Client may be copied only under the terms of the GNU Lesser
  5. * General Public License (LGPL).
  6. * Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
  7. */
  8. package com.kmall.common.fileserver.fastdfs;
  9. import java.io.IOException;
  10. import java.io.OutputStream;
  11. import java.net.Socket;
  12. import java.util.Arrays;
  13. /**
  14. * Tracker client
  15. *
  16. * @author Happy Fish / YuQing
  17. * @version Version 1.19
  18. */
  19. public class TrackerClient {
  20. protected TrackerGroup tracker_group;
  21. protected byte errno;
  22. /**
  23. * constructor with global tracker group
  24. */
  25. public TrackerClient() {
  26. this.tracker_group = ClientGlobal.g_tracker_group;
  27. }
  28. /**
  29. * constructor with specified tracker group
  30. *
  31. * @param tracker_group the tracker group object
  32. */
  33. public TrackerClient(TrackerGroup tracker_group) {
  34. this.tracker_group = tracker_group;
  35. }
  36. /**
  37. * get the error code of last call
  38. *
  39. * @return the error code of last call
  40. */
  41. public byte getErrorCode() {
  42. return this.errno;
  43. }
  44. /**
  45. * get a connection to tracker server
  46. *
  47. * @return tracker server Socket object, return null if fail
  48. */
  49. public TrackerServer getConnection() throws IOException {
  50. return this.tracker_group.getConnection();
  51. }
  52. /**
  53. * query storage server to upload file
  54. *
  55. * @param trackerServer the tracker server
  56. * @return storage server Socket object, return null if fail
  57. */
  58. public StorageServer getStoreStorage(TrackerServer trackerServer) throws IOException {
  59. final String groupName = null;
  60. return this.getStoreStorage(trackerServer, groupName);
  61. }
  62. /**
  63. * query storage server to upload file
  64. *
  65. * @param trackerServer the tracker server
  66. * @param groupName the group name to upload file to, can be empty
  67. * @return storage server object, return null if fail
  68. */
  69. public StorageServer getStoreStorage(TrackerServer trackerServer, String groupName) throws IOException {
  70. byte[] header;
  71. String ip_addr;
  72. int port;
  73. byte cmd;
  74. int out_len;
  75. boolean bNewConnection;
  76. byte store_path;
  77. Socket trackerSocket;
  78. if (trackerServer == null) {
  79. trackerServer = getConnection();
  80. if (trackerServer == null) {
  81. return null;
  82. }
  83. bNewConnection = true;
  84. } else {
  85. bNewConnection = false;
  86. }
  87. trackerSocket = trackerServer.getSocket();
  88. OutputStream out = trackerSocket.getOutputStream();
  89. try {
  90. if (groupName == null || groupName.length() == 0) {
  91. cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE;
  92. out_len = 0;
  93. } else {
  94. cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE;
  95. out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
  96. }
  97. header = ProtoCommon.packHeader(cmd, out_len, (byte) 0);
  98. out.write(header);
  99. if (groupName != null && groupName.length() > 0) {
  100. byte[] bGroupName;
  101. byte[] bs;
  102. int group_len;
  103. bs = groupName.getBytes(ClientGlobal.g_charset);
  104. bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
  105. if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
  106. group_len = bs.length;
  107. } else {
  108. group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
  109. }
  110. Arrays.fill(bGroupName, (byte) 0);
  111. System.arraycopy(bs, 0, bGroupName, 0, group_len);
  112. out.write(bGroupName);
  113. }
  114. ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
  115. ProtoCommon.TRACKER_PROTO_CMD_RESP,
  116. ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN);
  117. this.errno = pkgInfo.errno;
  118. if (pkgInfo.errno != 0) {
  119. return null;
  120. }
  121. ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim();
  122. port = (int) ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN
  123. + ProtoCommon.FDFS_IPADDR_SIZE - 1);
  124. store_path = pkgInfo.body[ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN - 1];
  125. return new StorageServer(ip_addr, port, store_path);
  126. } catch (IOException ex) {
  127. if (!bNewConnection) {
  128. try {
  129. trackerServer.close();
  130. } catch (IOException ex1) {
  131. ex1.printStackTrace();
  132. }
  133. }
  134. throw ex;
  135. } finally {
  136. if (bNewConnection) {
  137. try {
  138. trackerServer.close();
  139. } catch (IOException ex1) {
  140. ex1.printStackTrace();
  141. }
  142. }
  143. }
  144. }
  145. /**
  146. * query storage servers to upload file
  147. *
  148. * @param trackerServer the tracker server
  149. * @param groupName the group name to upload file to, can be empty
  150. * @return storage servers, return null if fail
  151. */
  152. public StorageServer[] getStoreStorages(TrackerServer trackerServer, String groupName) throws IOException {
  153. byte[] header;
  154. String ip_addr;
  155. int port;
  156. byte cmd;
  157. int out_len;
  158. boolean bNewConnection;
  159. Socket trackerSocket;
  160. if (trackerServer == null) {
  161. trackerServer = getConnection();
  162. if (trackerServer == null) {
  163. return null;
  164. }
  165. bNewConnection = true;
  166. } else {
  167. bNewConnection = false;
  168. }
  169. trackerSocket = trackerServer.getSocket();
  170. OutputStream out = trackerSocket.getOutputStream();
  171. try {
  172. if (groupName == null || groupName.length() == 0) {
  173. cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL;
  174. out_len = 0;
  175. } else {
  176. cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL;
  177. out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
  178. }
  179. header = ProtoCommon.packHeader(cmd, out_len, (byte) 0);
  180. out.write(header);
  181. if (groupName != null && groupName.length() > 0) {
  182. byte[] bGroupName;
  183. byte[] bs;
  184. int group_len;
  185. bs = groupName.getBytes(ClientGlobal.g_charset);
  186. bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
  187. if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
  188. group_len = bs.length;
  189. } else {
  190. group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
  191. }
  192. Arrays.fill(bGroupName, (byte) 0);
  193. System.arraycopy(bs, 0, bGroupName, 0, group_len);
  194. out.write(bGroupName);
  195. }
  196. ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
  197. ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
  198. this.errno = pkgInfo.errno;
  199. if (pkgInfo.errno != 0) {
  200. return null;
  201. }
  202. if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN) {
  203. this.errno = ProtoCommon.ERR_NO_EINVAL;
  204. return null;
  205. }
  206. int ipPortLen = pkgInfo.body.length - (ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + 1);
  207. final int recordLength = ProtoCommon.FDFS_IPADDR_SIZE - 1 + ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;
  208. if (ipPortLen % recordLength != 0) {
  209. this.errno = ProtoCommon.ERR_NO_EINVAL;
  210. return null;
  211. }
  212. int serverCount = ipPortLen / recordLength;
  213. if (serverCount > 16) {
  214. this.errno = ProtoCommon.ERR_NO_ENOSPC;
  215. return null;
  216. }
  217. StorageServer[] results = new StorageServer[serverCount];
  218. byte store_path = pkgInfo.body[pkgInfo.body.length - 1];
  219. int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
  220. for (int i = 0; i < serverCount; i++) {
  221. ip_addr = new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim();
  222. offset += ProtoCommon.FDFS_IPADDR_SIZE - 1;
  223. port = (int) ProtoCommon.buff2long(pkgInfo.body, offset);
  224. offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;
  225. results[i] = new StorageServer(ip_addr, port, store_path);
  226. }
  227. return results;
  228. } catch (IOException ex) {
  229. if (!bNewConnection) {
  230. try {
  231. trackerServer.close();
  232. } catch (IOException ex1) {
  233. ex1.printStackTrace();
  234. }
  235. }
  236. throw ex;
  237. } finally {
  238. if (bNewConnection) {
  239. try {
  240. trackerServer.close();
  241. } catch (IOException ex1) {
  242. ex1.printStackTrace();
  243. }
  244. }
  245. }
  246. }
  247. /**
  248. * query storage server to download file
  249. *
  250. * @param trackerServer the tracker server
  251. * @param groupName the group name of storage server
  252. * @param filename filename on storage server
  253. * @return storage server Socket object, return null if fail
  254. */
  255. public StorageServer getFetchStorage(TrackerServer trackerServer,
  256. String groupName, String filename) throws IOException {
  257. ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE,
  258. groupName, filename);
  259. if (servers == null) {
  260. return null;
  261. } else {
  262. return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0);
  263. }
  264. }
  265. /**
  266. * query storage server to update file (delete file or set meta data)
  267. *
  268. * @param trackerServer the tracker server
  269. * @param groupName the group name of storage server
  270. * @param filename filename on storage server
  271. * @return storage server Socket object, return null if fail
  272. */
  273. public StorageServer getUpdateStorage(TrackerServer trackerServer,
  274. String groupName, String filename) throws IOException {
  275. ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE,
  276. groupName, filename);
  277. if (servers == null) {
  278. return null;
  279. } else {
  280. return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0);
  281. }
  282. }
  283. /**
  284. * get storage servers to download file
  285. *
  286. * @param trackerServer the tracker server
  287. * @param groupName the group name of storage server
  288. * @param filename filename on storage server
  289. * @return storage servers, return null if fail
  290. */
  291. public ServerInfo[] getFetchStorages(TrackerServer trackerServer,
  292. String groupName, String filename) throws IOException {
  293. return this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL,
  294. groupName, filename);
  295. }
  296. /**
  297. * query storage server to download file
  298. *
  299. * @param trackerServer the tracker server
  300. * @param cmd command code, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE or
  301. * ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE
  302. * @param groupName the group name of storage server
  303. * @param filename filename on storage server
  304. * @return storage server Socket object, return null if fail
  305. */
  306. protected ServerInfo[] getStorages(TrackerServer trackerServer,
  307. byte cmd, String groupName, String filename) throws IOException {
  308. byte[] header;
  309. byte[] bFileName;
  310. byte[] bGroupName;
  311. byte[] bs;
  312. int len;
  313. String ip_addr;
  314. int port;
  315. boolean bNewConnection;
  316. Socket trackerSocket;
  317. if (trackerServer == null) {
  318. trackerServer = getConnection();
  319. if (trackerServer == null) {
  320. return null;
  321. }
  322. bNewConnection = true;
  323. } else {
  324. bNewConnection = false;
  325. }
  326. trackerSocket = trackerServer.getSocket();
  327. OutputStream out = trackerSocket.getOutputStream();
  328. try {
  329. bs = groupName.getBytes(ClientGlobal.g_charset);
  330. bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
  331. bFileName = filename.getBytes(ClientGlobal.g_charset);
  332. if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
  333. len = bs.length;
  334. } else {
  335. len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
  336. }
  337. Arrays.fill(bGroupName, (byte) 0);
  338. System.arraycopy(bs, 0, bGroupName, 0, len);
  339. header = ProtoCommon.packHeader(cmd, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + bFileName.length, (byte) 0);
  340. byte[] wholePkg = new byte[header.length + bGroupName.length + bFileName.length];
  341. System.arraycopy(header, 0, wholePkg, 0, header.length);
  342. System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length);
  343. System.arraycopy(bFileName, 0, wholePkg, header.length + bGroupName.length, bFileName.length);
  344. out.write(wholePkg);
  345. ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
  346. ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
  347. this.errno = pkgInfo.errno;
  348. if (pkgInfo.errno != 0) {
  349. return null;
  350. }
  351. if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) {
  352. throw new IOException("Invalid body length: " + pkgInfo.body.length);
  353. }
  354. if ((pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) % (ProtoCommon.FDFS_IPADDR_SIZE - 1) != 0) {
  355. throw new IOException("Invalid body length: " + pkgInfo.body.length);
  356. }
  357. int server_count = 1 + (pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) / (ProtoCommon.FDFS_IPADDR_SIZE - 1);
  358. ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim();
  359. int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ProtoCommon.FDFS_IPADDR_SIZE - 1;
  360. port = (int) ProtoCommon.buff2long(pkgInfo.body, offset);
  361. offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;
  362. ServerInfo[] servers = new ServerInfo[server_count];
  363. servers[0] = new ServerInfo(ip_addr, port);
  364. for (int i = 1; i < server_count; i++) {
  365. servers[i] = new ServerInfo(new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(), port);
  366. offset += ProtoCommon.FDFS_IPADDR_SIZE - 1;
  367. }
  368. return servers;
  369. } catch (IOException ex) {
  370. if (!bNewConnection) {
  371. try {
  372. trackerServer.close();
  373. } catch (IOException ex1) {
  374. ex1.printStackTrace();
  375. }
  376. }
  377. throw ex;
  378. } finally {
  379. if (bNewConnection) {
  380. try {
  381. trackerServer.close();
  382. } catch (IOException ex1) {
  383. ex1.printStackTrace();
  384. }
  385. }
  386. }
  387. }
  388. /**
  389. * query storage server to download file
  390. *
  391. * @param trackerServer the tracker server
  392. * @param file_id the file id(including group name and filename)
  393. * @return storage server Socket object, return null if fail
  394. */
  395. public StorageServer getFetchStorage1(TrackerServer trackerServer, String file_id) throws IOException {
  396. String[] parts = new String[2];
  397. this.errno = StorageClient1.split_file_id(file_id, parts);
  398. if (this.errno != 0) {
  399. return null;
  400. }
  401. return this.getFetchStorage(trackerServer, parts[0], parts[1]);
  402. }
  403. /**
  404. * get storage servers to download file
  405. *
  406. * @param trackerServer the tracker server
  407. * @param file_id the file id(including group name and filename)
  408. * @return storage servers, return null if fail
  409. */
  410. public ServerInfo[] getFetchStorages1(TrackerServer trackerServer, String file_id) throws IOException {
  411. String[] parts = new String[2];
  412. this.errno = StorageClient1.split_file_id(file_id, parts);
  413. if (this.errno != 0) {
  414. return null;
  415. }
  416. return this.getFetchStorages(trackerServer, parts[0], parts[1]);
  417. }
  418. /**
  419. * list groups
  420. *
  421. * @param trackerServer the tracker server
  422. * @return group stat array, return null if fail
  423. */
  424. public StructGroupStat[] listGroups(TrackerServer trackerServer) throws IOException {
  425. byte[] header;
  426. String ip_addr;
  427. int port;
  428. byte cmd;
  429. int out_len;
  430. boolean bNewConnection;
  431. byte store_path;
  432. Socket trackerSocket;
  433. if (trackerServer == null) {
  434. trackerServer = getConnection();
  435. if (trackerServer == null) {
  436. return null;
  437. }
  438. bNewConnection = true;
  439. } else {
  440. bNewConnection = false;
  441. }
  442. trackerSocket = trackerServer.getSocket();
  443. OutputStream out = trackerSocket.getOutputStream();
  444. try {
  445. header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_GROUP, 0, (byte) 0);
  446. out.write(header);
  447. ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
  448. ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
  449. this.errno = pkgInfo.errno;
  450. if (pkgInfo.errno != 0) {
  451. return null;
  452. }
  453. ProtoStructDecoder<StructGroupStat> decoder = new ProtoStructDecoder<StructGroupStat>();
  454. return decoder.decode(pkgInfo.body, StructGroupStat.class, StructGroupStat.getFieldsTotalSize());
  455. } catch (IOException ex) {
  456. if (!bNewConnection) {
  457. try {
  458. trackerServer.close();
  459. } catch (IOException ex1) {
  460. ex1.printStackTrace();
  461. }
  462. }
  463. throw ex;
  464. } catch (Exception ex) {
  465. ex.printStackTrace();
  466. this.errno = ProtoCommon.ERR_NO_EINVAL;
  467. return null;
  468. } finally {
  469. if (bNewConnection) {
  470. try {
  471. trackerServer.close();
  472. } catch (IOException ex1) {
  473. ex1.printStackTrace();
  474. }
  475. }
  476. }
  477. }
  478. /**
  479. * query storage server stat info of the group
  480. *
  481. * @param trackerServer the tracker server
  482. * @param groupName the group name of storage server
  483. * @return storage server stat array, return null if fail
  484. */
  485. public StructStorageStat[] listStorages(TrackerServer trackerServer, String groupName) throws IOException {
  486. final String storageIpAddr = null;
  487. return this.listStorages(trackerServer, groupName, storageIpAddr);
  488. }
  489. /**
  490. * query storage server stat info of the group
  491. *
  492. * @param trackerServer the tracker server
  493. * @param groupName the group name of storage server
  494. * @param storageIpAddr the storage server ip address, can be null or empty
  495. * @return storage server stat array, return null if fail
  496. */
  497. public StructStorageStat[] listStorages(TrackerServer trackerServer,
  498. String groupName, String storageIpAddr) throws IOException {
  499. byte[] header;
  500. byte[] bGroupName;
  501. byte[] bs;
  502. int len;
  503. boolean bNewConnection;
  504. Socket trackerSocket;
  505. if (trackerServer == null) {
  506. trackerServer = getConnection();
  507. if (trackerServer == null) {
  508. return null;
  509. }
  510. bNewConnection = true;
  511. } else {
  512. bNewConnection = false;
  513. }
  514. trackerSocket = trackerServer.getSocket();
  515. OutputStream out = trackerSocket.getOutputStream();
  516. try {
  517. bs = groupName.getBytes(ClientGlobal.g_charset);
  518. bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
  519. if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
  520. len = bs.length;
  521. } else {
  522. len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
  523. }
  524. Arrays.fill(bGroupName, (byte) 0);
  525. System.arraycopy(bs, 0, bGroupName, 0, len);
  526. int ipAddrLen;
  527. byte[] bIpAddr;
  528. if (storageIpAddr != null && storageIpAddr.length() > 0) {
  529. bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset);
  530. if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) {
  531. ipAddrLen = bIpAddr.length;
  532. } else {
  533. ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1;
  534. }
  535. } else {
  536. bIpAddr = null;
  537. ipAddrLen = 0;
  538. }
  539. header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0);
  540. byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen];
  541. System.arraycopy(header, 0, wholePkg, 0, header.length);
  542. System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length);
  543. if (ipAddrLen > 0) {
  544. System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen);
  545. }
  546. out.write(wholePkg);
  547. ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
  548. ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
  549. this.errno = pkgInfo.errno;
  550. if (pkgInfo.errno != 0) {
  551. return null;
  552. }
  553. ProtoStructDecoder<StructStorageStat> decoder = new ProtoStructDecoder<StructStorageStat>();
  554. return decoder.decode(pkgInfo.body, StructStorageStat.class, StructStorageStat.getFieldsTotalSize());
  555. } catch (IOException ex) {
  556. if (!bNewConnection) {
  557. try {
  558. trackerServer.close();
  559. } catch (IOException ex1) {
  560. ex1.printStackTrace();
  561. }
  562. }
  563. throw ex;
  564. } catch (Exception ex) {
  565. ex.printStackTrace();
  566. this.errno = ProtoCommon.ERR_NO_EINVAL;
  567. return null;
  568. } finally {
  569. if (bNewConnection) {
  570. try {
  571. trackerServer.close();
  572. } catch (IOException ex1) {
  573. ex1.printStackTrace();
  574. }
  575. }
  576. }
  577. }
  578. /**
  579. * delete a storage server from the tracker server
  580. *
  581. * @param trackerServer the connected tracker server
  582. * @param groupName the group name of storage server
  583. * @param storageIpAddr the storage server ip address
  584. * @return true for success, false for fail
  585. */
  586. private boolean deleteStorage(TrackerServer trackerServer,
  587. String groupName, String storageIpAddr) throws IOException {
  588. byte[] header;
  589. byte[] bGroupName;
  590. byte[] bs;
  591. int len;
  592. Socket trackerSocket;
  593. trackerSocket = trackerServer.getSocket();
  594. OutputStream out = trackerSocket.getOutputStream();
  595. bs = groupName.getBytes(ClientGlobal.g_charset);
  596. bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
  597. if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
  598. len = bs.length;
  599. } else {
  600. len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
  601. }
  602. Arrays.fill(bGroupName, (byte) 0);
  603. System.arraycopy(bs, 0, bGroupName, 0, len);
  604. int ipAddrLen;
  605. byte[] bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset);
  606. if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) {
  607. ipAddrLen = bIpAddr.length;
  608. } else {
  609. ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1;
  610. }
  611. header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0);
  612. byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen];
  613. System.arraycopy(header, 0, wholePkg, 0, header.length);
  614. System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length);
  615. System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen);
  616. out.write(wholePkg);
  617. ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
  618. ProtoCommon.TRACKER_PROTO_CMD_RESP, 0);
  619. this.errno = pkgInfo.errno;
  620. return pkgInfo.errno == 0;
  621. }
  622. /**
  623. * delete a storage server from the global FastDFS cluster
  624. *
  625. * @param groupName the group name of storage server
  626. * @param storageIpAddr the storage server ip address
  627. * @return true for success, false for fail
  628. */
  629. public boolean deleteStorage(String groupName, String storageIpAddr) throws IOException {
  630. return this.deleteStorage(ClientGlobal.g_tracker_group, groupName, storageIpAddr);
  631. }
  632. /**
  633. * delete a storage server from the FastDFS cluster
  634. *
  635. * @param trackerGroup the tracker server group
  636. * @param groupName the group name of storage server
  637. * @param storageIpAddr the storage server ip address
  638. * @return true for success, false for fail
  639. */
  640. public boolean deleteStorage(TrackerGroup trackerGroup,
  641. String groupName, String storageIpAddr) throws IOException {
  642. int serverIndex;
  643. int notFoundCount;
  644. TrackerServer trackerServer;
  645. notFoundCount = 0;
  646. for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) {
  647. try {
  648. trackerServer = trackerGroup.getConnection(serverIndex);
  649. } catch (IOException ex) {
  650. ex.printStackTrace(System.err);
  651. this.errno = ProtoCommon.ECONNREFUSED;
  652. return false;
  653. }
  654. try {
  655. StructStorageStat[] storageStats = listStorages(trackerServer, groupName, storageIpAddr);
  656. if (storageStats == null) {
  657. if (this.errno == ProtoCommon.ERR_NO_ENOENT) {
  658. notFoundCount++;
  659. } else {
  660. return false;
  661. }
  662. } else if (storageStats.length == 0) {
  663. notFoundCount++;
  664. } else if (storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ONLINE ||
  665. storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ACTIVE) {
  666. this.errno = ProtoCommon.ERR_NO_EBUSY;
  667. return false;
  668. }
  669. } finally {
  670. try {
  671. trackerServer.close();
  672. } catch (IOException ex1) {
  673. ex1.printStackTrace();
  674. }
  675. }
  676. }
  677. if (notFoundCount == trackerGroup.tracker_servers.length) {
  678. this.errno = ProtoCommon.ERR_NO_ENOENT;
  679. return false;
  680. }
  681. notFoundCount = 0;
  682. for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) {
  683. try {
  684. trackerServer = trackerGroup.getConnection(serverIndex);
  685. } catch (IOException ex) {
  686. System.err.println("connect to server " + trackerGroup.tracker_servers[serverIndex].getAddress().getHostAddress() + ":" + trackerGroup.tracker_servers[serverIndex].getPort() + " fail");
  687. ex.printStackTrace(System.err);
  688. this.errno = ProtoCommon.ECONNREFUSED;
  689. return false;
  690. }
  691. try {
  692. if (!this.deleteStorage(trackerServer, groupName, storageIpAddr)) {
  693. if (this.errno != 0) {
  694. if (this.errno == ProtoCommon.ERR_NO_ENOENT) {
  695. notFoundCount++;
  696. } else if (this.errno != ProtoCommon.ERR_NO_EALREADY) {
  697. return false;
  698. }
  699. }
  700. }
  701. } finally {
  702. try {
  703. trackerServer.close();
  704. } catch (IOException ex1) {
  705. ex1.printStackTrace();
  706. }
  707. }
  708. }
  709. if (notFoundCount == trackerGroup.tracker_servers.length) {
  710. this.errno = ProtoCommon.ERR_NO_ENOENT;
  711. return false;
  712. }
  713. if (this.errno == ProtoCommon.ERR_NO_ENOENT) {
  714. this.errno = 0;
  715. }
  716. return this.errno == 0;
  717. }
  718. }