From 32167310ddcc5331ddb80276f95acd566f1152a3 Mon Sep 17 00:00:00 2001 From: tanyawen Date: Sun, 29 Dec 2019 03:28:26 +0800 Subject: [PATCH] feature:add connection pool v2 --- fastdfs-client.properties | 4 +- fdfs_client.conf | 4 +- .../org/csource/fastdfs/ClientGlobal.java | 27 +- .../org/csource/fastdfs/StorageClient.java | 3669 ++++++++--------- .../org/csource/fastdfs/TrackerClient.java | 1507 ++++--- .../org/csource/fastdfs/TrackerGroup.java | 9 +- .../org/csource/fastdfs/TrackerServer.java | 125 +- .../org/csource/fastdfs/pool/Connection.java | 107 + ...ionFactory.java => ConnectionFactory.java} | 21 +- .../csource/fastdfs/pool/ConnectionInfo.java | 60 - .../fastdfs/pool/ConnectionManager.java | 74 +- .../csource/fastdfs/pool/ConnectionPool.java | 62 +- src/main/resources/fastdfs-client.properties | 2 +- .../fastdfs-client.properties.sample | 2 +- src/main/resources/fdfs_client.conf.sample | 2 +- .../java/org/csource/fastdfs/FdfsTest.java | 2 +- .../java/org/csource/fastdfs/Monitor.java | 6 +- src/test/java/org/csource/fastdfs/Test.java | 5 +- src/test/java/org/csource/fastdfs/Test1.java | 5 +- .../org/csource/fastdfs/TestAppender.java | 11 +- .../org/csource/fastdfs/TestAppender1.java | 478 ++- .../java/org/csource/fastdfs/TestClient.java | 502 ++- .../java/org/csource/fastdfs/TestClient1.java | 431 +- .../java/org/csource/fastdfs/TestLoad.java | 6 +- 24 files changed, 3451 insertions(+), 3670 deletions(-) create mode 100644 src/main/java/org/csource/fastdfs/pool/Connection.java rename src/main/java/org/csource/fastdfs/pool/{PoolConnectionFactory.java => ConnectionFactory.java} (58%) delete mode 100644 src/main/java/org/csource/fastdfs/pool/ConnectionInfo.java diff --git a/fastdfs-client.properties b/fastdfs-client.properties index df66a20..54e30eb 100644 --- a/fastdfs-client.properties +++ b/fastdfs-client.properties @@ -19,5 +19,5 @@ fastdfs.connection_pool.max_count_per_entry = 100 ## connections whose the idle time exceeds this time will be closed, unit: second,default value is 60 fastdfs.connection_pool.max_idle_time = 60 -## Maximum waiting time when the maximum number of connections is reached, unit: second, default value is 5 -fastdfs.connection_pool.max_wait_time = 5 +## Maximum waiting time when the maximum number of connections is reached, unit: Millisecond, default value is 5000 +fastdfs.connection_pool.max_wait_time_in_ms = 5000 diff --git a/fdfs_client.conf b/fdfs_client.conf index 1f2029a..7cabb47 100644 --- a/fdfs_client.conf +++ b/fdfs_client.conf @@ -9,7 +9,7 @@ tracker_server = 10.0.11.247:22122 tracker_server = 10.0.11.248:22122 tracker_server = 10.0.11.249:22122 -connection_pool.enabled = false +connection_pool.enabled = true connection_pool.max_count_per_entry = 100 connection_pool.max_idle_time = 60 -connection_pool.max_wait_time = 5 +connection_pool.max_wait_time_in_ms = 5000 diff --git a/src/main/java/org/csource/fastdfs/ClientGlobal.java b/src/main/java/org/csource/fastdfs/ClientGlobal.java index 4773f4a..fe8baef 100644 --- a/src/main/java/org/csource/fastdfs/ClientGlobal.java +++ b/src/main/java/org/csource/fastdfs/ClientGlobal.java @@ -46,7 +46,7 @@ public class ClientGlobal { public static final String PROP_KEY_CONNECTION_POOL_ENABLED = "fastdfs.connection_pool.enabled"; public static final String PROP_KEY_CONNECTION_POOL_MAX_COUNT_PER_ENTRY = "fastdfs.connection_pool.max_count_per_entry"; public static final String PROP_KEY_CONNECTION_POOL_MAX_IDLE_TIME = "fastdfs.connection_pool.max_idle_time"; - public static final String PROP_KEY_CONNECTION_POOL_MAX_WAIT_TIME = "fastdfs.connection_pool.max_wait_time"; + public static final String PROP_KEY_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS = "fastdfs.connection_pool.max_wait_time_in_ms"; public static final int DEFAULT_CONNECT_TIMEOUT = 5; //second @@ -56,10 +56,10 @@ public class ClientGlobal { public static final String DEFAULT_HTTP_SECRET_KEY = "FastDFS1234567890"; public static final int DEFAULT_HTTP_TRACKER_HTTP_PORT = 80; - public static final boolean DEFAULT_CONNECTION_POOL_ENABLED = true; + public static final boolean DEFAULT_CONNECTION_POOL_ENABLED = false; public static final int DEFAULT_CONNECTION_POOL_MAX_COUNT_PER_ENTRY = 100; public static final int DEFAULT_CONNECTION_POOL_MAX_IDLE_TIME = 60 ;//second - public static final int DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME = 5 ;//second + public static final int DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS = 5000 ;//millisecond public static int g_connect_timeout = DEFAULT_CONNECT_TIMEOUT * 1000; //millisecond public static int g_network_timeout = DEFAULT_NETWORK_TIMEOUT * 1000; //millisecond @@ -71,7 +71,7 @@ public class ClientGlobal { public static boolean g_connection_pool_enabled = DEFAULT_CONNECTION_POOL_ENABLED; public static int g_connection_pool_max_count_per_entry = DEFAULT_CONNECTION_POOL_MAX_COUNT_PER_ENTRY; public static int g_connection_pool_max_idle_time = DEFAULT_CONNECTION_POOL_MAX_IDLE_TIME * 1000; //millisecond - public static int g_connection_pool_max_wait_time = DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME * 1000; //millisecond + public static int g_connection_pool_max_wait_time_in_ms = DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS; //millisecond public static TrackerGroup g_tracker_group; @@ -135,11 +135,10 @@ public class ClientGlobal { g_connection_pool_max_idle_time = DEFAULT_CONNECTION_POOL_MAX_IDLE_TIME; } g_connection_pool_max_idle_time *= 1000; - g_connection_pool_max_wait_time = iniReader.getIntValue("connection_pool.max_wait_time", DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME); - if (g_connection_pool_max_wait_time < 0) { - g_connection_pool_max_wait_time = DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME; + g_connection_pool_max_wait_time_in_ms = iniReader.getIntValue("connection_pool.max_wait_time_in_ms", DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS); + if (g_connection_pool_max_wait_time_in_ms < 0) { + g_connection_pool_max_wait_time_in_ms = DEFAULT_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS; } - g_connection_pool_max_wait_time *= 1000; } /** @@ -180,7 +179,7 @@ public class ClientGlobal { String poolEnabled = props.getProperty(PROP_KEY_CONNECTION_POOL_ENABLED); String poolMaxCountPerEntry = props.getProperty(PROP_KEY_CONNECTION_POOL_MAX_COUNT_PER_ENTRY); String poolMaxIdleTime = props.getProperty(PROP_KEY_CONNECTION_POOL_MAX_IDLE_TIME); - String poolMaxWaitTime = props.getProperty(PROP_KEY_CONNECTION_POOL_MAX_WAIT_TIME); + String poolMaxWaitTimeInMS = props.getProperty(PROP_KEY_CONNECTION_POOL_MAX_WAIT_TIME_IN_MS); if (connectTimeoutInSecondsConf != null && connectTimeoutInSecondsConf.trim().length() != 0) { g_connect_timeout = Integer.parseInt(connectTimeoutInSecondsConf.trim()) * 1000; @@ -209,8 +208,8 @@ public class ClientGlobal { if (poolMaxIdleTime != null && poolMaxIdleTime.trim().length() != 0) { g_connection_pool_max_idle_time = Integer.parseInt(poolMaxIdleTime) * 1000; } - if (poolMaxWaitTime != null && poolMaxWaitTime.trim().length() != 0) { - g_connection_pool_max_wait_time = Integer.parseInt(poolMaxWaitTime) * 1000; + if (poolMaxWaitTimeInMS != null && poolMaxWaitTimeInMS.trim().length() != 0) { + g_connection_pool_max_wait_time_in_ms = Integer.parseInt(poolMaxWaitTimeInMS) * 1000; } } @@ -340,8 +339,8 @@ public class ClientGlobal { return g_connection_pool_max_idle_time; } - public static int getG_connection_pool_max_wait_time() { - return g_connection_pool_max_wait_time; + public static int getG_connection_pool_max_wait_time_in_ms() { + return g_connection_pool_max_wait_time_in_ms; } public static String configInfo() { @@ -363,7 +362,7 @@ public class ClientGlobal { + "\n g_connection_pool_enabled = " + g_connection_pool_enabled + "\n g_connection_pool_max_count_per_entry = " + g_connection_pool_max_count_per_entry + "\n g_connection_pool_max_idle_time = " + g_connection_pool_max_idle_time - + "\n g_connection_pool_max_wait_time = " + g_connection_pool_max_wait_time + + "\n g_connection_pool_max_wait_time_in_ms = " + g_connection_pool_max_wait_time_in_ms + "\n trackerServers = " + trackerServers + "\n}"; } diff --git a/src/main/java/org/csource/fastdfs/StorageClient.java b/src/main/java/org/csource/fastdfs/StorageClient.java index d1d2045..9b966b6 100644 --- a/src/main/java/org/csource/fastdfs/StorageClient.java +++ b/src/main/java/org/csource/fastdfs/StorageClient.java @@ -11,6 +11,8 @@ package org.csource.fastdfs; import org.csource.common.Base64; import org.csource.common.MyException; import org.csource.common.NameValuePair; +import org.csource.fastdfs.pool.Connection; +import org.omg.CORBA.CODESET_INCOMPATIBLE; import java.io.*; import java.net.Socket; @@ -19,1914 +21,1789 @@ import java.util.Arrays; /** * Storage client for 2 fields file id: group name and filename * Note: the instance of this class is NOT thread safe !!! - * if not necessary, do NOT set storage server instance + * if not necessary, do NOT set storage server instance * * @author Happy Fish / YuQing * @version Version 1.27 */ public class StorageClient { - public final static Base64 base64 = new Base64('-', '_', '.', 0); - protected TrackerServer trackerServer; - protected StorageServer storageServer; - protected byte errno; - - /** - * constructor using global settings in class ClientGlobal - */ - public StorageClient() { - this.trackerServer = null; - this.storageServer = null; - } - - /** - * constructor with tracker server - * - * @param trackerServer the tracker server, can be null - */ - public StorageClient(TrackerServer trackerServer) { - this.trackerServer = trackerServer; - this.storageServer = null; - } - - /** - * constructor with tracker server and storage server - * NOTE: if not necessary, do NOT set storage server instance - * - * @param trackerServer the tracker server, can be null - * @param storageServer the storage server, can be null - */ - public StorageClient(TrackerServer trackerServer, StorageServer storageServer) { - this.trackerServer = trackerServer; - this.storageServer = storageServer; - } - - /** - * get the error code of last call - * - * @return the error code of last call - */ - public byte getErrorCode() { - return this.errno; - } - - /** - * upload file to storage server (by file name) - * - * @param local_filename local filename to upload - * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(String local_filename, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - final String group_name = null; - return this.upload_file(group_name, local_filename, file_ext_name, meta_list); - } - - /** - * upload file to storage server (by file name) - * - * @param group_name the group name to upload file to, can be empty - * @param local_filename local filename to upload - * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - protected String[] upload_file(String group_name, String local_filename, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - final byte cmd = ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE; - return this.upload_file(cmd, group_name, local_filename, file_ext_name, meta_list); - } - - /** - * upload file to storage server (by file name) - * - * @param cmd the command - * @param group_name the group name to upload file to, can be empty - * @param local_filename local filename to upload - * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - protected String[] upload_file(byte cmd, String group_name, String local_filename, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - File f = new File(local_filename); - FileInputStream fis = new FileInputStream(f); - - if (file_ext_name == null) { - int nPos = local_filename.lastIndexOf('.'); - if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { - file_ext_name = local_filename.substring(nPos + 1); - } - } - - try { - return this.do_upload_file(cmd, group_name, null, null, file_ext_name, - f.length(), new UploadStream(fis, f.length()), meta_list); - } finally { - fis.close(); - } - } - - /** - * upload file to storage server (by file buff) - * - * @param file_buff file content/buff - * @param offset start offset of the buff - * @param length the length of buff to upload - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(byte[] file_buff, int offset, int length, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - final String group_name = null; - return this.upload_file(group_name, file_buff, offset, length, file_ext_name, meta_list); - } - - /** - * upload file to storage server (by file buff) - * - * @param group_name the group name to upload file to, can be empty - * @param file_buff file content/buff - * @param offset start offset of the buff - * @param length the length of buff to upload - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(String group_name, byte[] file_buff, int offset, int length, - String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, null, null, file_ext_name, - length, new UploadBuff(file_buff, offset, length), meta_list); - } - - /** - * upload file to storage server (by file buff) - * - * @param file_buff file content/buff - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(byte[] file_buff, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - final String group_name = null; - return this.upload_file(group_name, file_buff, 0, file_buff.length, file_ext_name, meta_list); - } - - /** - * upload file to storage server (by file buff) - * - * @param group_name the group name to upload file to, can be empty - * @param file_buff file content/buff - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(String group_name, byte[] file_buff, - String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, null, null, file_ext_name, - file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); - } - - /** - * upload file to storage server (by callback) - * - * @param group_name the group name to upload file to, can be empty - * @param file_size the file size - * @param callback the write data callback object - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(String group_name, long file_size, UploadCallback callback, - String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - final String master_filename = null; - final String prefix_name = null; - - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, master_filename, prefix_name, - file_ext_name, file_size, callback, meta_list); - } - - /** - * upload file to storage server (by file name, slave file mode) - * - * @param group_name the group name of master file - * @param master_filename the master file name to generate the slave file - * @param prefix_name the prefix name to generate the slave file - * @param local_filename local filename to upload - * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(String group_name, String master_filename, String prefix_name, - String local_filename, String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - if ((group_name == null || group_name.length() == 0) || - (master_filename == null || master_filename.length() == 0) || - (prefix_name == null)) { - throw new MyException("invalid arguement"); - } - - File f = new File(local_filename); - FileInputStream fis = new FileInputStream(f); - - if (file_ext_name == null) { - int nPos = local_filename.lastIndexOf('.'); - if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { - file_ext_name = local_filename.substring(nPos + 1); - } - } - - try { - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, - file_ext_name, f.length(), new UploadStream(fis, f.length()), meta_list); - } finally { - fis.close(); - } - } - - /** - * upload file to storage server (by file buff, slave file mode) - * - * @param group_name the group name of master file - * @param master_filename the master file name to generate the slave file - * @param prefix_name the prefix name to generate the slave file - * @param file_buff file content/buff - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(String group_name, String master_filename, String prefix_name, - byte[] file_buff, String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - if ((group_name == null || group_name.length() == 0) || - (master_filename == null || master_filename.length() == 0) || - (prefix_name == null)) { - throw new MyException("invalid arguement"); - } - - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, - file_ext_name, file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); - } - - /** - * upload file to storage server (by file buff, slave file mode) - * - * @param group_name the group name of master file - * @param master_filename the master file name to generate the slave file - * @param prefix_name the prefix name to generate the slave file - * @param file_buff file content/buff - * @param offset start offset of the buff - * @param length the length of buff to upload - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(String group_name, String master_filename, String prefix_name, - byte[] file_buff, int offset, int length, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - if ((group_name == null || group_name.length() == 0) || - (master_filename == null || master_filename.length() == 0) || - (prefix_name == null)) { - throw new MyException("invalid arguement"); - } - - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, - file_ext_name, length, new UploadBuff(file_buff, offset, length), meta_list); - } - - /** - * upload file to storage server (by callback, slave file mode) - * - * @param group_name the group name to upload file to, can be empty - * @param master_filename the master file name to generate the slave file - * @param prefix_name the prefix name to generate the slave file - * @param file_size the file size - * @param callback the write data callback object - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_file(String group_name, String master_filename, - String prefix_name, long file_size, UploadCallback callback, - String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, - file_ext_name, file_size, callback, meta_list); - } - - /** - * upload appender file to storage server (by file name) - * - * @param local_filename local filename to upload - * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_appender_file(String local_filename, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - final String group_name = null; - return this.upload_appender_file(group_name, local_filename, file_ext_name, meta_list); - } - - /** - * upload appender file to storage server (by file name) - * - * @param group_name the group name to upload file to, can be empty - * @param local_filename local filename to upload - * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - protected String[] upload_appender_file(String group_name, String local_filename, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - final byte cmd = ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE; - return this.upload_file(cmd, group_name, local_filename, file_ext_name, meta_list); - } - - /** - * upload appender file to storage server (by file buff) - * - * @param file_buff file content/buff - * @param offset start offset of the buff - * @param length the length of buff to upload - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_appender_file(byte[] file_buff, int offset, int length, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - final String group_name = null; - return this.upload_appender_file(group_name, file_buff, offset, length, file_ext_name, meta_list); - } - - /** - * upload appender file to storage server (by file buff) - * - * @param group_name the group name to upload file to, can be empty - * @param file_buff file content/buff - * @param offset start offset of the buff - * @param length the length of buff to upload - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_appender_file(String group_name, byte[] file_buff, int offset, int length, - String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, null, null, file_ext_name, - length, new UploadBuff(file_buff, offset, length), meta_list); - } - - /** - * upload appender file to storage server (by file buff) - * - * @param file_buff file content/buff - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_appender_file(byte[] file_buff, String file_ext_name, - NameValuePair[] meta_list) throws IOException, MyException { - final String group_name = null; - return this.upload_appender_file(group_name, file_buff, 0, file_buff.length, file_ext_name, meta_list); - } - - /** - * upload appender file to storage server (by file buff) - * - * @param group_name the group name to upload file to, can be empty - * @param file_buff file content/buff - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_appender_file(String group_name, byte[] file_buff, - String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, null, null, file_ext_name, - file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); - } - - /** - * upload appender file to storage server (by callback) - * - * @param group_name the group name to upload file to, can be empty - * @param file_size the file size - * @param callback the write data callback object - * @param file_ext_name file ext name, do not include dot(.) - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] upload_appender_file(String group_name, long file_size, UploadCallback callback, - String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { - final String master_filename = null; - final String prefix_name = null; - - return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, master_filename, prefix_name, - file_ext_name, file_size, callback, meta_list); - } - - /** - * append file to storage server (by file name) - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @param local_filename local filename to append - * @return 0 for success, != 0 for error (error no) - */ - public int append_file(String group_name, String appender_filename, String local_filename) throws IOException, MyException { - File f = new File(local_filename); - FileInputStream fis = new FileInputStream(f); - - try { - return this.do_append_file(group_name, appender_filename, f.length(), new UploadStream(fis, f.length())); - } finally { - fis.close(); - } - } - - /** - * append file to storage server (by file buff) - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @param file_buff file content/buff - * @return 0 for success, != 0 for error (error no) - */ - public int append_file(String group_name, String appender_filename, byte[] file_buff) throws IOException, MyException { - return this.do_append_file(group_name, appender_filename, file_buff.length, new UploadBuff(file_buff, 0, file_buff.length)); - } - - /** - * append file to storage server (by file buff) - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @param file_buff file content/buff - * @param offset start offset of the buff - * @param length the length of buff to append - * @return 0 for success, != 0 for error (error no) - */ - public int append_file(String group_name, String appender_filename, - byte[] file_buff, int offset, int length) throws IOException, MyException { - return this.do_append_file(group_name, appender_filename, length, new UploadBuff(file_buff, offset, length)); - } - - /** - * append file to storage server (by callback) - * - * @param group_name the group name to append file to - * @param appender_filename the appender filename - * @param file_size the file size - * @param callback the write data callback object - * @return 0 for success, != 0 for error (error no) - */ - public int append_file(String group_name, String appender_filename, - long file_size, UploadCallback callback) throws IOException, MyException { - return this.do_append_file(group_name, appender_filename, file_size, callback); - } - - /** - * modify appender file to storage server (by file name) - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @param file_offset the offset of appender file - * @param local_filename local filename to append - * @return 0 for success, != 0 for error (error no) - */ - public int modify_file(String group_name, String appender_filename, - long file_offset, String local_filename) throws IOException, MyException { - File f = new File(local_filename); - FileInputStream fis = new FileInputStream(f); - - try { - return this.do_modify_file(group_name, appender_filename, file_offset, - f.length(), new UploadStream(fis, f.length())); - } finally { - fis.close(); - } - } - - /** - * modify appender file to storage server (by file buff) - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @param file_offset the offset of appender file - * @param file_buff file content/buff - * @return 0 for success, != 0 for error (error no) - */ - public int modify_file(String group_name, String appender_filename, - long file_offset, byte[] file_buff) throws IOException, MyException { - return this.do_modify_file(group_name, appender_filename, file_offset, - file_buff.length, new UploadBuff(file_buff, 0, file_buff.length)); - } - - /** - * modify appender file to storage server (by file buff) - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @param file_offset the offset of appender file - * @param file_buff file content/buff - * @param buffer_offset start offset of the buff - * @param buffer_length the length of buff to modify - * @return 0 for success, != 0 for error (error no) - */ - public int modify_file(String group_name, String appender_filename, - long file_offset, byte[] file_buff, int buffer_offset, int buffer_length) throws IOException, MyException { - return this.do_modify_file(group_name, appender_filename, file_offset, - buffer_length, new UploadBuff(file_buff, buffer_offset, buffer_length)); - } - - /** - * modify appender file to storage server (by callback) - * - * @param group_name the group name to modify file to - * @param appender_filename the appender filename - * @param file_offset the offset of appender file - * @param modify_size the modify size - * @param callback the write data callback object - * @return 0 for success, != 0 for error (error no) - */ - public int modify_file(String group_name, String appender_filename, - long file_offset, long modify_size, UploadCallback callback) throws IOException, MyException { - return this.do_modify_file(group_name, appender_filename, file_offset, - modify_size, callback); - } - - /** - * regenerate filename for appender file - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - public String[] regenerate_appender_filename(String group_name, String appender_filename) throws IOException, MyException { - byte[] header; - boolean bNewConnection; - Socket storageSocket; - byte[] hexLenBytes; - byte[] appenderFilenameBytes; - int offset; - long body_len; - - if ((group_name == null || group_name.length() == 0) || - (appender_filename == null || appender_filename.length() == 0)) { - this.errno = ProtoCommon.ERR_NO_EINVAL; - return null; - } - - bNewConnection = this.newUpdatableStorageConnection(group_name, appender_filename); - - try { - storageSocket = this.storageServer.getSocket(); - - appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); - body_len = appenderFilenameBytes.length; - - header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_REGENERATE_APPENDER_FILENAME, body_len, (byte) 0); - byte[] wholePkg = new byte[(int) (header.length + body_len)]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - offset = header.length; - - System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); - offset += appenderFilenameBytes.length; - - OutputStream out = storageSocket.getOutputStream(); - out.write(wholePkg); - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - if (pkgInfo.body.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { - throw new MyException("body length: " + pkgInfo.body.length + " <= " + ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); - } - - String new_group_name = new String(pkgInfo.body, 0, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN).trim(); - String remote_filename = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, - pkgInfo.body.length - ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); - String[] results = new String[2]; - results[0] = new_group_name; - results[1] = remote_filename; - - return results; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * upload file to storage server - * - * @param cmd the command code - * @param group_name the group name to upload file to, can be empty - * @param master_filename the master file name to generate the slave file - * @param prefix_name the prefix name to generate the slave file - * @param file_ext_name file ext name, do not include dot(.) - * @param file_size the file size - * @param callback the write data callback object - * @param meta_list meta info array - * @return 2 elements string array if success:
- * - * - * return null if fail - */ - protected String[] do_upload_file(byte cmd, String group_name, String master_filename, - String prefix_name, String file_ext_name, long file_size, UploadCallback callback, - NameValuePair[] meta_list) throws IOException, MyException { - byte[] header; - byte[] ext_name_bs; - String new_group_name; - String remote_filename; - boolean bNewConnection; - Socket storageSocket; - byte[] sizeBytes; - byte[] hexLenBytes; - byte[] masterFilenameBytes; - boolean bUploadSlave; - int offset; - long body_len; - - bUploadSlave = ((group_name != null && group_name.length() > 0) && - (master_filename != null && master_filename.length() > 0) && - (prefix_name != null)); - if (bUploadSlave) { - bNewConnection = this.newUpdatableStorageConnection(group_name, master_filename); - } else { - bNewConnection = this.newWritableStorageConnection(group_name); - } - - try { - storageSocket = this.storageServer.getSocket(); - - ext_name_bs = new byte[ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN]; - Arrays.fill(ext_name_bs, (byte) 0); - if (file_ext_name != null && file_ext_name.length() > 0) { - byte[] bs = file_ext_name.getBytes(ClientGlobal.g_charset); - int ext_name_len = bs.length; - if (ext_name_len > ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN) { - ext_name_len = ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN; - } - System.arraycopy(bs, 0, ext_name_bs, 0, ext_name_len); - } - - if (bUploadSlave) { - masterFilenameBytes = master_filename.getBytes(ClientGlobal.g_charset); - - sizeBytes = new byte[2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; - body_len = sizeBytes.length + ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN - + masterFilenameBytes.length + file_size; - - hexLenBytes = ProtoCommon.long2buff(master_filename.length()); - System.arraycopy(hexLenBytes, 0, sizeBytes, 0, hexLenBytes.length); - offset = hexLenBytes.length; - } else { - masterFilenameBytes = null; - sizeBytes = new byte[1 + 1 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; - body_len = sizeBytes.length + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + file_size; - - sizeBytes[0] = (byte) this.storageServer.getStorePathIndex(); - offset = 1; - } - - hexLenBytes = ProtoCommon.long2buff(file_size); - System.arraycopy(hexLenBytes, 0, sizeBytes, offset, hexLenBytes.length); - - OutputStream out = storageSocket.getOutputStream(); - header = ProtoCommon.packHeader(cmd, body_len, (byte) 0); - byte[] wholePkg = new byte[(int) (header.length + body_len - file_size)]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - System.arraycopy(sizeBytes, 0, wholePkg, header.length, sizeBytes.length); - offset = header.length + sizeBytes.length; - if (bUploadSlave) { - byte[] prefix_name_bs = new byte[ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN]; - byte[] bs = prefix_name.getBytes(ClientGlobal.g_charset); - int prefix_name_len = bs.length; - Arrays.fill(prefix_name_bs, (byte) 0); - if (prefix_name_len > ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN) { - prefix_name_len = ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN; - } - if (prefix_name_len > 0) { - System.arraycopy(bs, 0, prefix_name_bs, 0, prefix_name_len); - } - - System.arraycopy(prefix_name_bs, 0, wholePkg, offset, prefix_name_bs.length); - offset += prefix_name_bs.length; - } - - System.arraycopy(ext_name_bs, 0, wholePkg, offset, ext_name_bs.length); - offset += ext_name_bs.length; - - if (bUploadSlave) { - System.arraycopy(masterFilenameBytes, 0, wholePkg, offset, masterFilenameBytes.length); - offset += masterFilenameBytes.length; - } - - out.write(wholePkg); - - if ((this.errno = (byte) callback.send(out)) != 0) { - return null; - } - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - if (pkgInfo.body.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { - throw new MyException("body length: " + pkgInfo.body.length + " <= " + ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); - } - - new_group_name = new String(pkgInfo.body, 0, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN).trim(); - remote_filename = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, pkgInfo.body.length - ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); - String[] results = new String[2]; - results[0] = new_group_name; - results[1] = remote_filename; - - if (meta_list == null || meta_list.length == 0) { - return results; - } - - int result = 0; - try { - result = this.set_metadata(new_group_name, remote_filename, - meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE); - } catch (IOException ex) { - result = 5; - throw ex; - } finally { - if (result != 0) { - this.errno = (byte) result; - this.delete_file(new_group_name, remote_filename); - return null; - } - } - - return results; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * append file to storage server - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @param file_size the file size - * @param callback the write data callback object - * @return return true for success, false for fail - */ - protected int do_append_file(String group_name, String appender_filename, - long file_size, UploadCallback callback) throws IOException, MyException { - byte[] header; - boolean bNewConnection; - Socket storageSocket; - byte[] hexLenBytes; - byte[] appenderFilenameBytes; - int offset; - long body_len; - - if ((group_name == null || group_name.length() == 0) || - (appender_filename == null || appender_filename.length() == 0)) { - this.errno = ProtoCommon.ERR_NO_EINVAL; - return this.errno; - } - - bNewConnection = this.newUpdatableStorageConnection(group_name, appender_filename); - - try { - storageSocket = this.storageServer.getSocket(); - - appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); - body_len = 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length + file_size; - - header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_APPEND_FILE, body_len, (byte) 0); - byte[] wholePkg = new byte[(int) (header.length + body_len - file_size)]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - offset = header.length; - - hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); - System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); - offset += hexLenBytes.length; - - hexLenBytes = ProtoCommon.long2buff(file_size); - System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); - offset += hexLenBytes.length; - - OutputStream out = storageSocket.getOutputStream(); - - System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); - offset += appenderFilenameBytes.length; - - out.write(wholePkg); - if ((this.errno = (byte) callback.send(out)) != 0) { - return this.errno; - } - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return this.errno; - } - - return 0; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * modify appender file to storage server - * - * @param group_name the group name of appender file - * @param appender_filename the appender filename - * @param file_offset the offset of appender file - * @param modify_size the modify size - * @param callback the write data callback object - * @return return true for success, false for fail - */ - protected int do_modify_file(String group_name, String appender_filename, - long file_offset, long modify_size, UploadCallback callback) throws IOException, MyException { - byte[] header; - boolean bNewConnection; - Socket storageSocket; - byte[] hexLenBytes; - byte[] appenderFilenameBytes; - int offset; - long body_len; - - if ((group_name == null || group_name.length() == 0) || - (appender_filename == null || appender_filename.length() == 0)) { - this.errno = ProtoCommon.ERR_NO_EINVAL; - return this.errno; - } - - bNewConnection = this.newUpdatableStorageConnection(group_name, appender_filename); - - try { - storageSocket = this.storageServer.getSocket(); - - appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); - body_len = 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length + modify_size; - - header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_MODIFY_FILE, body_len, (byte) 0); - byte[] wholePkg = new byte[(int) (header.length + body_len - modify_size)]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - offset = header.length; - - hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); - System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); - offset += hexLenBytes.length; - - hexLenBytes = ProtoCommon.long2buff(file_offset); - System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); - offset += hexLenBytes.length; - - hexLenBytes = ProtoCommon.long2buff(modify_size); - System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); - offset += hexLenBytes.length; - - OutputStream out = storageSocket.getOutputStream(); - - System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); - offset += appenderFilenameBytes.length; - - out.write(wholePkg); - if ((this.errno = (byte) callback.send(out)) != 0) { - return this.errno; - } - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return this.errno; - } - - return 0; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * delete file from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @return 0 for success, none zero for fail (error code) - */ - public int delete_file(String group_name, String remote_filename) throws IOException, MyException { - boolean bNewConnection = this.newUpdatableStorageConnection(group_name, remote_filename); - Socket storageSocket = this.storageServer.getSocket(); - - try { - this.send_package(ProtoCommon.STORAGE_PROTO_CMD_DELETE_FILE, group_name, remote_filename); - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); - - this.errno = pkgInfo.errno; - return pkgInfo.errno; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * truncate appender file to size 0 from storage server - * - * @param group_name the group name of storage server - * @param appender_filename the appender filename - * @return 0 for success, none zero for fail (error code) - */ - public int truncate_file(String group_name, String appender_filename) throws IOException, MyException { - final long truncated_file_size = 0; - return this.truncate_file(group_name, appender_filename, truncated_file_size); - } - - /** - * truncate appender file from storage server - * - * @param group_name the group name of storage server - * @param appender_filename the appender filename - * @param truncated_file_size truncated file size - * @return 0 for success, none zero for fail (error code) - */ - public int truncate_file(String group_name, String appender_filename, - long truncated_file_size) throws IOException, MyException { - byte[] header; - boolean bNewConnection; - Socket storageSocket; - byte[] hexLenBytes; - byte[] appenderFilenameBytes; - int offset; - int body_len; - - if ((group_name == null || group_name.length() == 0) || - (appender_filename == null || appender_filename.length() == 0)) { - this.errno = ProtoCommon.ERR_NO_EINVAL; - return this.errno; - } - - bNewConnection = this.newUpdatableStorageConnection(group_name, appender_filename); - - try { - storageSocket = this.storageServer.getSocket(); - - appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); - body_len = 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length; - - header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_TRUNCATE_FILE, body_len, (byte) 0); - byte[] wholePkg = new byte[header.length + body_len]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - offset = header.length; - - hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); - System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); - offset += hexLenBytes.length; - - hexLenBytes = ProtoCommon.long2buff(truncated_file_size); - System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); - offset += hexLenBytes.length; - - OutputStream out = storageSocket.getOutputStream(); - - System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); - offset += appenderFilenameBytes.length; - - out.write(wholePkg); - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); - this.errno = pkgInfo.errno; - return pkgInfo.errno; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * download file from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @return file content/buff, return null if fail - */ - public byte[] download_file(String group_name, String remote_filename) throws IOException, MyException { - final long file_offset = 0; - final long download_bytes = 0; - - return this.download_file(group_name, remote_filename, file_offset, download_bytes); - } - - /** - * download file from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @param file_offset the start offset of the file - * @param download_bytes download bytes, 0 for remain bytes from offset - * @return file content/buff, return null if fail - */ - public byte[] download_file(String group_name, String remote_filename, long file_offset, long download_bytes) throws IOException, MyException { - boolean bNewConnection = this.newReadableStorageConnection(group_name, remote_filename); - Socket storageSocket = this.storageServer.getSocket(); - - try { - ProtoCommon.RecvPackageInfo pkgInfo; - - this.send_download_package(group_name, remote_filename, file_offset, download_bytes); - pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); - - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - return pkgInfo.body; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * download file from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @param local_filename filename on local - * @return 0 success, return none zero errno if fail - */ - public int download_file(String group_name, String remote_filename, - String local_filename) throws IOException, MyException { - final long file_offset = 0; - final long download_bytes = 0; - return this.download_file(group_name, remote_filename, - file_offset, download_bytes, local_filename); - } - - /** - * download file from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @param file_offset the start offset of the file - * @param download_bytes download bytes, 0 for remain bytes from offset - * @param local_filename filename on local - * @return 0 success, return none zero errno if fail - */ - public int download_file(String group_name, String remote_filename, - long file_offset, long download_bytes, - String local_filename) throws IOException, MyException { - boolean bNewConnection = this.newReadableStorageConnection(group_name, remote_filename); - Socket storageSocket = this.storageServer.getSocket(); - try { - ProtoCommon.RecvHeaderInfo header; - FileOutputStream out = new FileOutputStream(local_filename); - try { - this.errno = 0; - this.send_download_package(group_name, remote_filename, file_offset, download_bytes); - - InputStream in = storageSocket.getInputStream(); - header = ProtoCommon.recvHeader(in, ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); - this.errno = header.errno; - if (header.errno != 0) { - return header.errno; - } - - byte[] buff = new byte[256 * 1024]; - long remainBytes = header.body_len; - int bytes; - - //System.out.println("expect_body_len=" + header.body_len); - - while (remainBytes > 0) { - if ((bytes = in.read(buff, 0, remainBytes > buff.length ? buff.length : (int) remainBytes)) < 0) { - throw new IOException("recv package size " + (header.body_len - remainBytes) + " != " + header.body_len); - } - - out.write(buff, 0, bytes); - remainBytes -= bytes; - - //System.out.println("totalBytes=" + (header.body_len - remainBytes)); - } - - return 0; - } catch (IOException ex) { - if (this.errno == 0) { - this.errno = ProtoCommon.ERR_NO_EIO; - } - - throw ex; - } finally { - out.close(); - if (this.errno != 0) { - (new File(local_filename)).delete(); - } - } - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * download file from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @param callback call callback.recv() when data arrive - * @return 0 success, return none zero errno if fail - */ - public int download_file(String group_name, String remote_filename, - DownloadCallback callback) throws IOException, MyException { - final long file_offset = 0; - final long download_bytes = 0; - return this.download_file(group_name, remote_filename, - file_offset, download_bytes, callback); - } - - /** - * download file from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @param file_offset the start offset of the file - * @param download_bytes download bytes, 0 for remain bytes from offset - * @param callback call callback.recv() when data arrive - * @return 0 success, return none zero errno if fail - */ - public int download_file(String group_name, String remote_filename, - long file_offset, long download_bytes, - DownloadCallback callback) throws IOException, MyException { - int result; - boolean bNewConnection = this.newReadableStorageConnection(group_name, remote_filename); - Socket storageSocket = this.storageServer.getSocket(); - - try { - ProtoCommon.RecvHeaderInfo header; - this.send_download_package(group_name, remote_filename, file_offset, download_bytes); - - InputStream in = storageSocket.getInputStream(); - header = ProtoCommon.recvHeader(in, ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); - this.errno = header.errno; - if (header.errno != 0) { - return header.errno; - } - - byte[] buff = new byte[2 * 1024]; - long remainBytes = header.body_len; - int bytes; - - //System.out.println("expect_body_len=" + header.body_len); - - while (remainBytes > 0) { - if ((bytes = in.read(buff, 0, remainBytes > buff.length ? buff.length : (int) remainBytes)) < 0) { - throw new IOException("recv package size " + (header.body_len - remainBytes) + " != " + header.body_len); - } - - if ((result = callback.recv(header.body_len, buff, bytes)) != 0) { - this.errno = (byte) result; - return result; - } - - remainBytes -= bytes; - //System.out.println("totalBytes=" + (header.body_len - remainBytes)); - } - - return 0; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * get all metadata items from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @return meta info array, return null if fail - */ - public NameValuePair[] get_metadata(String group_name, String remote_filename) throws IOException, MyException { - boolean bNewConnection = this.newUpdatableStorageConnection(group_name, remote_filename); - Socket storageSocket = this.storageServer.getSocket(); - - try { - ProtoCommon.RecvPackageInfo pkgInfo; - - this.send_package(ProtoCommon.STORAGE_PROTO_CMD_GET_METADATA, group_name, remote_filename); - pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); - - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - return ProtoCommon.split_metadata(new String(pkgInfo.body, ClientGlobal.g_charset)); - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * set metadata items to storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @param meta_list meta item array - * @param op_flag flag, can be one of following values:
- * - * - * @return 0 for success, !=0 fail (error code) - */ - public int set_metadata(String group_name, String remote_filename, - NameValuePair[] meta_list, byte op_flag) throws IOException, MyException { - boolean bNewConnection = this.newUpdatableStorageConnection(group_name, remote_filename); - Socket storageSocket = this.storageServer.getSocket(); - - try { - byte[] header; - byte[] groupBytes; - byte[] filenameBytes; - byte[] meta_buff; - byte[] bs; - int groupLen; - byte[] sizeBytes; - ProtoCommon.RecvPackageInfo pkgInfo; - - if (meta_list == null) { - meta_buff = new byte[0]; - } else { - meta_buff = ProtoCommon.pack_metadata(meta_list).getBytes(ClientGlobal.g_charset); - } - - filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); - sizeBytes = new byte[2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; - Arrays.fill(sizeBytes, (byte) 0); - - bs = ProtoCommon.long2buff(filenameBytes.length); - System.arraycopy(bs, 0, sizeBytes, 0, bs.length); - bs = ProtoCommon.long2buff(meta_buff.length); - System.arraycopy(bs, 0, sizeBytes, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE, bs.length); - - groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; - bs = group_name.getBytes(ClientGlobal.g_charset); - - Arrays.fill(groupBytes, (byte) 0); - if (bs.length <= groupBytes.length) { - groupLen = bs.length; - } else { - groupLen = groupBytes.length; - } - System.arraycopy(bs, 0, groupBytes, 0, groupLen); - - header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_SET_METADATA, - 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + 1 + groupBytes.length - + filenameBytes.length + meta_buff.length, (byte) 0); - OutputStream out = storageSocket.getOutputStream(); - byte[] wholePkg = new byte[header.length + sizeBytes.length + 1 + groupBytes.length + filenameBytes.length]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - System.arraycopy(sizeBytes, 0, wholePkg, header.length, sizeBytes.length); - wholePkg[header.length + sizeBytes.length] = op_flag; - System.arraycopy(groupBytes, 0, wholePkg, header.length + sizeBytes.length + 1, groupBytes.length); - System.arraycopy(filenameBytes, 0, wholePkg, header.length + sizeBytes.length + 1 + groupBytes.length, filenameBytes.length); - out.write(wholePkg); - if (meta_buff.length > 0) { - out.write(meta_buff); - } - - pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); - - this.errno = pkgInfo.errno; - return pkgInfo.errno; - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * get file info decoded from the filename, fetch from the storage if necessary - * - * @param group_name the group name - * @param remote_filename the filename - * @return FileInfo object for success, return null for fail - */ - public FileInfo get_file_info(String group_name, String remote_filename) throws IOException, MyException { - if (remote_filename.length() < ProtoCommon.FDFS_FILE_PATH_LEN + ProtoCommon.FDFS_FILENAME_BASE64_LENGTH - + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { - this.errno = ProtoCommon.ERR_NO_EINVAL; - return null; - } - - byte[] buff = base64.decodeAuto(remote_filename.substring(ProtoCommon.FDFS_FILE_PATH_LEN, - ProtoCommon.FDFS_FILE_PATH_LEN + ProtoCommon.FDFS_FILENAME_BASE64_LENGTH)); - - short file_type; - long file_size = ProtoCommon.buff2long(buff, 4 * 2); - if (((file_size & ProtoCommon.APPENDER_FILE_SIZE) != 0)) - { - file_type = FileInfo.FILE_TYPE_APPENDER; - } - else if ((remote_filename.length() > ProtoCommon.TRUNK_LOGIC_FILENAME_LENGTH) || - ((remote_filename.length() > ProtoCommon.NORMAL_LOGIC_FILENAME_LENGTH) && - ((file_size & ProtoCommon.TRUNK_FILE_MARK_SIZE) == 0))) - { - file_type = FileInfo.FILE_TYPE_SLAVE; - } - else { - file_type = FileInfo.FILE_TYPE_NORMAL; - } - - if (file_type == FileInfo.FILE_TYPE_SLAVE || - file_type == FileInfo.FILE_TYPE_APPENDER) - { //slave file or appender file - FileInfo fi = this.query_file_info(group_name, remote_filename); - if (fi == null) { - return null; - } - - fi.setFileType(file_type); - return fi; - } - - int create_timestamp = ProtoCommon.buff2int(buff, 4); - if ((file_size >> 63) != 0) { - file_size &= 0xFFFFFFFFL; //low 32 bits is file size - } - int crc32 = ProtoCommon.buff2int(buff, 4 * 4); - - return new FileInfo(false, file_type, file_size, create_timestamp, - crc32, ProtoCommon.getIpAddress(buff, 0)); - } - - /** - * get file info from storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @return FileInfo object for success, return null for fail - */ - public FileInfo query_file_info(String group_name, String remote_filename) throws IOException, MyException { - boolean bNewConnection = this.newUpdatableStorageConnection(group_name, remote_filename); - Socket storageSocket = this.storageServer.getSocket(); - - try { - byte[] header; - byte[] groupBytes; - byte[] filenameBytes; - byte[] bs; - int groupLen; - ProtoCommon.RecvPackageInfo pkgInfo; - - filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); - groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; - bs = group_name.getBytes(ClientGlobal.g_charset); - - Arrays.fill(groupBytes, (byte) 0); - if (bs.length <= groupBytes.length) { - groupLen = bs.length; - } else { - groupLen = groupBytes.length; - } - System.arraycopy(bs, 0, groupBytes, 0, groupLen); - - header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_QUERY_FILE_INFO, - +groupBytes.length + filenameBytes.length, (byte) 0); - OutputStream out = storageSocket.getOutputStream(); - byte[] wholePkg = new byte[header.length + groupBytes.length + filenameBytes.length]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - System.arraycopy(groupBytes, 0, wholePkg, header.length, groupBytes.length); - System.arraycopy(filenameBytes, 0, wholePkg, header.length + groupBytes.length, filenameBytes.length); - out.write(wholePkg); - - pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), - ProtoCommon.STORAGE_PROTO_CMD_RESP, - 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + - ProtoCommon.FDFS_IPADDR_SIZE); - - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - long file_size = ProtoCommon.buff2long(pkgInfo.body, 0); - int create_timestamp = (int) ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); - int crc32 = (int) ProtoCommon.buff2long(pkgInfo.body, 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); - String source_ip_addr = (new String(pkgInfo.body, 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE, ProtoCommon.FDFS_IPADDR_SIZE)).trim(); - return new FileInfo(true, FileInfo.FILE_TYPE_NORMAL, file_size, - create_timestamp, crc32, source_ip_addr); - } catch (IOException ex) { - if (!bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - this.storageServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } finally { - this.storageServer = null; - } - } - } - } - - /** - * check storage socket, if null create a new connection - * - * @param group_name the group name to upload file to, can be empty - * @return true if create a new connection - */ - protected boolean newWritableStorageConnection(String group_name) throws IOException, MyException { - if (this.storageServer != null) { - return false; - } else { - TrackerClient tracker = new TrackerClient(); - this.storageServer = tracker.getStoreStorage(this.trackerServer, group_name); - if (this.storageServer == null) { - throw new MyException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); - } - return true; - } - } - - /** - * check storage socket, if null create a new connection - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @return true if create a new connection - */ - protected boolean newReadableStorageConnection(String group_name, String remote_filename) throws IOException, MyException { - if (this.storageServer != null) { - return false; - } else { - TrackerClient tracker = new TrackerClient(); - this.storageServer = tracker.getFetchStorage(this.trackerServer, group_name, remote_filename); - if (this.storageServer == null) { - throw new MyException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); - } - return true; - } - } - - /** - * check storage socket, if null create a new connection - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @return true if create a new connection - */ - protected boolean newUpdatableStorageConnection(String group_name, String remote_filename) throws IOException, MyException { - if (this.storageServer != null) { - return false; - } else { - TrackerClient tracker = new TrackerClient(); - this.storageServer = tracker.getUpdateStorage(this.trackerServer, group_name, remote_filename); - if (this.storageServer == null) { - throw new MyException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); - } - return true; - } - } - - /** - * send package to storage server - * - * @param cmd which command to send - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - */ - protected void send_package(byte cmd, String group_name, String remote_filename) throws IOException { - byte[] header; - byte[] groupBytes; - byte[] filenameBytes; - byte[] bs; - int groupLen; - - groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; - bs = group_name.getBytes(ClientGlobal.g_charset); - filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); - - Arrays.fill(groupBytes, (byte) 0); - if (bs.length <= groupBytes.length) { - groupLen = bs.length; - } else { - groupLen = groupBytes.length; - } - System.arraycopy(bs, 0, groupBytes, 0, groupLen); - - header = ProtoCommon.packHeader(cmd, groupBytes.length + filenameBytes.length, (byte) 0); - byte[] wholePkg = new byte[header.length + groupBytes.length + filenameBytes.length]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - System.arraycopy(groupBytes, 0, wholePkg, header.length, groupBytes.length); - System.arraycopy(filenameBytes, 0, wholePkg, header.length + groupBytes.length, filenameBytes.length); - this.storageServer.getSocket().getOutputStream().write(wholePkg); - } - - /** - * send package to storage server - * - * @param group_name the group name of storage server - * @param remote_filename filename on storage server - * @param file_offset the start offset of the file - * @param download_bytes download bytes - */ - protected void send_download_package(String group_name, String remote_filename, long file_offset, long download_bytes) throws IOException { - byte[] header; - byte[] bsOffset; - byte[] bsDownBytes; - byte[] groupBytes; - byte[] filenameBytes; - byte[] bs; - int groupLen; - - bsOffset = ProtoCommon.long2buff(file_offset); - bsDownBytes = ProtoCommon.long2buff(download_bytes); - groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; - bs = group_name.getBytes(ClientGlobal.g_charset); - filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); - - Arrays.fill(groupBytes, (byte) 0); - if (bs.length <= groupBytes.length) { - groupLen = bs.length; - } else { - groupLen = groupBytes.length; - } - System.arraycopy(bs, 0, groupBytes, 0, groupLen); - - header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_DOWNLOAD_FILE, - bsOffset.length + bsDownBytes.length + groupBytes.length + filenameBytes.length, (byte) 0); - byte[] wholePkg = new byte[header.length + bsOffset.length + bsDownBytes.length + groupBytes.length + filenameBytes.length]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - System.arraycopy(bsOffset, 0, wholePkg, header.length, bsOffset.length); - System.arraycopy(bsDownBytes, 0, wholePkg, header.length + bsOffset.length, bsDownBytes.length); - System.arraycopy(groupBytes, 0, wholePkg, header.length + bsOffset.length + bsDownBytes.length, groupBytes.length); - System.arraycopy(filenameBytes, 0, wholePkg, header.length + bsOffset.length + bsDownBytes.length + groupBytes.length, filenameBytes.length); - this.storageServer.getSocket().getOutputStream().write(wholePkg); - } - - public boolean isConnected(){ - return trackerServer.isConnected(); - } - - public boolean isAvaliable(){ - return trackerServer.isAvaliable(); - } - - public void close() throws IOException { - trackerServer.close(); - } - - public TrackerServer getTrackerServer() { - return trackerServer; - } - - public void setTrackerServer(TrackerServer trackerServer) { - this.trackerServer = trackerServer; - } - - public StorageServer getStorageServer() { - return storageServer; - } - - public void setStorageServer(StorageServer storageServer) { - this.storageServer = storageServer; - } - - /** - * Upload file by file buff - * - * @author Happy Fish / YuQing - * @version Version 1.12 - */ - public static class UploadBuff implements UploadCallback { - private byte[] fileBuff; - private int offset; - private int length; + public final static Base64 base64 = new Base64('-', '_', '.', 0); + protected TrackerServer trackerServer; + protected StorageServer storageServer; + protected byte errno; /** - * constructor - * - * @param fileBuff the file buff for uploading + * constructor using global settings in class ClientGlobal */ - public UploadBuff(byte[] fileBuff, int offset, int length) { - super(); - this.fileBuff = fileBuff; - this.offset = offset; - this.length = length; + public StorageClient() { + this.trackerServer = null; + this.storageServer = null; } /** - * send file content callback function, be called only once when the file uploaded + * constructor with tracker server * - * @param out output stream for writing file content - * @return 0 success, return none zero(errno) if fail + * @param trackerServer the tracker server, can be null */ - public int send(OutputStream out) throws IOException { - out.write(this.fileBuff, this.offset, this.length); - - return 0; + public StorageClient(TrackerServer trackerServer) { + this.trackerServer = trackerServer; + this.storageServer = null; + } + + /** + * constructor with tracker server and storage server + * NOTE: if not necessary, do NOT set storage server instance + * + * @param trackerServer the tracker server, can be null + * @param storageServer the storage server, can be null + */ + public StorageClient(TrackerServer trackerServer, StorageServer storageServer) { + this.trackerServer = trackerServer; + this.storageServer = storageServer; + } + + /** + * get the error code of last call + * + * @return the error code of last call + */ + public byte getErrorCode() { + return this.errno; + } + + /** + * upload file to storage server (by file name) + * + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + final String group_name = null; + return this.upload_file(group_name, local_filename, file_ext_name, meta_list); + } + + /** + * upload file to storage server (by file name) + * + * @param group_name the group name to upload file to, can be empty + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + protected String[] upload_file(String group_name, String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + final byte cmd = ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE; + return this.upload_file(cmd, group_name, local_filename, file_ext_name, meta_list); + } + + /** + * upload file to storage server (by file name) + * + * @param cmd the command + * @param group_name the group name to upload file to, can be empty + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + protected String[] upload_file(byte cmd, String group_name, String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + File f = new File(local_filename); + FileInputStream fis = new FileInputStream(f); + + if (file_ext_name == null) { + int nPos = local_filename.lastIndexOf('.'); + if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + file_ext_name = local_filename.substring(nPos + 1); + } + } + + try { + return this.do_upload_file(cmd, group_name, null, null, file_ext_name, + f.length(), new UploadStream(fis, f.length()), meta_list); + } finally { + fis.close(); + } + } + + /** + * upload file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(byte[] file_buff, int offset, int length, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + final String group_name = null; + return this.upload_file(group_name, file_buff, offset, length, file_ext_name, meta_list); + } + + /** + * upload file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(String group_name, byte[] file_buff, int offset, int length, + String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, null, null, file_ext_name, + length, new UploadBuff(file_buff, offset, length), meta_list); + } + + /** + * upload file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(byte[] file_buff, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + final String group_name = null; + return this.upload_file(group_name, file_buff, 0, file_buff.length, file_ext_name, meta_list); + } + + /** + * upload file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(String group_name, byte[] file_buff, + String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, null, null, file_ext_name, + file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); + } + + /** + * upload file to storage server (by callback) + * + * @param group_name the group name to upload file to, can be empty + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(String group_name, long file_size, UploadCallback callback, + String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + final String master_filename = null; + final String prefix_name = null; + + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, master_filename, prefix_name, + file_ext_name, file_size, callback, meta_list); + } + + /** + * upload file to storage server (by file name, slave file mode) + * + * @param group_name the group name of master file + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(String group_name, String master_filename, String prefix_name, + String local_filename, String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + if ((group_name == null || group_name.length() == 0) || + (master_filename == null || master_filename.length() == 0) || + (prefix_name == null)) { + throw new MyException("invalid arguement"); + } + + File f = new File(local_filename); + FileInputStream fis = new FileInputStream(f); + + if (file_ext_name == null) { + int nPos = local_filename.lastIndexOf('.'); + if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + file_ext_name = local_filename.substring(nPos + 1); + } + } + + try { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, + file_ext_name, f.length(), new UploadStream(fis, f.length()), meta_list); + } finally { + fis.close(); + } + } + + /** + * upload file to storage server (by file buff, slave file mode) + * + * @param group_name the group name of master file + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(String group_name, String master_filename, String prefix_name, + byte[] file_buff, String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + if ((group_name == null || group_name.length() == 0) || + (master_filename == null || master_filename.length() == 0) || + (prefix_name == null)) { + throw new MyException("invalid arguement"); + } + + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, + file_ext_name, file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); + } + + /** + * upload file to storage server (by file buff, slave file mode) + * + * @param group_name the group name of master file + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(String group_name, String master_filename, String prefix_name, + byte[] file_buff, int offset, int length, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + if ((group_name == null || group_name.length() == 0) || + (master_filename == null || master_filename.length() == 0) || + (prefix_name == null)) { + throw new MyException("invalid arguement"); + } + + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, + file_ext_name, length, new UploadBuff(file_buff, offset, length), meta_list); + } + + /** + * upload file to storage server (by callback, slave file mode) + * + * @param group_name the group name to upload file to, can be empty + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_file(String group_name, String master_filename, + String prefix_name, long file_size, UploadCallback callback, + String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, + file_ext_name, file_size, callback, meta_list); + } + + /** + * upload appender file to storage server (by file name) + * + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_appender_file(String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + final String group_name = null; + return this.upload_appender_file(group_name, local_filename, file_ext_name, meta_list); + } + + /** + * upload appender file to storage server (by file name) + * + * @param group_name the group name to upload file to, can be empty + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + protected String[] upload_appender_file(String group_name, String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + final byte cmd = ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE; + return this.upload_file(cmd, group_name, local_filename, file_ext_name, meta_list); + } + + /** + * upload appender file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_appender_file(byte[] file_buff, int offset, int length, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + final String group_name = null; + return this.upload_appender_file(group_name, file_buff, offset, length, file_ext_name, meta_list); + } + + /** + * upload appender file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_appender_file(String group_name, byte[] file_buff, int offset, int length, + String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, null, null, file_ext_name, + length, new UploadBuff(file_buff, offset, length), meta_list); + } + + /** + * upload appender file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_appender_file(byte[] file_buff, String file_ext_name, + NameValuePair[] meta_list) throws IOException, MyException { + final String group_name = null; + return this.upload_appender_file(group_name, file_buff, 0, file_buff.length, file_ext_name, meta_list); + } + + /** + * upload appender file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_appender_file(String group_name, byte[] file_buff, + String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, null, null, file_ext_name, + file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); + } + + /** + * upload appender file to storage server (by callback) + * + * @param group_name the group name to upload file to, can be empty + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] upload_appender_file(String group_name, long file_size, UploadCallback callback, + String file_ext_name, NameValuePair[] meta_list) throws IOException, MyException { + final String master_filename = null; + final String prefix_name = null; + + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, master_filename, prefix_name, + file_ext_name, file_size, callback, meta_list); + } + + /** + * append file to storage server (by file name) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param local_filename local filename to append + * @return 0 for success, != 0 for error (error no) + */ + public int append_file(String group_name, String appender_filename, String local_filename) throws IOException, MyException { + File f = new File(local_filename); + FileInputStream fis = new FileInputStream(f); + + try { + return this.do_append_file(group_name, appender_filename, f.length(), new UploadStream(fis, f.length())); + } finally { + fis.close(); + } + } + + /** + * append file to storage server (by file buff) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_buff file content/buff + * @return 0 for success, != 0 for error (error no) + */ + public int append_file(String group_name, String appender_filename, byte[] file_buff) throws IOException, MyException { + return this.do_append_file(group_name, appender_filename, file_buff.length, new UploadBuff(file_buff, 0, file_buff.length)); + } + + /** + * append file to storage server (by file buff) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to append + * @return 0 for success, != 0 for error (error no) + */ + public int append_file(String group_name, String appender_filename, + byte[] file_buff, int offset, int length) throws IOException, MyException { + return this.do_append_file(group_name, appender_filename, length, new UploadBuff(file_buff, offset, length)); + } + + /** + * append file to storage server (by callback) + * + * @param group_name the group name to append file to + * @param appender_filename the appender filename + * @param file_size the file size + * @param callback the write data callback object + * @return 0 for success, != 0 for error (error no) + */ + public int append_file(String group_name, String appender_filename, + long file_size, UploadCallback callback) throws IOException, MyException { + return this.do_append_file(group_name, appender_filename, file_size, callback); + } + + /** + * modify appender file to storage server (by file name) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param local_filename local filename to append + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file(String group_name, String appender_filename, + long file_offset, String local_filename) throws IOException, MyException { + File f = new File(local_filename); + FileInputStream fis = new FileInputStream(f); + + try { + return this.do_modify_file(group_name, appender_filename, file_offset, + f.length(), new UploadStream(fis, f.length())); + } finally { + fis.close(); + } + } + + /** + * modify appender file to storage server (by file buff) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param file_buff file content/buff + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file(String group_name, String appender_filename, + long file_offset, byte[] file_buff) throws IOException, MyException { + return this.do_modify_file(group_name, appender_filename, file_offset, + file_buff.length, new UploadBuff(file_buff, 0, file_buff.length)); + } + + /** + * modify appender file to storage server (by file buff) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param file_buff file content/buff + * @param buffer_offset start offset of the buff + * @param buffer_length the length of buff to modify + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file(String group_name, String appender_filename, + long file_offset, byte[] file_buff, int buffer_offset, int buffer_length) throws IOException, MyException { + return this.do_modify_file(group_name, appender_filename, file_offset, + buffer_length, new UploadBuff(file_buff, buffer_offset, buffer_length)); + } + + /** + * modify appender file to storage server (by callback) + * + * @param group_name the group name to modify file to + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param modify_size the modify size + * @param callback the write data callback object + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file(String group_name, String appender_filename, + long file_offset, long modify_size, UploadCallback callback) throws IOException, MyException { + return this.do_modify_file(group_name, appender_filename, file_offset, + modify_size, callback); + } + + /** + * regenerate filename for appender file + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + public String[] regenerate_appender_filename(String group_name, String appender_filename) throws IOException, MyException { + byte[] header; + boolean bNewStorageServer; + Connection connection = null; + byte[] hexLenBytes; + byte[] appenderFilenameBytes; + int offset; + long body_len; + + if ((group_name == null || group_name.length() == 0) || + (appender_filename == null || appender_filename.length() == 0)) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } + + bNewStorageServer = this.newUpdatableStorageConnection(group_name, appender_filename); + + try { + connection = this.storageServer.getConnection(); + + appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); + body_len = appenderFilenameBytes.length; + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_REGENERATE_APPENDER_FILENAME, body_len, (byte) 0); + byte[] wholePkg = new byte[(int) (header.length + body_len)]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + offset = header.length; + + System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); + offset += appenderFilenameBytes.length; + + OutputStream out = connection.getOutputStream(); + out.write(wholePkg); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + if (pkgInfo.body.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + throw new MyException("body length: " + pkgInfo.body.length + " <= " + ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); + } + + String new_group_name = new String(pkgInfo.body, 0, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN).trim(); + String remote_filename = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, + pkgInfo.body.length - ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); + String[] results = new String[2]; + results[0] = new_group_name; + results[1] = remote_filename; + + return results; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * upload file to storage server + * + * @param cmd the command code + * @param group_name the group name to upload file to, can be empty + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_ext_name file ext name, do not include dot(.) + * @param file_size the file size + * @param callback the write data callback object + * @param meta_list meta info array + * @return 2 elements string array if success:
+ * + * + * return null if fail + */ + protected String[] do_upload_file(byte cmd, String group_name, String master_filename, + String prefix_name, String file_ext_name, long file_size, UploadCallback callback, + NameValuePair[] meta_list) throws IOException, MyException { + byte[] header; + byte[] ext_name_bs; + String new_group_name; + String remote_filename; + boolean bNewStorageServer; + Connection connection = null; + byte[] sizeBytes; + byte[] hexLenBytes; + byte[] masterFilenameBytes; + boolean bUploadSlave; + int offset; + long body_len; + + bUploadSlave = ((group_name != null && group_name.length() > 0) && + (master_filename != null && master_filename.length() > 0) && + (prefix_name != null)); + if (bUploadSlave) { + bNewStorageServer = this.newUpdatableStorageConnection(group_name, master_filename); + } else { + bNewStorageServer = this.newWritableStorageConnection(group_name); + } + + try { + connection = this.storageServer.getConnection(); + + ext_name_bs = new byte[ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN]; + Arrays.fill(ext_name_bs, (byte) 0); + if (file_ext_name != null && file_ext_name.length() > 0) { + byte[] bs = file_ext_name.getBytes(ClientGlobal.g_charset); + int ext_name_len = bs.length; + if (ext_name_len > ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN) { + ext_name_len = ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN; + } + System.arraycopy(bs, 0, ext_name_bs, 0, ext_name_len); + } + + if (bUploadSlave) { + masterFilenameBytes = master_filename.getBytes(ClientGlobal.g_charset); + + sizeBytes = new byte[2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; + body_len = sizeBytes.length + ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + + masterFilenameBytes.length + file_size; + + hexLenBytes = ProtoCommon.long2buff(master_filename.length()); + System.arraycopy(hexLenBytes, 0, sizeBytes, 0, hexLenBytes.length); + offset = hexLenBytes.length; + } else { + masterFilenameBytes = null; + sizeBytes = new byte[1 + 1 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; + body_len = sizeBytes.length + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + file_size; + + sizeBytes[0] = (byte) this.storageServer.getStorePathIndex(); + offset = 1; + } + + hexLenBytes = ProtoCommon.long2buff(file_size); + System.arraycopy(hexLenBytes, 0, sizeBytes, offset, hexLenBytes.length); + + OutputStream out = connection.getOutputStream(); + header = ProtoCommon.packHeader(cmd, body_len, (byte) 0); + byte[] wholePkg = new byte[(int) (header.length + body_len - file_size)]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(sizeBytes, 0, wholePkg, header.length, sizeBytes.length); + offset = header.length + sizeBytes.length; + if (bUploadSlave) { + byte[] prefix_name_bs = new byte[ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN]; + byte[] bs = prefix_name.getBytes(ClientGlobal.g_charset); + int prefix_name_len = bs.length; + Arrays.fill(prefix_name_bs, (byte) 0); + if (prefix_name_len > ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN) { + prefix_name_len = ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN; + } + if (prefix_name_len > 0) { + System.arraycopy(bs, 0, prefix_name_bs, 0, prefix_name_len); + } + + System.arraycopy(prefix_name_bs, 0, wholePkg, offset, prefix_name_bs.length); + offset += prefix_name_bs.length; + } + + System.arraycopy(ext_name_bs, 0, wholePkg, offset, ext_name_bs.length); + offset += ext_name_bs.length; + + if (bUploadSlave) { + System.arraycopy(masterFilenameBytes, 0, wholePkg, offset, masterFilenameBytes.length); + offset += masterFilenameBytes.length; + } + + out.write(wholePkg); + + if ((this.errno = (byte) callback.send(out)) != 0) { + return null; + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + if (pkgInfo.body.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + throw new MyException("body length: " + pkgInfo.body.length + " <= " + ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); + } + + new_group_name = new String(pkgInfo.body, 0, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN).trim(); + remote_filename = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, pkgInfo.body.length - ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); + String[] results = new String[2]; + results[0] = new_group_name; + results[1] = remote_filename; + + if (meta_list == null || meta_list.length == 0) { + return results; + } + + int result = 0; + try { + result = this.set_metadata(new_group_name, remote_filename, + meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE); + } catch (IOException ex) { + result = 5; + throw ex; + } finally { + if (result != 0) { + this.errno = (byte) result; + this.delete_file(new_group_name, remote_filename); + return null; + } + } + return results; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + + } + } + + /** + * append file to storage server + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_size the file size + * @param callback the write data callback object + * @return return true for success, false for fail + */ + protected int do_append_file(String group_name, String appender_filename, + long file_size, UploadCallback callback) throws IOException, MyException { + byte[] header; + boolean bNewStorageServer; + Connection connection = null; + byte[] hexLenBytes; + byte[] appenderFilenameBytes; + int offset; + long body_len; + + if ((group_name == null || group_name.length() == 0) || + (appender_filename == null || appender_filename.length() == 0)) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return this.errno; + } + + bNewStorageServer = this.newUpdatableStorageConnection(group_name, appender_filename); + + try { + connection = this.storageServer.getConnection(); + + appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); + body_len = 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length + file_size; + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_APPEND_FILE, body_len, (byte) 0); + byte[] wholePkg = new byte[(int) (header.length + body_len - file_size)]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + offset = header.length; + + hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + hexLenBytes = ProtoCommon.long2buff(file_size); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + OutputStream out = connection.getOutputStream(); + + System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); + offset += appenderFilenameBytes.length; + + out.write(wholePkg); + if ((this.errno = (byte) callback.send(out)) != 0) { + return this.errno; + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return this.errno; + } + + return 0; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + private void doFinally(Connection connection, boolean bNewStorageServer) { + try { + if (connection != null) { + this.storageServer.releaseConnection(connection); + } + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + if (bNewStorageServer) { + this.storageServer = null; + } + } + } + + /** + * modify appender file to storage server + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param modify_size the modify size + * @param callback the write data callback object + * @return return true for success, false for fail + */ + protected int do_modify_file(String group_name, String appender_filename, + long file_offset, long modify_size, UploadCallback callback) throws IOException, MyException { + byte[] header; + boolean bNewStorageServer; + Connection connection = null; + byte[] hexLenBytes; + byte[] appenderFilenameBytes; + int offset; + long body_len; + + if ((group_name == null || group_name.length() == 0) || + (appender_filename == null || appender_filename.length() == 0)) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return this.errno; + } + + bNewStorageServer = this.newUpdatableStorageConnection(group_name, appender_filename); + + try { + connection = this.storageServer.getConnection(); + + appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); + body_len = 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length + modify_size; + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_MODIFY_FILE, body_len, (byte) 0); + byte[] wholePkg = new byte[(int) (header.length + body_len - modify_size)]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + offset = header.length; + + hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + hexLenBytes = ProtoCommon.long2buff(file_offset); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + hexLenBytes = ProtoCommon.long2buff(modify_size); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + OutputStream out = connection.getOutputStream(); + + System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); + offset += appenderFilenameBytes.length; + + out.write(wholePkg); + if ((this.errno = (byte) callback.send(out)) != 0) { + return this.errno; + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return this.errno; + } + + return 0; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * delete file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return 0 for success, none zero for fail (error code) + */ + public int delete_file(String group_name, String remote_filename) throws IOException, MyException { + boolean bNewStorageServer = this.newUpdatableStorageConnection(group_name, remote_filename); + Connection connection = this.storageServer.getConnection(); + + try { + this.send_package(ProtoCommon.STORAGE_PROTO_CMD_DELETE_FILE, group_name, remote_filename, connection); + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + + this.errno = pkgInfo.errno; + return pkgInfo.errno; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * truncate appender file to size 0 from storage server + * + * @param group_name the group name of storage server + * @param appender_filename the appender filename + * @return 0 for success, none zero for fail (error code) + */ + public int truncate_file(String group_name, String appender_filename) throws IOException, MyException { + final long truncated_file_size = 0; + return this.truncate_file(group_name, appender_filename, truncated_file_size); + } + + /** + * truncate appender file from storage server + * + * @param group_name the group name of storage server + * @param appender_filename the appender filename + * @param truncated_file_size truncated file size + * @return 0 for success, none zero for fail (error code) + */ + public int truncate_file(String group_name, String appender_filename, + long truncated_file_size) throws IOException, MyException { + byte[] header; + boolean bNewStorageServer; + Connection connection = null; + byte[] hexLenBytes; + byte[] appenderFilenameBytes; + int offset; + int body_len; + + if ((group_name == null || group_name.length() == 0) || + (appender_filename == null || appender_filename.length() == 0)) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return this.errno; + } + + bNewStorageServer = this.newUpdatableStorageConnection(group_name, appender_filename); + + try { + connection = this.storageServer.getConnection(); + + appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); + body_len = 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length; + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_TRUNCATE_FILE, body_len, (byte) 0); + byte[] wholePkg = new byte[header.length + body_len]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + offset = header.length; + + hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + hexLenBytes = ProtoCommon.long2buff(truncated_file_size); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + OutputStream out = connection.getOutputStream(); + + System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); + offset += appenderFilenameBytes.length; + + out.write(wholePkg); + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + this.errno = pkgInfo.errno; + return pkgInfo.errno; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return file content/buff, return null if fail + */ + public byte[] download_file(String group_name, String remote_filename) throws IOException, MyException { + final long file_offset = 0; + final long download_bytes = 0; + + return this.download_file(group_name, remote_filename, file_offset, download_bytes); + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @return file content/buff, return null if fail + */ + public byte[] download_file(String group_name, String remote_filename, long file_offset, long download_bytes) throws IOException, MyException { + boolean bNewStorageServer = this.newReadableStorageConnection(group_name, remote_filename); + Connection connection = this.storageServer.getConnection(); + + try { + ProtoCommon.RecvPackageInfo pkgInfo; + + this.send_download_package(group_name, remote_filename, file_offset, download_bytes, connection); + pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + return pkgInfo.body; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param local_filename filename on local + * @return 0 success, return none zero errno if fail + */ + public int download_file(String group_name, String remote_filename, + String local_filename) throws IOException, MyException { + final long file_offset = 0; + final long download_bytes = 0; + return this.download_file(group_name, remote_filename, + file_offset, download_bytes, local_filename); + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @param local_filename filename on local + * @return 0 success, return none zero errno if fail + */ + public int download_file(String group_name, String remote_filename, + long file_offset, long download_bytes, + String local_filename) throws IOException, MyException { + boolean bNewStorageServer = this.newReadableStorageConnection(group_name, remote_filename); + Connection connection = this.storageServer.getConnection(); + try { + ProtoCommon.RecvHeaderInfo header; + FileOutputStream out = new FileOutputStream(local_filename); + try { + this.errno = 0; + this.send_download_package(group_name, remote_filename, file_offset, download_bytes, connection); + + InputStream in = connection.getInputStream(); + header = ProtoCommon.recvHeader(in, ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + this.errno = header.errno; + if (header.errno != 0) { + return header.errno; + } + + byte[] buff = new byte[256 * 1024]; + long remainBytes = header.body_len; + int bytes; + + //System.out.println("expect_body_len=" + header.body_len); + + while (remainBytes > 0) { + if ((bytes = in.read(buff, 0, remainBytes > buff.length ? buff.length : (int) remainBytes)) < 0) { + throw new IOException("recv package size " + (header.body_len - remainBytes) + " != " + header.body_len); + } + + out.write(buff, 0, bytes); + remainBytes -= bytes; + + //System.out.println("totalBytes=" + (header.body_len - remainBytes)); + } + + return 0; + } catch (IOException ex) { + if (this.errno == 0) { + this.errno = ProtoCommon.ERR_NO_EIO; + } + + throw ex; + } finally { + out.close(); + if (this.errno != 0) { + (new File(local_filename)).delete(); + } + } + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param callback call callback.recv() when data arrive + * @return 0 success, return none zero errno if fail + */ + public int download_file(String group_name, String remote_filename, + DownloadCallback callback) throws IOException, MyException { + final long file_offset = 0; + final long download_bytes = 0; + return this.download_file(group_name, remote_filename, + file_offset, download_bytes, callback); + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @param callback call callback.recv() when data arrive + * @return 0 success, return none zero errno if fail + */ + public int download_file(String group_name, String remote_filename, + long file_offset, long download_bytes, + DownloadCallback callback) throws IOException, MyException { + int result; + boolean bNewStorageServer = this.newReadableStorageConnection(group_name, remote_filename); + Connection connection = this.storageServer.getConnection(); + + try { + ProtoCommon.RecvHeaderInfo header; + this.send_download_package(group_name, remote_filename, file_offset, download_bytes, connection); + + InputStream in = connection.getInputStream(); + header = ProtoCommon.recvHeader(in, ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + this.errno = header.errno; + if (header.errno != 0) { + return header.errno; + } + + byte[] buff = new byte[2 * 1024]; + long remainBytes = header.body_len; + int bytes; + + //System.out.println("expect_body_len=" + header.body_len); + + while (remainBytes > 0) { + if ((bytes = in.read(buff, 0, remainBytes > buff.length ? buff.length : (int) remainBytes)) < 0) { + throw new IOException("recv package size " + (header.body_len - remainBytes) + " != " + header.body_len); + } + + if ((result = callback.recv(header.body_len, buff, bytes)) != 0) { + this.errno = (byte) result; + return result; + } + + remainBytes -= bytes; + //System.out.println("totalBytes=" + (header.body_len - remainBytes)); + } + + return 0; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * get all metadata items from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return meta info array, return null if fail + */ + public NameValuePair[] get_metadata(String group_name, String remote_filename) throws IOException, MyException { + boolean bNewStorageServer = this.newUpdatableStorageConnection(group_name, remote_filename); + Connection connection = this.storageServer.getConnection(); + try { + ProtoCommon.RecvPackageInfo pkgInfo; + + this.send_package(ProtoCommon.STORAGE_PROTO_CMD_GET_METADATA, group_name, remote_filename, connection); + pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + return ProtoCommon.split_metadata(new String(pkgInfo.body, ClientGlobal.g_charset)); + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * set metadata items to storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param meta_list meta item array + * @param op_flag flag, can be one of following values:
+ * + * + * @return 0 for success, !=0 fail (error code) + */ + public int set_metadata(String group_name, String remote_filename, + NameValuePair[] meta_list, byte op_flag) throws IOException, MyException { + boolean bNewStorageServer = this.newUpdatableStorageConnection(group_name, remote_filename); + Connection connection = this.storageServer.getConnection(); + try { + byte[] header; + byte[] groupBytes; + byte[] filenameBytes; + byte[] meta_buff; + byte[] bs; + int groupLen; + byte[] sizeBytes; + ProtoCommon.RecvPackageInfo pkgInfo; + + if (meta_list == null) { + meta_buff = new byte[0]; + } else { + meta_buff = ProtoCommon.pack_metadata(meta_list).getBytes(ClientGlobal.g_charset); + } + + filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); + sizeBytes = new byte[2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; + Arrays.fill(sizeBytes, (byte) 0); + + bs = ProtoCommon.long2buff(filenameBytes.length); + System.arraycopy(bs, 0, sizeBytes, 0, bs.length); + bs = ProtoCommon.long2buff(meta_buff.length); + System.arraycopy(bs, 0, sizeBytes, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE, bs.length); + + groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bs = group_name.getBytes(ClientGlobal.g_charset); + + Arrays.fill(groupBytes, (byte) 0); + if (bs.length <= groupBytes.length) { + groupLen = bs.length; + } else { + groupLen = groupBytes.length; + } + System.arraycopy(bs, 0, groupBytes, 0, groupLen); + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_SET_METADATA, + 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + 1 + groupBytes.length + + filenameBytes.length + meta_buff.length, (byte) 0); + OutputStream out = connection.getOutputStream(); + byte[] wholePkg = new byte[header.length + sizeBytes.length + 1 + groupBytes.length + filenameBytes.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(sizeBytes, 0, wholePkg, header.length, sizeBytes.length); + wholePkg[header.length + sizeBytes.length] = op_flag; + System.arraycopy(groupBytes, 0, wholePkg, header.length + sizeBytes.length + 1, groupBytes.length); + System.arraycopy(filenameBytes, 0, wholePkg, header.length + sizeBytes.length + 1 + groupBytes.length, filenameBytes.length); + out.write(wholePkg); + if (meta_buff.length > 0) { + out.write(meta_buff); + } + + pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + + this.errno = pkgInfo.errno; + return pkgInfo.errno; + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * get file info decoded from the filename, fetch from the storage if necessary + * + * @param group_name the group name + * @param remote_filename the filename + * @return FileInfo object for success, return null for fail + */ + public FileInfo get_file_info(String group_name, String remote_filename) throws IOException, MyException { + if (remote_filename.length() < ProtoCommon.FDFS_FILE_PATH_LEN + ProtoCommon.FDFS_FILENAME_BASE64_LENGTH + + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } + + byte[] buff = base64.decodeAuto(remote_filename.substring(ProtoCommon.FDFS_FILE_PATH_LEN, + ProtoCommon.FDFS_FILE_PATH_LEN + ProtoCommon.FDFS_FILENAME_BASE64_LENGTH)); + + short file_type; + long file_size = ProtoCommon.buff2long(buff, 4 * 2); + if (((file_size & ProtoCommon.APPENDER_FILE_SIZE) != 0)) { + file_type = FileInfo.FILE_TYPE_APPENDER; + } else if ((remote_filename.length() > ProtoCommon.TRUNK_LOGIC_FILENAME_LENGTH) || + ((remote_filename.length() > ProtoCommon.NORMAL_LOGIC_FILENAME_LENGTH) && + ((file_size & ProtoCommon.TRUNK_FILE_MARK_SIZE) == 0))) { + file_type = FileInfo.FILE_TYPE_SLAVE; + } else { + file_type = FileInfo.FILE_TYPE_NORMAL; + } + + if (file_type == FileInfo.FILE_TYPE_SLAVE || + file_type == FileInfo.FILE_TYPE_APPENDER) { //slave file or appender file + FileInfo fi = this.query_file_info(group_name, remote_filename); + if (fi == null) { + return null; + } + + fi.setFileType(file_type); + return fi; + } + + int create_timestamp = ProtoCommon.buff2int(buff, 4); + if ((file_size >> 63) != 0) { + file_size &= 0xFFFFFFFFL; //low 32 bits is file size + } + int crc32 = ProtoCommon.buff2int(buff, 4 * 4); + + return new FileInfo(false, file_type, file_size, create_timestamp, + crc32, ProtoCommon.getIpAddress(buff, 0)); + } + + /** + * get file info from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return FileInfo object for success, return null for fail + */ + public FileInfo query_file_info(String group_name, String remote_filename) throws IOException, MyException { + boolean bNewStorageServer = this.newUpdatableStorageConnection(group_name, remote_filename); + Connection connection = this.storageServer.getConnection(); + try { + byte[] header; + byte[] groupBytes; + byte[] filenameBytes; + byte[] bs; + int groupLen; + ProtoCommon.RecvPackageInfo pkgInfo; + + filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); + groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bs = group_name.getBytes(ClientGlobal.g_charset); + + Arrays.fill(groupBytes, (byte) 0); + if (bs.length <= groupBytes.length) { + groupLen = bs.length; + } else { + groupLen = groupBytes.length; + } + System.arraycopy(bs, 0, groupBytes, 0, groupLen); + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_QUERY_FILE_INFO, + +groupBytes.length + filenameBytes.length, (byte) 0); + OutputStream out = connection.getOutputStream(); + byte[] wholePkg = new byte[header.length + groupBytes.length + filenameBytes.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(groupBytes, 0, wholePkg, header.length, groupBytes.length); + System.arraycopy(filenameBytes, 0, wholePkg, header.length + groupBytes.length, filenameBytes.length); + out.write(wholePkg); + + pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, + 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + + ProtoCommon.FDFS_IPADDR_SIZE); + + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + long file_size = ProtoCommon.buff2long(pkgInfo.body, 0); + int create_timestamp = (int) ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + int crc32 = (int) ProtoCommon.buff2long(pkgInfo.body, 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + String source_ip_addr = (new String(pkgInfo.body, 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE, ProtoCommon.FDFS_IPADDR_SIZE)).trim(); + return new FileInfo(true, FileInfo.FILE_TYPE_NORMAL, file_size, + create_timestamp, crc32, source_ip_addr); + } catch (IOException ex) { + try { + this.storageServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + doFinally(connection, bNewStorageServer); + } + } + + /** + * check storage socket, if null create a new connection + * + * @param group_name the group name to upload file to, can be empty + * @return true if create a new connection + */ + protected boolean newWritableStorageConnection(String group_name) throws IOException, MyException { + if (this.storageServer != null) { + return false; + } else { + TrackerClient tracker = new TrackerClient(); + this.storageServer = tracker.getStoreStorage(this.trackerServer, group_name); + if (this.storageServer == null) { + throw new MyException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); + } + return true; + } + } + + /** + * check storage socket, if null create a new connection + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return true if create a new connection + */ + protected boolean newReadableStorageConnection(String group_name, String remote_filename) throws IOException, MyException { + if (this.storageServer != null) { + return false; + } else { + TrackerClient tracker = new TrackerClient(); + this.storageServer = tracker.getFetchStorage(this.trackerServer, group_name, remote_filename); + if (this.storageServer == null) { + throw new MyException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); + } + return true; + } + } + + /** + * check storage socket, if null create a new connection + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return true if create a new connection + */ + protected boolean newUpdatableStorageConnection(String group_name, String remote_filename) throws IOException, MyException { + if (this.storageServer != null) { + return false; + } else { + TrackerClient tracker = new TrackerClient(); + this.storageServer = tracker.getUpdateStorage(this.trackerServer, group_name, remote_filename); + if (this.storageServer == null) { + throw new MyException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); + } + return true; + } + } + + /** + * send package to storage server + * + * @param cmd which command to send + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + */ + protected void send_package(byte cmd, String group_name, String remote_filename, Connection connection) throws IOException { + byte[] header; + byte[] groupBytes; + byte[] filenameBytes; + byte[] bs; + int groupLen; + + groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bs = group_name.getBytes(ClientGlobal.g_charset); + filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); + + Arrays.fill(groupBytes, (byte) 0); + if (bs.length <= groupBytes.length) { + groupLen = bs.length; + } else { + groupLen = groupBytes.length; + } + System.arraycopy(bs, 0, groupBytes, 0, groupLen); + + header = ProtoCommon.packHeader(cmd, groupBytes.length + filenameBytes.length, (byte) 0); + byte[] wholePkg = new byte[header.length + groupBytes.length + filenameBytes.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(groupBytes, 0, wholePkg, header.length, groupBytes.length); + System.arraycopy(filenameBytes, 0, wholePkg, header.length + groupBytes.length, filenameBytes.length); + connection.getOutputStream().write(wholePkg); + } + + /** + * send package to storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param file_offset the start offset of the file + * @param download_bytes download bytes + */ + protected void send_download_package(String group_name, String remote_filename, long file_offset, long download_bytes, Connection connection) throws IOException { + byte[] header; + byte[] bsOffset; + byte[] bsDownBytes; + byte[] groupBytes; + byte[] filenameBytes; + byte[] bs; + int groupLen; + + bsOffset = ProtoCommon.long2buff(file_offset); + bsDownBytes = ProtoCommon.long2buff(download_bytes); + groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bs = group_name.getBytes(ClientGlobal.g_charset); + filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); + + Arrays.fill(groupBytes, (byte) 0); + if (bs.length <= groupBytes.length) { + groupLen = bs.length; + } else { + groupLen = groupBytes.length; + } + System.arraycopy(bs, 0, groupBytes, 0, groupLen); + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_DOWNLOAD_FILE, + bsOffset.length + bsDownBytes.length + groupBytes.length + filenameBytes.length, (byte) 0); + byte[] wholePkg = new byte[header.length + bsOffset.length + bsDownBytes.length + groupBytes.length + filenameBytes.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(bsOffset, 0, wholePkg, header.length, bsOffset.length); + System.arraycopy(bsDownBytes, 0, wholePkg, header.length + bsOffset.length, bsDownBytes.length); + System.arraycopy(groupBytes, 0, wholePkg, header.length + bsOffset.length + bsDownBytes.length, groupBytes.length); + System.arraycopy(filenameBytes, 0, wholePkg, header.length + bsOffset.length + bsDownBytes.length + groupBytes.length, filenameBytes.length); + connection.getOutputStream().write(wholePkg); + } + + public boolean isConnected() { + return trackerServer != null; + } + + public boolean isAvaliable() { + return trackerServer != null; + } + + public void close() throws IOException { + trackerServer = null; + } + + public TrackerServer getTrackerServer() { + return trackerServer; + } + + public void setTrackerServer(TrackerServer trackerServer) { + this.trackerServer = trackerServer; + } + + public StorageServer getStorageServer() { + return storageServer; + } + + public void setStorageServer(StorageServer storageServer) { + this.storageServer = storageServer; + } + + /** + * Upload file by file buff + * + * @author Happy Fish / YuQing + * @version Version 1.12 + */ + public static class UploadBuff implements UploadCallback { + private byte[] fileBuff; + private int offset; + private int length; + + /** + * constructor + * + * @param fileBuff the file buff for uploading + */ + public UploadBuff(byte[] fileBuff, int offset, int length) { + super(); + this.fileBuff = fileBuff; + this.offset = offset; + this.length = length; + } + + /** + * send file content callback function, be called only once when the file uploaded + * + * @param out output stream for writing file content + * @return 0 success, return none zero(errno) if fail + */ + public int send(OutputStream out) throws IOException { + out.write(this.fileBuff, this.offset, this.length); + + return 0; + } } - } } diff --git a/src/main/java/org/csource/fastdfs/TrackerClient.java b/src/main/java/org/csource/fastdfs/TrackerClient.java index d8d6cc0..ab1917f 100644 --- a/src/main/java/org/csource/fastdfs/TrackerClient.java +++ b/src/main/java/org/csource/fastdfs/TrackerClient.java @@ -8,6 +8,9 @@ package org.csource.fastdfs; +import org.csource.common.MyException; +import org.csource.fastdfs.pool.Connection; + import java.io.IOException; import java.io.OutputStream; import java.net.Socket; @@ -21,792 +24,760 @@ import java.util.Arrays; * @version Version 1.19 */ public class TrackerClient { - protected TrackerGroup tracker_group; - protected byte errno; + protected TrackerGroup tracker_group; + protected byte errno; - /** - * constructor with global tracker group - */ - public TrackerClient() { - this.tracker_group = ClientGlobal.g_tracker_group; - } - - /** - * constructor with specified tracker group - * - * @param tracker_group the tracker group object - */ - public TrackerClient(TrackerGroup tracker_group) { - this.tracker_group = tracker_group; - } - - /** - * get the error code of last call - * - * @return the error code of last call - */ - public byte getErrorCode() { - return this.errno; - } - - /** - * get a connection to tracker server - * - * @return tracker server Socket object, return null if fail - */ - public TrackerServer getConnection() throws IOException { - return this.tracker_group.getConnection(); - } - - /** - * query storage server to upload file - * - * @param trackerServer the tracker server - * @return storage server Socket object, return null if fail - */ - public StorageServer getStoreStorage(TrackerServer trackerServer) throws IOException { - final String groupName = null; - return this.getStoreStorage(trackerServer, groupName); - } - - /** - * query storage server to upload file - * - * @param trackerServer the tracker server - * @param groupName the group name to upload file to, can be empty - * @return storage server object, return null if fail - */ - public StorageServer getStoreStorage(TrackerServer trackerServer, String groupName) throws IOException { - byte[] header; - String ip_addr; - int port; - byte cmd; - int out_len; - boolean bNewConnection; - byte store_path; - Socket trackerSocket; - - if (trackerServer == null) { - trackerServer = getConnection(); - if (trackerServer == null) { - return null; - } - bNewConnection = true; - } else { - bNewConnection = false; + /** + * constructor with global tracker group + */ + public TrackerClient() { + this.tracker_group = ClientGlobal.g_tracker_group; } - trackerSocket = trackerServer.getSocket(); - OutputStream out = trackerSocket.getOutputStream(); + /** + * constructor with specified tracker group + * + * @param tracker_group the tracker group object + */ + public TrackerClient(TrackerGroup tracker_group) { + this.tracker_group = tracker_group; + } - try { - if (groupName == null || groupName.length() == 0) { - cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE; - out_len = 0; - } else { - cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE; - out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; - } - header = ProtoCommon.packHeader(cmd, out_len, (byte) 0); - out.write(header); + /** + * get the error code of last call + * + * @return the error code of last call + */ + public byte getErrorCode() { + return this.errno; + } - if (groupName != null && groupName.length() > 0) { - byte[] bGroupName; - byte[] bs; - int group_len; + /** + * get a connection to tracker server + * + * @return tracker server Socket object, return null if fail + */ + public TrackerServer getTrackerServer() throws IOException { + return this.tracker_group.getTrackerServer(); + } - bs = groupName.getBytes(ClientGlobal.g_charset); - bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + /** + * query storage server to upload file + * + * @param trackerServer the tracker server + * @return storage server Socket object, return null if fail + */ + public StorageServer getStoreStorage(TrackerServer trackerServer) throws IOException, MyException { + final String groupName = null; + return this.getStoreStorage(trackerServer, groupName); + } - if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { - group_len = bs.length; - } else { - group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + /** + * query storage server to upload file + * + * @param trackerServer the tracker server + * @param groupName the group name to upload file to, can be empty + * @return storage server object, return null if fail + */ + public StorageServer getStoreStorage(TrackerServer trackerServer, String groupName) throws IOException, MyException { + byte[] header; + String ip_addr; + int port; + byte cmd; + int out_len; + byte store_path; + Connection connection; + + if (trackerServer == null) { + trackerServer = getTrackerServer(); } - Arrays.fill(bGroupName, (byte) 0); - System.arraycopy(bs, 0, bGroupName, 0, group_len); - out.write(bGroupName); - } + connection = trackerServer.getConnection(); + OutputStream out = connection.getOutputStream(); - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), - ProtoCommon.TRACKER_PROTO_CMD_RESP, - ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); - - port = (int) ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN - + ProtoCommon.FDFS_IPADDR_SIZE - 1); - store_path = pkgInfo.body[ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN - 1]; - - return new StorageServer(ip_addr, port, store_path); - } catch (IOException ex) { - if (!bNewConnection) { try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - } - } - - /** - * query storage servers to upload file - * - * @param trackerServer the tracker server - * @param groupName the group name to upload file to, can be empty - * @return storage servers, return null if fail - */ - public StorageServer[] getStoreStorages(TrackerServer trackerServer, String groupName) throws IOException { - byte[] header; - String ip_addr; - int port; - byte cmd; - int out_len; - boolean bNewConnection; - Socket trackerSocket; - - if (trackerServer == null) { - trackerServer = getConnection(); - if (trackerServer == null) { - return null; - } - bNewConnection = true; - } else { - bNewConnection = false; - } - - trackerSocket = trackerServer.getSocket(); - OutputStream out = trackerSocket.getOutputStream(); - - try { - if (groupName == null || groupName.length() == 0) { - cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL; - out_len = 0; - } else { - cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL; - out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; - } - header = ProtoCommon.packHeader(cmd, out_len, (byte) 0); - out.write(header); - - if (groupName != null && groupName.length() > 0) { - byte[] bGroupName; - byte[] bs; - int group_len; - - bs = groupName.getBytes(ClientGlobal.g_charset); - bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; - - if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { - group_len = bs.length; - } else { - group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; - } - Arrays.fill(bGroupName, (byte) 0); - System.arraycopy(bs, 0, bGroupName, 0, group_len); - out.write(bGroupName); - } - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), - ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN) { - this.errno = ProtoCommon.ERR_NO_EINVAL; - return null; - } - - int ipPortLen = pkgInfo.body.length - (ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + 1); - final int recordLength = ProtoCommon.FDFS_IPADDR_SIZE - 1 + ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; - - if (ipPortLen % recordLength != 0) { - this.errno = ProtoCommon.ERR_NO_EINVAL; - return null; - } - - int serverCount = ipPortLen / recordLength; - if (serverCount > 16) { - this.errno = ProtoCommon.ERR_NO_ENOSPC; - return null; - } - - StorageServer[] results = new StorageServer[serverCount]; - byte store_path = pkgInfo.body[pkgInfo.body.length - 1]; - int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; - - for (int i = 0; i < serverCount; i++) { - ip_addr = new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); - offset += ProtoCommon.FDFS_IPADDR_SIZE - 1; - - port = (int) ProtoCommon.buff2long(pkgInfo.body, offset); - offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; - - results[i] = new StorageServer(ip_addr, port, store_path); - } - - return results; - } catch (IOException ex) { - if (!bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - } - } - - /** - * query storage server to download file - * - * @param trackerServer the tracker server - * @param groupName the group name of storage server - * @param filename filename on storage server - * @return storage server Socket object, return null if fail - */ - public StorageServer getFetchStorage(TrackerServer trackerServer, - String groupName, String filename) throws IOException { - ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE, - groupName, filename); - if (servers == null) { - return null; - } else { - return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0); - } - } - - /** - * query storage server to update file (delete file or set meta data) - * - * @param trackerServer the tracker server - * @param groupName the group name of storage server - * @param filename filename on storage server - * @return storage server Socket object, return null if fail - */ - public StorageServer getUpdateStorage(TrackerServer trackerServer, - String groupName, String filename) throws IOException { - ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE, - groupName, filename); - if (servers == null) { - return null; - } else { - return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0); - } - } - - /** - * get storage servers to download file - * - * @param trackerServer the tracker server - * @param groupName the group name of storage server - * @param filename filename on storage server - * @return storage servers, return null if fail - */ - public ServerInfo[] getFetchStorages(TrackerServer trackerServer, - String groupName, String filename) throws IOException { - return this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL, - groupName, filename); - } - - /** - * query storage server to download file - * - * @param trackerServer the tracker server - * @param cmd command code, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE or - * ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE - * @param groupName the group name of storage server - * @param filename filename on storage server - * @return storage server Socket object, return null if fail - */ - protected ServerInfo[] getStorages(TrackerServer trackerServer, - byte cmd, String groupName, String filename) throws IOException { - byte[] header; - byte[] bFileName; - byte[] bGroupName; - byte[] bs; - int len; - String ip_addr; - int port; - boolean bNewConnection; - Socket trackerSocket; - - if (trackerServer == null) { - trackerServer = getConnection(); - if (trackerServer == null) { - return null; - } - bNewConnection = true; - } else { - bNewConnection = false; - } - trackerSocket = trackerServer.getSocket(); - OutputStream out = trackerSocket.getOutputStream(); - - try { - bs = groupName.getBytes(ClientGlobal.g_charset); - bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; - bFileName = filename.getBytes(ClientGlobal.g_charset); - - if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { - len = bs.length; - } else { - len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; - } - Arrays.fill(bGroupName, (byte) 0); - System.arraycopy(bs, 0, bGroupName, 0, len); - - header = ProtoCommon.packHeader(cmd, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + bFileName.length, (byte) 0); - byte[] wholePkg = new byte[header.length + bGroupName.length + bFileName.length]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); - System.arraycopy(bFileName, 0, wholePkg, header.length + bGroupName.length, bFileName.length); - out.write(wholePkg); - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), - ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) { - throw new IOException("Invalid body length: " + pkgInfo.body.length); - } - - if ((pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) % (ProtoCommon.FDFS_IPADDR_SIZE - 1) != 0) { - throw new IOException("Invalid body length: " + pkgInfo.body.length); - } - - int server_count = 1 + (pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) / (ProtoCommon.FDFS_IPADDR_SIZE - 1); - - ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); - int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ProtoCommon.FDFS_IPADDR_SIZE - 1; - - port = (int) ProtoCommon.buff2long(pkgInfo.body, offset); - offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; - - ServerInfo[] servers = new ServerInfo[server_count]; - servers[0] = new ServerInfo(ip_addr, port); - for (int i = 1; i < server_count; i++) { - servers[i] = new ServerInfo(new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(), port); - offset += ProtoCommon.FDFS_IPADDR_SIZE - 1; - } - - return servers; - } catch (IOException ex) { - if (!bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - - throw ex; - } finally { - if (bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - } - } - - /** - * query storage server to download file - * - * @param trackerServer the tracker server - * @param file_id the file id(including group name and filename) - * @return storage server Socket object, return null if fail - */ - public StorageServer getFetchStorage1(TrackerServer trackerServer, String file_id) throws IOException { - String[] parts = new String[2]; - this.errno = StorageClient1.split_file_id(file_id, parts); - if (this.errno != 0) { - return null; - } - - return this.getFetchStorage(trackerServer, parts[0], parts[1]); - } - - /** - * get storage servers to download file - * - * @param trackerServer the tracker server - * @param file_id the file id(including group name and filename) - * @return storage servers, return null if fail - */ - public ServerInfo[] getFetchStorages1(TrackerServer trackerServer, String file_id) throws IOException { - String[] parts = new String[2]; - this.errno = StorageClient1.split_file_id(file_id, parts); - if (this.errno != 0) { - return null; - } - - return this.getFetchStorages(trackerServer, parts[0], parts[1]); - } - - /** - * list groups - * - * @param trackerServer the tracker server - * @return group stat array, return null if fail - */ - public StructGroupStat[] listGroups(TrackerServer trackerServer) throws IOException { - byte[] header; - String ip_addr; - int port; - byte cmd; - int out_len; - boolean bNewConnection; - byte store_path; - Socket trackerSocket; - - if (trackerServer == null) { - trackerServer = getConnection(); - if (trackerServer == null) { - return null; - } - bNewConnection = true; - } else { - bNewConnection = false; - } - - trackerSocket = trackerServer.getSocket(); - OutputStream out = trackerSocket.getOutputStream(); - - try { - header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_GROUP, 0, (byte) 0); - out.write(header); - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), - ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - ProtoStructDecoder decoder = new ProtoStructDecoder(); - return decoder.decode(pkgInfo.body, StructGroupStat.class, StructGroupStat.getFieldsTotalSize()); - } catch (IOException ex) { - if (!bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - - throw ex; - } catch (Exception ex) { - ex.printStackTrace(); - this.errno = ProtoCommon.ERR_NO_EINVAL; - return null; - } finally { - if (bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - } - } - - /** - * query storage server stat info of the group - * - * @param trackerServer the tracker server - * @param groupName the group name of storage server - * @return storage server stat array, return null if fail - */ - public StructStorageStat[] listStorages(TrackerServer trackerServer, String groupName) throws IOException { - final String storageIpAddr = null; - return this.listStorages(trackerServer, groupName, storageIpAddr); - } - - /** - * query storage server stat info of the group - * - * @param trackerServer the tracker server - * @param groupName the group name of storage server - * @param storageIpAddr the storage server ip address, can be null or empty - * @return storage server stat array, return null if fail - */ - public StructStorageStat[] listStorages(TrackerServer trackerServer, - String groupName, String storageIpAddr) throws IOException { - byte[] header; - byte[] bGroupName; - byte[] bs; - int len; - boolean bNewConnection; - Socket trackerSocket; - - if (trackerServer == null) { - trackerServer = getConnection(); - if (trackerServer == null) { - return null; - } - bNewConnection = true; - } else { - bNewConnection = false; - } - trackerSocket = trackerServer.getSocket(); - OutputStream out = trackerSocket.getOutputStream(); - - try { - bs = groupName.getBytes(ClientGlobal.g_charset); - bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; - - if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { - len = bs.length; - } else { - len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; - } - Arrays.fill(bGroupName, (byte) 0); - System.arraycopy(bs, 0, bGroupName, 0, len); - - int ipAddrLen; - byte[] bIpAddr; - if (storageIpAddr != null && storageIpAddr.length() > 0) { - bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset); - if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) { - ipAddrLen = bIpAddr.length; - } else { - ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1; - } - } else { - bIpAddr = null; - ipAddrLen = 0; - } - - header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0); - byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); - if (ipAddrLen > 0) { - System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen); - } - out.write(wholePkg); - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), - ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); - this.errno = pkgInfo.errno; - if (pkgInfo.errno != 0) { - return null; - } - - ProtoStructDecoder decoder = new ProtoStructDecoder(); - return decoder.decode(pkgInfo.body, StructStorageStat.class, StructStorageStat.getFieldsTotalSize()); - } catch (IOException ex) { - if (!bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - - throw ex; - } catch (Exception ex) { - ex.printStackTrace(); - this.errno = ProtoCommon.ERR_NO_EINVAL; - return null; - } finally { - if (bNewConnection) { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - } - } - - /** - * delete a storage server from the tracker server - * - * @param trackerServer the connected tracker server - * @param groupName the group name of storage server - * @param storageIpAddr the storage server ip address - * @return true for success, false for fail - */ - private boolean deleteStorage(TrackerServer trackerServer, - String groupName, String storageIpAddr) throws IOException { - byte[] header; - byte[] bGroupName; - byte[] bs; - int len; - Socket trackerSocket; - - trackerSocket = trackerServer.getSocket(); - OutputStream out = trackerSocket.getOutputStream(); - - bs = groupName.getBytes(ClientGlobal.g_charset); - bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; - - if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { - len = bs.length; - } else { - len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; - } - Arrays.fill(bGroupName, (byte) 0); - System.arraycopy(bs, 0, bGroupName, 0, len); - - int ipAddrLen; - byte[] bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset); - if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) { - ipAddrLen = bIpAddr.length; - } else { - ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1; - } - - header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0); - byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen]; - System.arraycopy(header, 0, wholePkg, 0, header.length); - System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); - System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen); - out.write(wholePkg); - - ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), - ProtoCommon.TRACKER_PROTO_CMD_RESP, 0); - this.errno = pkgInfo.errno; - return pkgInfo.errno == 0; - } - - /** - * delete a storage server from the global FastDFS cluster - * - * @param groupName the group name of storage server - * @param storageIpAddr the storage server ip address - * @return true for success, false for fail - */ - public boolean deleteStorage(String groupName, String storageIpAddr) throws IOException { - return this.deleteStorage(ClientGlobal.g_tracker_group, groupName, storageIpAddr); - } - - /** - * delete a storage server from the FastDFS cluster - * - * @param trackerGroup the tracker server group - * @param groupName the group name of storage server - * @param storageIpAddr the storage server ip address - * @return true for success, false for fail - */ - public boolean deleteStorage(TrackerGroup trackerGroup, - String groupName, String storageIpAddr) throws IOException { - int serverIndex; - int notFoundCount; - TrackerServer trackerServer; - - notFoundCount = 0; - for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) { - try { - trackerServer = trackerGroup.getConnection(serverIndex); - } catch (IOException ex) { - ex.printStackTrace(System.err); - this.errno = ProtoCommon.ECONNREFUSED; - return false; - } - - try { - StructStorageStat[] storageStats = listStorages(trackerServer, groupName, storageIpAddr); - if (storageStats == null) { - if (this.errno == ProtoCommon.ERR_NO_ENOENT) { - notFoundCount++; - } else { - return false; - } - } else if (storageStats.length == 0) { - notFoundCount++; - } else if (storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ONLINE || - storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ACTIVE) { - this.errno = ProtoCommon.ERR_NO_EBUSY; - return false; - } - } finally { - try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); - } - } - } - - if (notFoundCount == trackerGroup.tracker_servers.length) { - this.errno = ProtoCommon.ERR_NO_ENOENT; - return false; - } - - notFoundCount = 0; - for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) { - try { - trackerServer = trackerGroup.getConnection(serverIndex); - } catch (IOException ex) { - System.err.println("connect to server " + trackerGroup.tracker_servers[serverIndex].getAddress().getHostAddress() + ":" + trackerGroup.tracker_servers[serverIndex].getPort() + " fail"); - ex.printStackTrace(System.err); - this.errno = ProtoCommon.ECONNREFUSED; - return false; - } - - try { - if (!this.deleteStorage(trackerServer, groupName, storageIpAddr)) { - if (this.errno != 0) { - if (this.errno == ProtoCommon.ERR_NO_ENOENT) { - notFoundCount++; - } else if (this.errno != ProtoCommon.ERR_NO_EALREADY) { - return false; + if (groupName == null || groupName.length() == 0) { + cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE; + out_len = 0; + } else { + cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE; + out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + header = ProtoCommon.packHeader(cmd, out_len, (byte) 0); + out.write(header); + + if (groupName != null && groupName.length() > 0) { + byte[] bGroupName; + byte[] bs; + int group_len; + + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + group_len = bs.length; + } else { + group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, group_len); + out.write(bGroupName); + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, + ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); + + port = (int) ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + + ProtoCommon.FDFS_IPADDR_SIZE - 1); + store_path = pkgInfo.body[ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN - 1]; + + return new StorageServer(ip_addr, port, store_path); + } catch (IOException ex) { + try { + trackerServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + if (connection != null) { + try { + trackerServer.releaseConnection(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } } - } } - } finally { + } + + /** + * query storage servers to upload file + * + * @param trackerServer the tracker server + * @param groupName the group name to upload file to, can be empty + * @return storage servers, return null if fail + */ + public StorageServer[] getStoreStorages(TrackerServer trackerServer, String groupName) throws IOException, MyException { + byte[] header; + String ip_addr; + int port; + byte cmd; + int out_len; + Connection connection; + + if (trackerServer == null) { + trackerServer = getTrackerServer(); + if (trackerServer == null) { + return null; + } + } + + connection = trackerServer.getConnection(); + OutputStream out = connection.getOutputStream(); + try { - trackerServer.close(); - } catch (IOException ex1) { - ex1.printStackTrace(); + if (groupName == null || groupName.length() == 0) { + cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL; + out_len = 0; + } else { + cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL; + out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + header = ProtoCommon.packHeader(cmd, out_len, (byte) 0); + out.write(header); + + if (groupName != null && groupName.length() > 0) { + byte[] bGroupName; + byte[] bs; + int group_len; + + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + group_len = bs.length; + } else { + group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, group_len); + out.write(bGroupName); + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } + + int ipPortLen = pkgInfo.body.length - (ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + 1); + final int recordLength = ProtoCommon.FDFS_IPADDR_SIZE - 1 + ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + if (ipPortLen % recordLength != 0) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } + + int serverCount = ipPortLen / recordLength; + if (serverCount > 16) { + this.errno = ProtoCommon.ERR_NO_ENOSPC; + return null; + } + + StorageServer[] results = new StorageServer[serverCount]; + byte store_path = pkgInfo.body[pkgInfo.body.length - 1]; + int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + + for (int i = 0; i < serverCount; i++) { + ip_addr = new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); + offset += ProtoCommon.FDFS_IPADDR_SIZE - 1; + + port = (int) ProtoCommon.buff2long(pkgInfo.body, offset); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + results[i] = new StorageServer(ip_addr, port, store_path); + } + + return results; + } catch (IOException ex) { + try { + trackerServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } finally { + if (connection != null) { + try { + trackerServer.releaseConnection(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } } - } } - if (notFoundCount == trackerGroup.tracker_servers.length) { - this.errno = ProtoCommon.ERR_NO_ENOENT; - return false; + /** + * query storage server to download file + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @param filename filename on storage server + * @return storage server Socket object, return null if fail + */ + public StorageServer getFetchStorage(TrackerServer trackerServer, + String groupName, String filename) throws IOException, MyException { + ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE, + groupName, filename); + if (servers == null) { + return null; + } else { + return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0); + } } - if (this.errno == ProtoCommon.ERR_NO_ENOENT) { - this.errno = 0; + /** + * query storage server to update file (delete file or set meta data) + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @param filename filename on storage server + * @return storage server Socket object, return null if fail + */ + public StorageServer getUpdateStorage(TrackerServer trackerServer, + String groupName, String filename) throws IOException, MyException { + ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE, + groupName, filename); + if (servers == null) { + return null; + } else { + return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0); + } } - return this.errno == 0; - } + /** + * get storage servers to download file + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @param filename filename on storage server + * @return storage servers, return null if fail + */ + public ServerInfo[] getFetchStorages(TrackerServer trackerServer, + String groupName, String filename) throws IOException, MyException { + return this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL, + groupName, filename); + } + + /** + * query storage server to download file + * + * @param trackerServer the tracker server + * @param cmd command code, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE or + * ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE + * @param groupName the group name of storage server + * @param filename filename on storage server + * @return storage server Socket object, return null if fail + */ + protected ServerInfo[] getStorages(TrackerServer trackerServer, + byte cmd, String groupName, String filename) throws IOException, MyException { + byte[] header; + byte[] bFileName; + byte[] bGroupName; + byte[] bs; + int len; + String ip_addr; + int port; + Connection connection; + + if (trackerServer == null) { + trackerServer = getTrackerServer(); + if (trackerServer == null) { + return null; + } + } + connection = trackerServer.getConnection(); + OutputStream out = connection.getOutputStream(); + + try { + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bFileName = filename.getBytes(ClientGlobal.g_charset); + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + len = bs.length; + } else { + len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, len); + + header = ProtoCommon.packHeader(cmd, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + bFileName.length, (byte) 0); + byte[] wholePkg = new byte[header.length + bGroupName.length + bFileName.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); + System.arraycopy(bFileName, 0, wholePkg, header.length + bGroupName.length, bFileName.length); + out.write(wholePkg); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) { + throw new IOException("Invalid body length: " + pkgInfo.body.length); + } + + if ((pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) % (ProtoCommon.FDFS_IPADDR_SIZE - 1) != 0) { + throw new IOException("Invalid body length: " + pkgInfo.body.length); + } + + int server_count = 1 + (pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) / (ProtoCommon.FDFS_IPADDR_SIZE - 1); + + ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); + int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ProtoCommon.FDFS_IPADDR_SIZE - 1; + + port = (int) ProtoCommon.buff2long(pkgInfo.body, offset); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + ServerInfo[] servers = new ServerInfo[server_count]; + servers[0] = new ServerInfo(ip_addr, port); + for (int i = 1; i < server_count; i++) { + servers[i] = new ServerInfo(new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(), port); + offset += ProtoCommon.FDFS_IPADDR_SIZE - 1; + } + + return servers; + } catch (IOException ex) { + try { + trackerServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + + throw ex; + } finally { + if (connection != null) { + try { + trackerServer.releaseConnection(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + } + + /** + * query storage server to download file + * + * @param trackerServer the tracker server + * @param file_id the file id(including group name and filename) + * @return storage server Socket object, return null if fail + */ + public StorageServer getFetchStorage1(TrackerServer trackerServer, String file_id) throws IOException, MyException { + String[] parts = new String[2]; + this.errno = StorageClient1.split_file_id(file_id, parts); + if (this.errno != 0) { + return null; + } + + return this.getFetchStorage(trackerServer, parts[0], parts[1]); + } + + /** + * get storage servers to download file + * + * @param trackerServer the tracker server + * @param file_id the file id(including group name and filename) + * @return storage servers, return null if fail + */ + public ServerInfo[] getFetchStorages1(TrackerServer trackerServer, String file_id) throws IOException, MyException { + String[] parts = new String[2]; + this.errno = StorageClient1.split_file_id(file_id, parts); + if (this.errno != 0) { + return null; + } + + return this.getFetchStorages(trackerServer, parts[0], parts[1]); + } + + /** + * list groups + * + * @param trackerServer the tracker server + * @return group stat array, return null if fail + */ + public StructGroupStat[] listGroups(TrackerServer trackerServer) throws IOException, MyException { + byte[] header; + String ip_addr; + int port; + byte cmd; + int out_len; + byte store_path; + Connection connection; + + if (trackerServer == null) { + trackerServer = getTrackerServer(); + if (trackerServer == null) { + return null; + } + } + + connection = trackerServer.getConnection(); + OutputStream out = connection.getOutputStream(); + + try { + header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_GROUP, 0, (byte) 0); + out.write(header); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + ProtoStructDecoder decoder = new ProtoStructDecoder(); + return decoder.decode(pkgInfo.body, StructGroupStat.class, StructGroupStat.getFieldsTotalSize()); + } catch (IOException ex) { + try { + trackerServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + connection = null; + } + throw ex; + } catch (Exception ex) { + ex.printStackTrace(); + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } finally { + if (connection != null) { + try { + trackerServer.releaseConnection(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + } + + /** + * query storage server stat info of the group + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @return storage server stat array, return null if fail + */ + public StructStorageStat[] listStorages(TrackerServer trackerServer, String groupName) throws IOException, MyException { + final String storageIpAddr = null; + return this.listStorages(trackerServer, groupName, storageIpAddr); + } + + /** + * query storage server stat info of the group + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @param storageIpAddr the storage server ip address, can be null or empty + * @return storage server stat array, return null if fail + */ + public StructStorageStat[] listStorages(TrackerServer trackerServer, + String groupName, String storageIpAddr) throws IOException, MyException { + byte[] header; + byte[] bGroupName; + byte[] bs; + int len; + Connection connection; + + if (trackerServer == null) { + trackerServer = getTrackerServer(); + if (trackerServer == null) { + return null; + } + } + connection = trackerServer.getConnection(); + OutputStream out = connection.getOutputStream(); + + try { + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + len = bs.length; + } else { + len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, len); + + int ipAddrLen; + byte[] bIpAddr; + if (storageIpAddr != null && storageIpAddr.length() > 0) { + bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset); + if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) { + ipAddrLen = bIpAddr.length; + } else { + ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1; + } + } else { + bIpAddr = null; + ipAddrLen = 0; + } + + header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0); + byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); + if (ipAddrLen > 0) { + System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen); + } + out.write(wholePkg); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + ProtoStructDecoder decoder = new ProtoStructDecoder(); + return decoder.decode(pkgInfo.body, StructStorageStat.class, StructStorageStat.getFieldsTotalSize()); + } catch (IOException ex) { + try { + trackerServer.close(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + + throw ex; + } catch (Exception ex) { + ex.printStackTrace(); + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } finally { + if (connection != null) { + try { + trackerServer.releaseConnection(connection); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + } + + /** + * delete a storage server from the tracker server + * + * @param trackerServer the connected tracker server + * @param groupName the group name of storage server + * @param storageIpAddr the storage server ip address + * @return true for success, false for fail + */ + private boolean deleteStorage(TrackerServer trackerServer, + String groupName, String storageIpAddr) throws IOException, MyException { + byte[] header; + byte[] bGroupName; + byte[] bs; + int len; + Connection connection; + + connection = trackerServer.getConnection(); + OutputStream out = connection.getOutputStream(); + + try { + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + len = bs.length; + } else { + len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, len); + + int ipAddrLen; + byte[] bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset); + if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) { + ipAddrLen = bIpAddr.length; + } else { + ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1; + } + + header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0); + byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); + System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen); + out.write(wholePkg); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(connection.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, 0); + this.errno = pkgInfo.errno; + return pkgInfo.errno == 0; + } catch (IOException e) { + try { + trackerServer.close(connection); + } finally { + connection = null; + } + throw e; + } finally { + if (connection != null) { + trackerServer.releaseConnection(connection); + } + } + } + + /** + * delete a storage server from the global FastDFS cluster + * + * @param groupName the group name of storage server + * @param storageIpAddr the storage server ip address + * @return true for success, false for fail + */ + public boolean deleteStorage(String groupName, String storageIpAddr) throws IOException, MyException { + return this.deleteStorage(ClientGlobal.g_tracker_group, groupName, storageIpAddr); + } + + /** + * delete a storage server from the FastDFS cluster + * + * @param trackerGroup the tracker server group + * @param groupName the group name of storage server + * @param storageIpAddr the storage server ip address + * @return true for success, false for fail + */ + public boolean deleteStorage(TrackerGroup trackerGroup, + String groupName, String storageIpAddr) throws IOException, MyException { + int serverIndex; + int notFoundCount; + TrackerServer trackerServer; + + notFoundCount = 0; + for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) { + try { + trackerServer = trackerGroup.getTrackerServer(serverIndex); + } catch (IOException ex) { + ex.printStackTrace(System.err); + this.errno = ProtoCommon.ECONNREFUSED; + return false; + } + StructStorageStat[] storageStats = listStorages(trackerServer, groupName, storageIpAddr); + if (storageStats == null) { + if (this.errno == ProtoCommon.ERR_NO_ENOENT) { + notFoundCount++; + } else { + return false; + } + } else if (storageStats.length == 0) { + notFoundCount++; + } else if (storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ONLINE || + storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ACTIVE) { + this.errno = ProtoCommon.ERR_NO_EBUSY; + return false; + } + + } + + if (notFoundCount == trackerGroup.tracker_servers.length) { + this.errno = ProtoCommon.ERR_NO_ENOENT; + return false; + } + + notFoundCount = 0; + for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) { + try { + trackerServer = trackerGroup.getTrackerServer(serverIndex); + } catch (IOException ex) { + System.err.println("connect to server " + trackerGroup.tracker_servers[serverIndex].getAddress().getHostAddress() + ":" + trackerGroup.tracker_servers[serverIndex].getPort() + " fail"); + ex.printStackTrace(System.err); + this.errno = ProtoCommon.ECONNREFUSED; + return false; + } + if (!this.deleteStorage(trackerServer, groupName, storageIpAddr)) { + if (this.errno != 0) { + if (this.errno == ProtoCommon.ERR_NO_ENOENT) { + notFoundCount++; + } else if (this.errno != ProtoCommon.ERR_NO_EALREADY) { + return false; + } + } + } + + } + + if (notFoundCount == trackerGroup.tracker_servers.length) { + this.errno = ProtoCommon.ERR_NO_ENOENT; + return false; + } + + if (this.errno == ProtoCommon.ERR_NO_ENOENT) { + this.errno = 0; + } + + return this.errno == 0; + } } diff --git a/src/main/java/org/csource/fastdfs/TrackerGroup.java b/src/main/java/org/csource/fastdfs/TrackerGroup.java index 9ba83cf..dfcfd74 100644 --- a/src/main/java/org/csource/fastdfs/TrackerGroup.java +++ b/src/main/java/org/csource/fastdfs/TrackerGroup.java @@ -10,7 +10,6 @@ package org.csource.fastdfs; import java.io.IOException; import java.net.InetSocketAddress; -import java.net.Socket; /** * Tracker server group @@ -39,7 +38,7 @@ public class TrackerGroup { * * @return connected tracker server, null for fail */ - public TrackerServer getConnection(int serverIndex) throws IOException { + public TrackerServer getTrackerServer(int serverIndex) throws IOException { return new TrackerServer(this.tracker_servers[serverIndex]); } @@ -48,7 +47,7 @@ public class TrackerGroup { * * @return connected tracker server, null for fail */ - public TrackerServer getConnection() throws IOException { + public TrackerServer getTrackerServer() throws IOException { int current_index; synchronized (this.lock) { @@ -61,7 +60,7 @@ public class TrackerGroup { } try { - return this.getConnection(current_index); + return this.getTrackerServer(current_index); } catch (IOException ex) { System.err.println("connect to server " + this.tracker_servers[current_index].getAddress().getHostAddress() + ":" + this.tracker_servers[current_index].getPort() + " fail"); ex.printStackTrace(System.err); @@ -73,7 +72,7 @@ public class TrackerGroup { } try { - TrackerServer trackerServer = this.getConnection(i); + TrackerServer trackerServer = this.getTrackerServer(i); synchronized (this.lock) { if (this.tracker_server_index == current_index) { diff --git a/src/main/java/org/csource/fastdfs/TrackerServer.java b/src/main/java/org/csource/fastdfs/TrackerServer.java index 4d5c31f..a497471 100644 --- a/src/main/java/org/csource/fastdfs/TrackerServer.java +++ b/src/main/java/org/csource/fastdfs/TrackerServer.java @@ -8,14 +8,13 @@ package org.csource.fastdfs; -import org.csource.fastdfs.pool.ConnectionInfo; +import org.csource.common.MyException; +import org.csource.fastdfs.pool.Connection; import org.csource.fastdfs.pool.ConnectionPool; +import org.csource.fastdfs.pool.ConnectionFactory; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.net.InetSocketAddress; -import java.net.Socket; /** * Tracker Server Info @@ -24,46 +23,22 @@ import java.net.Socket; * @version Version 1.11 */ public class TrackerServer { - protected Socket sock; protected InetSocketAddress inetSockAddr; - private Long lastAccessTime = System.currentTimeMillis(); - - /** - * Constructor - * - * @param sock Socket of server - * @param inetSockAddr the server info - */ - public TrackerServer(Socket sock, InetSocketAddress inetSockAddr) { - this.sock = sock; - this.inetSockAddr = inetSockAddr; - } public TrackerServer(InetSocketAddress inetSockAddr) throws IOException { this.inetSockAddr = inetSockAddr; - this.sock = getSocket(); } - /** - * get the connected socket - * - * @return the socket - */ - public Socket getSocket() throws IOException { - if (this.sock == null) { - if (ClientGlobal.g_connection_pool_enabled) { - ConnectionInfo connection = ConnectionPool.getConnection(this.inetSockAddr); - this.sock = connection.getSocket(); - this.lastAccessTime = connection.getLastAccessTime(); - } else { - this.sock = ClientGlobal.getSocket(this.inetSockAddr); - } + public Connection getConnection() throws MyException, IOException { + Connection connection; + if (ClientGlobal.g_connection_pool_enabled) { + connection = ConnectionPool.getConnection(this.inetSockAddr); + } else { + connection = ConnectionFactory.create(this.inetSockAddr); } - - return this.sock; + return connection; } - /** * get the server info * @@ -72,88 +47,28 @@ public class TrackerServer { public InetSocketAddress getInetSocketAddress() { return this.inetSockAddr; } - - public OutputStream getOutputStream() throws IOException { - return this.sock.getOutputStream(); - } - - public InputStream getInputStream() throws IOException { - return this.sock.getInputStream(); - } - - public void close() throws IOException { + public void close(Connection connection) throws IOException { //if connection enabled get from connection pool if (ClientGlobal.g_connection_pool_enabled) { - ConnectionPool.freeConnection(this); + ConnectionPool.closeConnection(connection); } else { - this.closeDirect(); + connection.close(); } } /** - * close direct if not create from pool or not open pool + * releaseConnection connection + * @param connection * @throws IOException */ - public void closeDirect() throws IOException { - if (this.sock != null) { - try { - ProtoCommon.closeSocket(this.sock); - } finally { - this.sock = null; - } + public void releaseConnection(Connection connection) throws IOException { + if (ClientGlobal.g_connection_pool_enabled) { + ConnectionPool.releaseConnection(connection); + } else { + connection.close(); } } - protected void finalize() throws Throwable { - this.close(); - } - public boolean isConnected() { - boolean isConnected = false; - if (sock != null) { - if (sock.isConnected()) { - isConnected = true; - } - } - return isConnected; - } - public boolean isAvaliable() { - if (isConnected()) { - if (sock.getPort() == 0) { - return false; - } - if (sock.getInetAddress() == null) { - return false; - } - if (sock.getRemoteSocketAddress() == null) { - return false; - } - if (sock.isInputShutdown()) { - return false; - } - if (sock.isOutputShutdown()) { - return false; - } - return true; - } - return false; - } - - public Long getLastAccessTime() { - return lastAccessTime; - } - - public void setLastAccessTime(Long lastAccessTime) { - this.lastAccessTime = lastAccessTime; - } - - @Override - public String toString() { - return "TrackerServer{" + - "sock=" + sock + - ", inetSockAddr=" + inetSockAddr + - ", lastAccessTime=" + lastAccessTime + - '}'; - } } diff --git a/src/main/java/org/csource/fastdfs/pool/Connection.java b/src/main/java/org/csource/fastdfs/pool/Connection.java new file mode 100644 index 0000000..cecbeae --- /dev/null +++ b/src/main/java/org/csource/fastdfs/pool/Connection.java @@ -0,0 +1,107 @@ +package org.csource.fastdfs.pool; + +import org.csource.fastdfs.ProtoCommon; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Socket; + +public class Connection { + + private Socket sock; + private InetSocketAddress inetSockAddr; + private Long lastAccessTime = System.currentTimeMillis(); + + public Connection(Socket sock, InetSocketAddress inetSockAddr) { + this.sock = sock; + this.inetSockAddr = inetSockAddr; + } + + /** + * get the server info + * + * @return the server info + */ + public InetSocketAddress getInetSocketAddress() { + return this.inetSockAddr; + } + + public OutputStream getOutputStream() throws IOException { + return this.sock.getOutputStream(); + } + + public InputStream getInputStream() throws IOException { + return this.sock.getInputStream(); + } + + public Long getLastAccessTime() { + return lastAccessTime; + } + + public void setLastAccessTime(Long lastAccessTime) { + this.lastAccessTime = lastAccessTime; + } + + /** + * close direct if not create from pool or not open pool + * + * @throws IOException + */ + public void close() throws IOException { + if (this.sock != null) { + try { + ProtoCommon.closeSocket(this.sock); + } finally { + this.sock = null; + } + } + } + + public boolean activeTest() throws IOException { + if (this.sock == null) { + return false; + } + return ProtoCommon.activeTest(this.sock); + } + + public boolean isConnected() { + boolean isConnected = false; + if (sock != null) { + if (sock.isConnected()) { + isConnected = true; + } + } + return isConnected; + } + public boolean isAvaliable() { + if (isConnected()) { + if (sock.getPort() == 0) { + return false; + } + if (sock.getInetAddress() == null) { + return false; + } + if (sock.getRemoteSocketAddress() == null) { + return false; + } + if (sock.isInputShutdown()) { + return false; + } + if (sock.isOutputShutdown()) { + return false; + } + return true; + } + return false; + } + + @Override + public String toString() { + return "TrackerServer{" + + "sock=" + sock + + ", inetSockAddr=" + inetSockAddr + + '}'; + } +} diff --git a/src/main/java/org/csource/fastdfs/pool/PoolConnectionFactory.java b/src/main/java/org/csource/fastdfs/pool/ConnectionFactory.java similarity index 58% rename from src/main/java/org/csource/fastdfs/pool/PoolConnectionFactory.java rename to src/main/java/org/csource/fastdfs/pool/ConnectionFactory.java index 545af98..8c64acc 100644 --- a/src/main/java/org/csource/fastdfs/pool/PoolConnectionFactory.java +++ b/src/main/java/org/csource/fastdfs/pool/ConnectionFactory.java @@ -5,9 +5,8 @@ import org.csource.fastdfs.ClientGlobal; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; - -public class PoolConnectionFactory { - public static ConnectionInfo create(String key) throws IOException { +public class ConnectionFactory { + public static Connection create(String key) throws IOException { if (key == null) { System.err.printf("ip:port entry conn't be null"); return null; @@ -24,7 +23,21 @@ public class PoolConnectionFactory { sock.setSoTimeout(ClientGlobal.g_network_timeout); InetSocketAddress inetSocketAddress = new InetSocketAddress(ip, port); sock.connect(inetSocketAddress, ClientGlobal.g_connect_timeout); - return new ConnectionInfo(sock, inetSocketAddress, System.currentTimeMillis(), false); + return new Connection(sock, inetSocketAddress); } + + /** + * create from InetSocketAddress + * @param socketAddress + * @return + * @throws IOException + */ + public static Connection create(InetSocketAddress socketAddress) throws IOException { + Socket sock = new Socket(); + sock.setReuseAddress(true); + sock.setSoTimeout(ClientGlobal.g_network_timeout); + sock.connect(socketAddress, ClientGlobal.g_connect_timeout); + return new Connection(sock, socketAddress); + } } diff --git a/src/main/java/org/csource/fastdfs/pool/ConnectionInfo.java b/src/main/java/org/csource/fastdfs/pool/ConnectionInfo.java deleted file mode 100644 index 9da1d76..0000000 --- a/src/main/java/org/csource/fastdfs/pool/ConnectionInfo.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.csource.fastdfs.pool; - -import java.net.InetSocketAddress; -import java.net.Socket; - -public class ConnectionInfo { - private Socket socket; - protected InetSocketAddress inetSockAddr; - private Long lastAccessTime; - private boolean needActiveCheck = false; - - public Socket getSocket() { - return socket; - } - - public void setSocket(Socket socket) { - this.socket = socket; - } - - public InetSocketAddress getInetSockAddr() { - return inetSockAddr; - } - - public void setInetSockAddr(InetSocketAddress inetSockAddr) { - this.inetSockAddr = inetSockAddr; - } - - public Long getLastAccessTime() { - return lastAccessTime; - } - - public void setLastAccessTime(Long lastAccessTime) { - this.lastAccessTime = lastAccessTime; - } - - public boolean isNeedActiveCheck() { - return needActiveCheck; - } - - public void setNeedActiveCheck(boolean needActiveCheck) { - this.needActiveCheck = needActiveCheck; - } - - public ConnectionInfo(Socket socket, InetSocketAddress inetSockAddr, Long lastAccessTime, boolean needActiveCheck) { - this.socket = socket; - this.inetSockAddr = inetSockAddr; - this.lastAccessTime = lastAccessTime; - this.needActiveCheck = needActiveCheck; - } - - @Override - public String toString() { - return "ConnectionInfo{" + - "socket=" + socket + - ", inetSockAddr=" + inetSockAddr + - ", lastAccessTime=" + lastAccessTime + - ", needActiveCheck=" + needActiveCheck + - '}'; - } -} diff --git a/src/main/java/org/csource/fastdfs/pool/ConnectionManager.java b/src/main/java/org/csource/fastdfs/pool/ConnectionManager.java index 68edb9b..fee3b16 100644 --- a/src/main/java/org/csource/fastdfs/pool/ConnectionManager.java +++ b/src/main/java/org/csource/fastdfs/pool/ConnectionManager.java @@ -1,9 +1,7 @@ package org.csource.fastdfs.pool; +import org.csource.common.MyException; import org.csource.fastdfs.ClientGlobal; -import org.csource.fastdfs.ProtoCommon; -import org.csource.fastdfs.TrackerServer; - import java.io.IOException; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; @@ -37,7 +35,7 @@ public class ConnectionManager { /** * free connections */ - private volatile ConcurrentLinkedQueue freeConnections = new ConcurrentLinkedQueue(); + private volatile ConcurrentLinkedQueue freeConnections = new ConcurrentLinkedQueue(); private ConnectionManager() { @@ -47,57 +45,46 @@ public class ConnectionManager { this.key = key; } - private synchronized ConnectionInfo newConnection() throws IOException { + private Connection newConnection() throws IOException { try { - ConnectionInfo connectionInfo = PoolConnectionFactory.create(this.key); - return connectionInfo; - + Connection connection = ConnectionFactory.create(this.key); + return connection; } catch (IOException e) { throw e; } } - public synchronized ConnectionInfo getConnection() throws IOException { + public Connection getConnection() throws MyException { lock.lock(); try { - ConnectionInfo connectionInfo = null; + Connection connection = null; while (true) { if (freeCount.get() > 0) { - connectionInfo = freeConnections.poll(); - if ((System.currentTimeMillis() - connectionInfo.getLastAccessTime()) > ClientGlobal.getG_connection_pool_max_idle_time()) { - closeConnection(connectionInfo); + freeCount.decrementAndGet(); + connection = freeConnections.poll(); + if (!connection.isAvaliable() || (System.currentTimeMillis() - connection.getLastAccessTime()) > ClientGlobal.getG_connection_pool_max_idle_time()) { + closeConnection(connection); continue; - } else { - freeCount.decrementAndGet(); } } else if (ClientGlobal.getG_connection_pool_max_count_per_entry() == 0 || totalCount.get() < ClientGlobal.getG_connection_pool_max_count_per_entry()) { - connectionInfo = newConnection(); - if (connectionInfo != null) { + connection = newConnection(); + if (connection != null) { totalCount.incrementAndGet(); } } else { try { - if (condition.await(ClientGlobal.getG_connection_pool_max_wait_time(), TimeUnit.MILLISECONDS)) { + if (condition.await(ClientGlobal.getG_connection_pool_max_wait_time_in_ms(), TimeUnit.MILLISECONDS)) { //wait single success continue; } + throw new MyException("get connection fail, wait_time greater than " + ClientGlobal.g_connection_pool_max_wait_time_in_ms + "ms"); } catch (InterruptedException e) { e.printStackTrace(); + throw new MyException("get connection fail, emsg > " + e.getMessage()); } } - //if need check active - if (connectionInfo.isNeedActiveCheck()) { - boolean activeYes = ProtoCommon.activeTest(connectionInfo.getSocket()); - if (activeYes) { - connectionInfo.setLastAccessTime(System.currentTimeMillis()); - } else { - //close if check fail - closeConnection(connectionInfo); - continue; - } - } - return connectionInfo; + return connection; } } catch (IOException e) { return null; @@ -106,33 +93,34 @@ public class ConnectionManager { } } - public void freeConnection(TrackerServer trackerServer) throws IOException { - if (trackerServer == null || !trackerServer.isConnected()) { + public void releaseConnection(Connection connection) throws IOException { + if (connection == null) { return; } - ConnectionInfo connectionInfo = new ConnectionInfo(trackerServer.getSocket(),trackerServer.getInetSocketAddress(),System.currentTimeMillis(),true); - if ((System.currentTimeMillis() - trackerServer.getLastAccessTime()) < ClientGlobal.getG_connection_pool_max_idle_time()) { + if ((System.currentTimeMillis() - connection.getLastAccessTime()) < ClientGlobal.g_connection_pool_max_idle_time) { try { lock.lock(); - freeConnections.add(connectionInfo); + freeConnections.add(connection); freeCount.incrementAndGet(); condition.signal(); } finally { lock.unlock(); } } else { - closeConnection(connectionInfo); + closeConnection(connection); } + } - public void closeConnection(ConnectionInfo connectionInfo) throws IOException { - if (connectionInfo.getSocket() != null) { - totalCount.decrementAndGet(); - try { - ProtoCommon.closeSocket(connectionInfo.getSocket()); - } finally { - connectionInfo.setSocket(null); + public void closeConnection(Connection connection) throws IOException { + try { + if (connection != null) { + totalCount.decrementAndGet(); + connection.close(); } + } catch (IOException e) { + System.err.println("close socket error , msg:" + e.getMessage()); + e.printStackTrace(); } } diff --git a/src/main/java/org/csource/fastdfs/pool/ConnectionPool.java b/src/main/java/org/csource/fastdfs/pool/ConnectionPool.java index c31465b..6179d6a 100644 --- a/src/main/java/org/csource/fastdfs/pool/ConnectionPool.java +++ b/src/main/java/org/csource/fastdfs/pool/ConnectionPool.java @@ -1,6 +1,6 @@ package org.csource.fastdfs.pool; -import org.csource.fastdfs.TrackerServer; +import org.csource.common.MyException; import java.io.IOException; import java.net.InetSocketAddress; @@ -13,54 +13,51 @@ public class ConnectionPool { */ private final static ConcurrentHashMap CP = new ConcurrentHashMap(); - public static synchronized ConnectionInfo getConnection(InetSocketAddress socketAddress) throws IOException { + public static Connection getConnection(InetSocketAddress socketAddress) throws MyException { if (socketAddress == null) { return null; } String key = getKey(socketAddress); - ConnectionManager connectionManager = CP.get(key); - if (connectionManager == null) { - connectionManager = new ConnectionManager(key); - CP.put(key, connectionManager); + ConnectionManager connectionManager; + synchronized (ConnectionPool.class) { + connectionManager = CP.get(key); + if (connectionManager == null) { + connectionManager = new ConnectionManager(key); + CP.put(key, connectionManager); + } } return connectionManager.getConnection(); } - /** - * release connection - */ - public static void closeConnection(TrackerServer trackerServer) throws IOException { - if (trackerServer == null || trackerServer.getInetSocketAddress() == null) { + public static void releaseConnection(Connection connection) throws IOException { + if (connection == null) { return; } - String key = getKey(trackerServer.getInetSocketAddress()); - if (key != null) { - ConnectionManager connectionManager = CP.get(key); - if (connectionManager != null) { - connectionManager.closeConnection(new ConnectionInfo(trackerServer.getSocket(), trackerServer.getInetSocketAddress(),trackerServer.getLastAccessTime(),true)); - } else { - trackerServer.closeDirect(); - } + String key = getKey(connection.getInetSocketAddress()); + ConnectionManager connectionManager = CP.get(key); + if (connectionManager != null) { + connectionManager.releaseConnection(connection); } else { - trackerServer.closeDirect(); + try { + connection.close(); + } catch (IOException e) { + System.err.println("close socket error, msg:" + e.getMessage()); + e.printStackTrace(); + } } + } - public static void freeConnection(TrackerServer trackerServer) throws IOException { - if (trackerServer == null || trackerServer.getInetSocketAddress() == null) { + public static void closeConnection(Connection connection) throws IOException { + if (connection == null) { return; } - String key = getKey(trackerServer.getInetSocketAddress()); - if (key != null) { - ConnectionManager connectionManager = CP.get(key); - if (connectionManager != null) { - connectionManager.freeConnection(trackerServer); - } else { - trackerServer.closeDirect(); - } - + String key = getKey(connection.getInetSocketAddress()); + ConnectionManager connectionManager = CP.get(key); + if (connectionManager != null) { + connectionManager.closeConnection(connection); } else { - trackerServer.closeDirect(); + connection.close(); } } @@ -70,6 +67,7 @@ public class ConnectionPool { } return String.format("%s:%s", socketAddress.getHostName(), socketAddress.getPort()); } + @Override public String toString() { if (!CP.isEmpty()) { diff --git a/src/main/resources/fastdfs-client.properties b/src/main/resources/fastdfs-client.properties index 40af15a..8722894 100644 --- a/src/main/resources/fastdfs-client.properties +++ b/src/main/resources/fastdfs-client.properties @@ -14,4 +14,4 @@ fastdfs.tracker_servers = 10.0.11.201:22122,10.0.11.202:22122,10.0.11.203:22122 fastdfs.connection_pool.enabled = false fastdfs.connection_pool.max_count_per_entry = 50 fastdfs.connection_pool.max_idle_time = 60 -fastdfs.connection_pool.max_wait_time = 5 \ No newline at end of file +fastdfs.connection_pool.max_wait_time_in_ms = 5000 \ No newline at end of file diff --git a/src/main/resources/fastdfs-client.properties.sample b/src/main/resources/fastdfs-client.properties.sample index 52fd46d..9a1f07e 100644 --- a/src/main/resources/fastdfs-client.properties.sample +++ b/src/main/resources/fastdfs-client.properties.sample @@ -18,4 +18,4 @@ fastdfs.connection_pool.enabled = false fastdfs.connection_pool.max_count_per_entry = 100 fastdfs.connection_pool.max_idle_time = 60 -fastdfs.connection_pool.max_wait_time = 5 \ No newline at end of file +fastdfs.connection_pool.max_wait_time_in_ms = 5000 \ No newline at end of file diff --git a/src/main/resources/fdfs_client.conf.sample b/src/main/resources/fdfs_client.conf.sample index 0ed36ba..00d6945 100644 --- a/src/main/resources/fdfs_client.conf.sample +++ b/src/main/resources/fdfs_client.conf.sample @@ -11,4 +11,4 @@ tracker_server = 10.0.11.244:22122 connection_pool.enabled = false connection_pool.max_count_per_entry = 100 connection_pool.max_idle_time = 60 -connection_pool.max_wait_time = 5 \ No newline at end of file +connection_pool.max_wait_time_in_ms = 5000 \ No newline at end of file diff --git a/src/test/java/org/csource/fastdfs/FdfsTest.java b/src/test/java/org/csource/fastdfs/FdfsTest.java index 2893114..6a23441 100644 --- a/src/test/java/org/csource/fastdfs/FdfsTest.java +++ b/src/test/java/org/csource/fastdfs/FdfsTest.java @@ -31,7 +31,7 @@ public class FdfsTest { LOGGER.info("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); LOGGER.info("charset=" + ClientGlobal.g_charset); TrackerClient tracker = new TrackerClient(); - trackerServer = tracker.getConnection(); + trackerServer = tracker.getTrackerServer(); StorageServer storageServer = null; storageClient = new StorageClient(trackerServer, storageServer); } diff --git a/src/test/java/org/csource/fastdfs/Monitor.java b/src/test/java/org/csource/fastdfs/Monitor.java index 30f86e7..f4265c3 100644 --- a/src/test/java/org/csource/fastdfs/Monitor.java +++ b/src/test/java/org/csource/fastdfs/Monitor.java @@ -8,8 +8,6 @@ package org.csource.fastdfs; -import org.csource.fastdfs.*; - import java.text.SimpleDateFormat; /** @@ -48,7 +46,7 @@ public class Monitor { System.out.println("delete storage errno: " + tracker.getErrorCode()); */ - TrackerServer trackerServer = tracker.getConnection(); + TrackerServer trackerServer = tracker.getTrackerServer(); if (trackerServer == null) { return; } @@ -157,8 +155,6 @@ public class Monitor { System.out.println("\t\tlast_synced_timestamp = " + df.format(storageStat.getLastSyncedTimestamp()) + getSyncedDelayString(storageStats, storageStat)); } } - - trackerServer.close(); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/src/test/java/org/csource/fastdfs/Test.java b/src/test/java/org/csource/fastdfs/Test.java index 612716e..109a615 100644 --- a/src/test/java/org/csource/fastdfs/Test.java +++ b/src/test/java/org/csource/fastdfs/Test.java @@ -9,7 +9,6 @@ package org.csource.fastdfs; import org.csource.common.NameValuePair; -import org.csource.fastdfs.*; /** * client test @@ -46,7 +45,7 @@ public class Test { System.out.println("charset=" + ClientGlobal.g_charset); TrackerClient tracker = new TrackerClient(); - TrackerServer trackerServer = tracker.getConnection(); + TrackerServer trackerServer = tracker.getTrackerServer(); StorageServer storageServer = null; StorageClient1 client = new StorageClient1(trackerServer, storageServer); @@ -60,8 +59,6 @@ public class Test { byte[] result = client.download_file1(fileId); System.out.println(i + ", download result is: " + result.length); } - - trackerServer.close(); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/src/test/java/org/csource/fastdfs/Test1.java b/src/test/java/org/csource/fastdfs/Test1.java index 5198afd..4e85cc8 100644 --- a/src/test/java/org/csource/fastdfs/Test1.java +++ b/src/test/java/org/csource/fastdfs/Test1.java @@ -1,7 +1,6 @@ package org.csource.fastdfs; import org.csource.common.NameValuePair; -import org.csource.fastdfs.*; import java.net.InetSocketAddress; @@ -39,9 +38,9 @@ public class Test1 { TrackerGroup tg = new TrackerGroup(new InetSocketAddress[]{new InetSocketAddress("47.95.221.159", 22122)}); TrackerClient tc = new TrackerClient(tg); - TrackerServer ts = tc.getConnection(); + TrackerServer ts = tc.getTrackerServer(); if (ts == null) { - System.out.println("getConnection return null"); + System.out.println("getTrackerServer return null"); return; } diff --git a/src/test/java/org/csource/fastdfs/TestAppender.java b/src/test/java/org/csource/fastdfs/TestAppender.java index ab01926..a573685 100644 --- a/src/test/java/org/csource/fastdfs/TestAppender.java +++ b/src/test/java/org/csource/fastdfs/TestAppender.java @@ -9,7 +9,6 @@ package org.csource.fastdfs; import org.csource.common.NameValuePair; -import org.csource.fastdfs.*; import java.io.File; import java.net.InetSocketAddress; @@ -53,7 +52,7 @@ public class TestAppender { String remote_filename; ServerInfo[] servers; TrackerClient tracker = new TrackerClient(); - TrackerServer trackerServer = tracker.getConnection(); + TrackerServer trackerServer = tracker.getTrackerServer(); StorageServer storageServer = null; @@ -298,14 +297,10 @@ public class TestAppender { return; } /* for test only */ - System.out.println("active test to storage server: " + ProtoCommon.activeTest(storageServer.getSocket())); - - storageServer.close(); + System.out.println("active test to storage server: " + storageServer.getConnection().activeTest()); /* for test only */ - System.out.println("active test to tracker server: " + ProtoCommon.activeTest(trackerServer.getSocket())); - - trackerServer.close(); + System.out.println("active test to tracker server: " + trackerServer.getConnection().activeTest()); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/src/test/java/org/csource/fastdfs/TestAppender1.java b/src/test/java/org/csource/fastdfs/TestAppender1.java index 0e1fbcd..0d7bd0b 100644 --- a/src/test/java/org/csource/fastdfs/TestAppender1.java +++ b/src/test/java/org/csource/fastdfs/TestAppender1.java @@ -9,7 +9,6 @@ package org.csource.fastdfs; import org.csource.common.NameValuePair; -import org.csource.fastdfs.*; import java.io.File; import java.net.InetSocketAddress; @@ -21,39 +20,39 @@ import java.net.InetSocketAddress; * @version Version 1.20 */ public class TestAppender1 { - private TestAppender1() { - } - - /** - * entry point - * - * @param args comand arguments - *
  • args[0]: config filename
- *
  • args[1]: local filename to upload
- */ - public static void main(String args[]) { - if (args.length < 2) { - System.out.println("Error: Must have 2 parameters, one is config filename, " - + "the other is the local filename to upload"); - return; + private TestAppender1() { } - System.out.println("java.version=" + System.getProperty("java.version")); + /** + * entry point + * + * @param args comand arguments + *
  • args[0]: config filename
+ *
  • args[1]: local filename to upload
+ */ + public static void main(String args[]) { + if (args.length < 2) { + System.out.println("Error: Must have 2 parameters, one is config filename, " + + "the other is the local filename to upload"); + return; + } - String conf_filename = args[0]; - String local_filename = args[1]; + System.out.println("java.version=" + System.getProperty("java.version")); - try { - ClientGlobal.init(conf_filename); - System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); - System.out.println("charset=" + ClientGlobal.g_charset); + String conf_filename = args[0]; + String local_filename = args[1]; - long startTime; - ServerInfo[] servers; - TrackerClient tracker = new TrackerClient(); - TrackerServer trackerServer = tracker.getConnection(); + try { + ClientGlobal.init(conf_filename); + System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); + System.out.println("charset=" + ClientGlobal.g_charset); - StorageServer storageServer = null; + long startTime; + ServerInfo[] servers; + TrackerClient tracker = new TrackerClient(); + TrackerServer trackerServer = tracker.getTrackerServer(); + + StorageServer storageServer = null; /* storageServer = tracker.getStoreStorage(trackerServer); @@ -64,229 +63,226 @@ public class TestAppender1 { } */ - StorageClient1 client = new StorageClient1(trackerServer, storageServer); - byte[] file_buff; - NameValuePair[] meta_list; - String group_name; - String appender_file_id; - String file_ext_name; - int errno; + StorageClient1 client = new StorageClient1(trackerServer, storageServer); + byte[] file_buff; + NameValuePair[] meta_list; + String group_name; + String appender_file_id; + String file_ext_name; + int errno; - meta_list = new NameValuePair[4]; - meta_list[0] = new NameValuePair("width", "800"); - meta_list[1] = new NameValuePair("heigth", "600"); - meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); - meta_list[3] = new NameValuePair("author", "Mike"); + meta_list = new NameValuePair[4]; + meta_list[0] = new NameValuePair("width", "800"); + meta_list[1] = new NameValuePair("heigth", "600"); + meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); + meta_list[3] = new NameValuePair("author", "Mike"); - file_buff = "this is a test".getBytes(ClientGlobal.g_charset); - System.out.println("file length: " + file_buff.length); + file_buff = "this is a test".getBytes(ClientGlobal.g_charset); + System.out.println("file length: " + file_buff.length); - group_name = null; - StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); - if (storageServers == null) { - System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); - } else { - System.err.println("store storage servers count: " + storageServers.length); - for (int k = 0; k < storageServers.length; k++) { - System.err.println((k + 1) + ". " + storageServers[k].getInetSocketAddress().getAddress().getHostAddress() + ":" + storageServers[k].getInetSocketAddress().getPort()); - } - System.err.println(""); - } + group_name = null; + StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); + if (storageServers == null) { + System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); + } else { + System.err.println("store storage servers count: " + storageServers.length); + for (int k = 0; k < storageServers.length; k++) { + System.err.println((k + 1) + ". " + storageServers[k].getInetSocketAddress().getAddress().getHostAddress() + ":" + storageServers[k].getInetSocketAddress().getPort()); + } + System.err.println(""); + } - startTime = System.currentTimeMillis(); - appender_file_id = client.upload_appender_file1(file_buff, "txt", meta_list); - System.out.println("upload_appender_file1 time used: " + (System.currentTimeMillis() - startTime) + " ms"); + startTime = System.currentTimeMillis(); + appender_file_id = client.upload_appender_file1(file_buff, "txt", meta_list); + System.out.println("upload_appender_file1 time used: " + (System.currentTimeMillis() - startTime) + " ms"); /* group_name = ""; appender_file_id = client.upload_appender_file1(group_name, file_buff, "txt", meta_list); */ - if (appender_file_id == null) { - System.err.println("upload file fail, error code: " + client.getErrorCode()); - return; - } else { - System.err.println(client.get_file_info1(appender_file_id)); + if (appender_file_id == null) { + System.err.println("upload file fail, error code: " + client.getErrorCode()); + return; + } else { + System.err.println(client.get_file_info1(appender_file_id)); - servers = tracker.getFetchStorages1(trackerServer, appender_file_id); - if (servers == null) { - System.err.println("get storage servers fail, error code: " + tracker.getErrorCode()); - } else { - System.err.println("storage servers count: " + servers.length); - for (int k = 0; k < servers.length; k++) { - System.err.println((k + 1) + ". " + servers[k].getIpAddr() + ":" + servers[k].getPort()); - } - System.err.println(""); + servers = tracker.getFetchStorages1(trackerServer, appender_file_id); + if (servers == null) { + System.err.println("get storage servers fail, error code: " + tracker.getErrorCode()); + } else { + System.err.println("storage servers count: " + servers.length); + for (int k = 0; k < servers.length; k++) { + System.err.println((k + 1) + ". " + servers[k].getIpAddr() + ":" + servers[k].getPort()); + } + System.err.println(""); + } + + meta_list = new NameValuePair[4]; + meta_list[0] = new NameValuePair("width", "1024"); + meta_list[1] = new NameValuePair("heigth", "768"); + meta_list[2] = new NameValuePair("bgcolor", "#000000"); + meta_list[3] = new NameValuePair("title", "Untitle"); + + startTime = System.currentTimeMillis(); + errno = client.set_metadata1(appender_file_id, meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE); + System.out.println("set_metadata time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println("set_metadata success"); + } else { + System.err.println("set_metadata fail, error no: " + errno); + } + + meta_list = client.get_metadata1(appender_file_id); + if (meta_list != null) { + for (int i = 0; i < meta_list.length; i++) { + System.out.println(meta_list[i].getName() + " " + meta_list[i].getValue()); + } + } + + startTime = System.currentTimeMillis(); + file_buff = client.download_file1(appender_file_id); + System.out.println("download_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + + if (file_buff != null) { + System.out.println("file length:" + file_buff.length); + System.out.println((new String(file_buff))); + } + + file_buff = "this is a slave buff".getBytes(ClientGlobal.g_charset); + file_ext_name = "txt"; + startTime = System.currentTimeMillis(); + errno = client.append_file1(appender_file_id, file_buff); + System.out.println("append_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println(client.get_file_info1(appender_file_id)); + } else { + System.err.println("append file fail, error no: " + errno); + } + + startTime = System.currentTimeMillis(); + String new_file_id = client.regenerate_appender_filename1(appender_file_id); + System.out.println("regenerate_appender_filename time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + appender_file_id = new_file_id; + System.err.println(client.get_file_info1(appender_file_id)); + } else { + System.err.println("regenerate_appender_filename fail, error no: " + errno); + } + + startTime = System.currentTimeMillis(); + errno = client.delete_file1(appender_file_id); + System.out.println("delete_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println("Delete file success"); + } else { + System.err.println("Delete file fail, error no: " + errno); + } + } + + appender_file_id = client.upload_appender_file1(local_filename, null, meta_list); + if (appender_file_id != null) { + int ts; + String token; + String file_url; + InetSocketAddress inetSockAddr; + + inetSockAddr = trackerServer.getInetSocketAddress(); + file_url = "http://" + inetSockAddr.getAddress().getHostAddress(); + if (ClientGlobal.g_tracker_http_port != 80) { + file_url += ":" + ClientGlobal.g_tracker_http_port; + } + file_url += "/" + appender_file_id; + if (ClientGlobal.g_anti_steal_token) { + ts = (int) (System.currentTimeMillis() / 1000); + token = ProtoCommon.getToken(appender_file_id, ts, ClientGlobal.g_secret_key); + file_url += "?token=" + token + "&ts=" + ts; + } + + System.err.println(client.get_file_info1(appender_file_id)); + System.err.println("file url: " + file_url); + + errno = client.download_file1(appender_file_id, 0, 0, "c:\\" + appender_file_id.replaceAll("/", "_")); + if (errno == 0) { + System.err.println("Download file success"); + } else { + System.err.println("Download file fail, error no: " + errno); + } + + errno = client.download_file1(appender_file_id, 0, 0, new DownloadFileWriter("c:\\" + appender_file_id.replaceAll("/", "-"))); + if (errno == 0) { + System.err.println("Download file success"); + } else { + System.err.println("Download file fail, error no: " + errno); + } + + file_ext_name = null; + startTime = System.currentTimeMillis(); + errno = client.append_file1(appender_file_id, local_filename); + System.out.println("append_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println(client.get_file_info1(appender_file_id)); + } else { + System.err.println("append file fail, error no: " + errno); + } + } + + File f; + f = new File(local_filename); + int nPos = local_filename.lastIndexOf('.'); + if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + file_ext_name = local_filename.substring(nPos + 1); + } else { + file_ext_name = null; + } + + appender_file_id = client.upload_appender_file1(null, f.length(), + new UploadLocalFileSender(local_filename), file_ext_name, meta_list); + if (appender_file_id != null) { + System.out.println(client.get_file_info1(appender_file_id)); + + startTime = System.currentTimeMillis(); + errno = client.append_file1(appender_file_id, f.length(), new UploadLocalFileSender(local_filename)); + System.out.println("append_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println(client.get_file_info1(appender_file_id)); + } else { + System.err.println("append file fail, error no: " + errno); + } + + startTime = System.currentTimeMillis(); + errno = client.modify_file1(appender_file_id, 0, f.length(), new UploadLocalFileSender(local_filename)); + System.out.println("modify_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println(client.get_file_info1(appender_file_id)); + } else { + System.err.println("modify file fail, error no: " + errno); + } + + startTime = System.currentTimeMillis(); + errno = client.truncate_file1(appender_file_id, 0); + System.out.println("truncate_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println(client.get_file_info1(appender_file_id)); + } else { + System.err.println("truncate file fail, error no: " + errno); + } + } else { + System.err.println("Upload file fail, error no: " + errno); + } + + storageServer = tracker.getFetchStorage1(trackerServer, appender_file_id); + if (storageServer == null) { + System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); + return; + } + + /* for test only */ + System.out.println("active test to storage server: " + storageServer.getConnection().activeTest()); + + /* for test only */ + System.out.println("active test to tracker server: " + trackerServer.getConnection().activeTest()); + } catch (Exception ex) { + ex.printStackTrace(); } - - meta_list = new NameValuePair[4]; - meta_list[0] = new NameValuePair("width", "1024"); - meta_list[1] = new NameValuePair("heigth", "768"); - meta_list[2] = new NameValuePair("bgcolor", "#000000"); - meta_list[3] = new NameValuePair("title", "Untitle"); - - startTime = System.currentTimeMillis(); - errno = client.set_metadata1(appender_file_id, meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE); - System.out.println("set_metadata time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println("set_metadata success"); - } else { - System.err.println("set_metadata fail, error no: " + errno); - } - - meta_list = client.get_metadata1(appender_file_id); - if (meta_list != null) { - for (int i = 0; i < meta_list.length; i++) { - System.out.println(meta_list[i].getName() + " " + meta_list[i].getValue()); - } - } - - startTime = System.currentTimeMillis(); - file_buff = client.download_file1(appender_file_id); - System.out.println("download_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - - if (file_buff != null) { - System.out.println("file length:" + file_buff.length); - System.out.println((new String(file_buff))); - } - - file_buff = "this is a slave buff".getBytes(ClientGlobal.g_charset); - file_ext_name = "txt"; - startTime = System.currentTimeMillis(); - errno = client.append_file1(appender_file_id, file_buff); - System.out.println("append_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println(client.get_file_info1(appender_file_id)); - } else { - System.err.println("append file fail, error no: " + errno); - } - - startTime = System.currentTimeMillis(); - String new_file_id = client.regenerate_appender_filename1(appender_file_id); - System.out.println("regenerate_appender_filename time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - appender_file_id = new_file_id; - System.err.println(client.get_file_info1(appender_file_id)); - } else { - System.err.println("regenerate_appender_filename fail, error no: " + errno); - } - - startTime = System.currentTimeMillis(); - errno = client.delete_file1(appender_file_id); - System.out.println("delete_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println("Delete file success"); - } else { - System.err.println("Delete file fail, error no: " + errno); - } - } - - appender_file_id = client.upload_appender_file1(local_filename, null, meta_list); - if (appender_file_id != null) { - int ts; - String token; - String file_url; - InetSocketAddress inetSockAddr; - - inetSockAddr = trackerServer.getInetSocketAddress(); - file_url = "http://" + inetSockAddr.getAddress().getHostAddress(); - if (ClientGlobal.g_tracker_http_port != 80) { - file_url += ":" + ClientGlobal.g_tracker_http_port; - } - file_url += "/" + appender_file_id; - if (ClientGlobal.g_anti_steal_token) { - ts = (int) (System.currentTimeMillis() / 1000); - token = ProtoCommon.getToken(appender_file_id, ts, ClientGlobal.g_secret_key); - file_url += "?token=" + token + "&ts=" + ts; - } - - System.err.println(client.get_file_info1(appender_file_id)); - System.err.println("file url: " + file_url); - - errno = client.download_file1(appender_file_id, 0, 0, "c:\\" + appender_file_id.replaceAll("/", "_")); - if (errno == 0) { - System.err.println("Download file success"); - } else { - System.err.println("Download file fail, error no: " + errno); - } - - errno = client.download_file1(appender_file_id, 0, 0, new DownloadFileWriter("c:\\" + appender_file_id.replaceAll("/", "-"))); - if (errno == 0) { - System.err.println("Download file success"); - } else { - System.err.println("Download file fail, error no: " + errno); - } - - file_ext_name = null; - startTime = System.currentTimeMillis(); - errno = client.append_file1(appender_file_id, local_filename); - System.out.println("append_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println(client.get_file_info1(appender_file_id)); - } else { - System.err.println("append file fail, error no: " + errno); - } - } - - File f; - f = new File(local_filename); - int nPos = local_filename.lastIndexOf('.'); - if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { - file_ext_name = local_filename.substring(nPos + 1); - } else { - file_ext_name = null; - } - - appender_file_id = client.upload_appender_file1(null, f.length(), - new UploadLocalFileSender(local_filename), file_ext_name, meta_list); - if (appender_file_id != null) { - System.out.println(client.get_file_info1(appender_file_id)); - - startTime = System.currentTimeMillis(); - errno = client.append_file1(appender_file_id, f.length(), new UploadLocalFileSender(local_filename)); - System.out.println("append_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println(client.get_file_info1(appender_file_id)); - } else { - System.err.println("append file fail, error no: " + errno); - } - - startTime = System.currentTimeMillis(); - errno = client.modify_file1(appender_file_id, 0, f.length(), new UploadLocalFileSender(local_filename)); - System.out.println("modify_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println(client.get_file_info1(appender_file_id)); - } else { - System.err.println("modify file fail, error no: " + errno); - } - - startTime = System.currentTimeMillis(); - errno = client.truncate_file1(appender_file_id, 0); - System.out.println("truncate_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println(client.get_file_info1(appender_file_id)); - } else { - System.err.println("truncate file fail, error no: " + errno); - } - } else { - System.err.println("Upload file fail, error no: " + errno); - } - - storageServer = tracker.getFetchStorage1(trackerServer, appender_file_id); - if (storageServer == null) { - System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); - return; - } - /* for test only */ - System.out.println("active test to storage server: " + ProtoCommon.activeTest(storageServer.getSocket())); - - storageServer.close(); - - /* for test only */ - System.out.println("active test to tracker server: " + ProtoCommon.activeTest(trackerServer.getSocket())); - - trackerServer.close(); - } catch (Exception ex) { - ex.printStackTrace(); } - } } diff --git a/src/test/java/org/csource/fastdfs/TestClient.java b/src/test/java/org/csource/fastdfs/TestClient.java index b9106f7..d8caba9 100644 --- a/src/test/java/org/csource/fastdfs/TestClient.java +++ b/src/test/java/org/csource/fastdfs/TestClient.java @@ -9,7 +9,6 @@ package org.csource.fastdfs; import org.csource.common.NameValuePair; -import org.csource.fastdfs.*; import java.io.File; import java.net.InetSocketAddress; @@ -21,41 +20,41 @@ import java.net.InetSocketAddress; * @version Version 1.18 */ public class TestClient { - private TestClient() { - } - - /** - * entry point - * - * @param args comand arguments - *
  • args[0]: config filename
- *
  • args[1]: local filename to upload
- */ - public static void main(String args[]) { - if (args.length < 2) { - System.out.println("Error: Must have 2 parameters, one is config filename, " - + "the other is the local filename to upload"); - return; + private TestClient() { } - System.out.println("java.version=" + System.getProperty("java.version")); + /** + * entry point + * + * @param args comand arguments + *
  • args[0]: config filename
+ *
  • args[1]: local filename to upload
+ */ + public static void main(String args[]) { + if (args.length < 2) { + System.out.println("Error: Must have 2 parameters, one is config filename, " + + "the other is the local filename to upload"); + return; + } - String conf_filename = args[0]; - String local_filename = args[1]; + System.out.println("java.version=" + System.getProperty("java.version")); - try { - ClientGlobal.init(conf_filename); - System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); - System.out.println("charset=" + ClientGlobal.g_charset); + String conf_filename = args[0]; + String local_filename = args[1]; - long startTime; - String group_name; - String remote_filename; - ServerInfo[] servers; - TrackerClient tracker = new TrackerClient(); - TrackerServer trackerServer = tracker.getConnection(); + try { + ClientGlobal.init(conf_filename); + System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); + System.out.println("charset=" + ClientGlobal.g_charset); - StorageServer storageServer = null; + long startTime; + String group_name; + String remote_filename; + ServerInfo[] servers; + TrackerClient tracker = new TrackerClient(); + TrackerServer trackerServer = tracker.getTrackerServer(); + + StorageServer storageServer = null; /* storageServer = tracker.getStoreStorage(trackerServer); @@ -66,239 +65,236 @@ public class TestClient { } */ - StorageClient client = new StorageClient(trackerServer, storageServer); - byte[] file_buff; - NameValuePair[] meta_list; - String[] results; - String master_filename; - String prefix_name; - String file_ext_name; - String generated_slave_filename; - int errno; + StorageClient client = new StorageClient(trackerServer, storageServer); + byte[] file_buff; + NameValuePair[] meta_list; + String[] results; + String master_filename; + String prefix_name; + String file_ext_name; + String generated_slave_filename; + int errno; - meta_list = new NameValuePair[4]; - meta_list[0] = new NameValuePair("width", "800"); - meta_list[1] = new NameValuePair("heigth", "600"); - meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); - meta_list[3] = new NameValuePair("author", "Mike"); + meta_list = new NameValuePair[4]; + meta_list[0] = new NameValuePair("width", "800"); + meta_list[1] = new NameValuePair("heigth", "600"); + meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); + meta_list[3] = new NameValuePair("author", "Mike"); - file_buff = "this is a test".getBytes(ClientGlobal.g_charset); - System.out.println("file length: " + file_buff.length); + file_buff = "this is a test".getBytes(ClientGlobal.g_charset); + System.out.println("file length: " + file_buff.length); - group_name = null; - StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); - if (storageServers == null) { - System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); - } else { - System.err.println("store storage servers count: " + storageServers.length); - for (int k = 0; k < storageServers.length; k++) { - System.err.println((k + 1) + ". " + storageServers[k].getInetSocketAddress().getAddress().getHostAddress() + ":" + storageServers[k].getInetSocketAddress().getPort()); - } - System.err.println(""); - } + group_name = null; + StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); + if (storageServers == null) { + System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); + } else { + System.err.println("store storage servers count: " + storageServers.length); + for (int k = 0; k < storageServers.length; k++) { + System.err.println((k + 1) + ". " + storageServers[k].getInetSocketAddress().getAddress().getHostAddress() + ":" + storageServers[k].getInetSocketAddress().getPort()); + } + System.err.println(""); + } - startTime = System.currentTimeMillis(); - results = client.upload_file(file_buff, "txt", meta_list); - System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + startTime = System.currentTimeMillis(); + results = client.upload_file(file_buff, "txt", meta_list); + System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); /* group_name = ""; results = client.upload_file(group_name, file_buff, "txt", meta_list); */ - if (results == null) { - System.err.println("upload file fail, error code: " + client.getErrorCode()); - return; - } else { - group_name = results[0]; - remote_filename = results[1]; - System.err.println("group_name: " + group_name + ", remote_filename: " + remote_filename); - System.err.println(client.get_file_info(group_name, remote_filename)); + if (results == null) { + System.err.println("upload file fail, error code: " + client.getErrorCode()); + return; + } else { + group_name = results[0]; + remote_filename = results[1]; + System.err.println("group_name: " + group_name + ", remote_filename: " + remote_filename); + System.err.println(client.get_file_info(group_name, remote_filename)); - servers = tracker.getFetchStorages(trackerServer, group_name, remote_filename); - if (servers == null) { - System.err.println("get storage servers fail, error code: " + tracker.getErrorCode()); - } else { - System.err.println("storage servers count: " + servers.length); - for (int k = 0; k < servers.length; k++) { - System.err.println((k + 1) + ". " + servers[k].getIpAddr() + ":" + servers[k].getPort()); - } - System.err.println(""); + servers = tracker.getFetchStorages(trackerServer, group_name, remote_filename); + if (servers == null) { + System.err.println("get storage servers fail, error code: " + tracker.getErrorCode()); + } else { + System.err.println("storage servers count: " + servers.length); + for (int k = 0; k < servers.length; k++) { + System.err.println((k + 1) + ". " + servers[k].getIpAddr() + ":" + servers[k].getPort()); + } + System.err.println(""); + } + + meta_list = new NameValuePair[4]; + meta_list[0] = new NameValuePair("width", "1024"); + meta_list[1] = new NameValuePair("heigth", "768"); + meta_list[2] = new NameValuePair("bgcolor", "#000000"); + meta_list[3] = new NameValuePair("title", "Untitle"); + + startTime = System.currentTimeMillis(); + errno = client.set_metadata(group_name, remote_filename, meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE); + System.out.println("set_metadata time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println("set_metadata success"); + } else { + System.err.println("set_metadata fail, error no: " + errno); + } + + meta_list = client.get_metadata(group_name, remote_filename); + if (meta_list != null) { + for (int i = 0; i < meta_list.length; i++) { + System.out.println(meta_list[i].getName() + " " + meta_list[i].getValue()); + } + } + + //Thread.sleep(30000); + + startTime = System.currentTimeMillis(); + file_buff = client.download_file(group_name, remote_filename); + System.out.println("download_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + + if (file_buff != null) { + System.out.println("file length:" + file_buff.length); + System.out.println((new String(file_buff))); + } + + file_buff = "this is a slave buff".getBytes(ClientGlobal.g_charset); + master_filename = remote_filename; + prefix_name = "-part1"; + file_ext_name = "txt"; + startTime = System.currentTimeMillis(); + results = client.upload_file(group_name, master_filename, prefix_name, file_buff, file_ext_name, meta_list); + System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (results != null) { + System.err.println("slave file group_name: " + results[0] + ", remote_filename: " + results[1]); + + generated_slave_filename = ProtoCommon.genSlaveFilename(master_filename, prefix_name, file_ext_name); + if (!generated_slave_filename.equals(results[1])) { + System.err.println("generated slave file: " + generated_slave_filename + "\n != returned slave file: " + results[1]); + } + + System.err.println(client.get_file_info(results[0], results[1])); + } + + startTime = System.currentTimeMillis(); + errno = client.delete_file(group_name, remote_filename); + System.out.println("delete_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (errno == 0) { + System.err.println("Delete file success"); + } else { + System.err.println("Delete file fail, error no: " + errno); + } + } + + results = client.upload_file(local_filename, null, meta_list); + if (results != null) { + String file_id; + int ts; + String token; + String file_url; + InetSocketAddress inetSockAddr; + + group_name = results[0]; + remote_filename = results[1]; + file_id = group_name + StorageClient1.SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + remote_filename; + + inetSockAddr = trackerServer.getInetSocketAddress(); + file_url = "http://" + inetSockAddr.getAddress().getHostAddress(); + if (ClientGlobal.g_tracker_http_port != 80) { + file_url += ":" + ClientGlobal.g_tracker_http_port; + } + file_url += "/" + file_id; + if (ClientGlobal.g_anti_steal_token) { + ts = (int) (System.currentTimeMillis() / 1000); + token = ProtoCommon.getToken(file_id, ts, ClientGlobal.g_secret_key); + file_url += "?token=" + token + "&ts=" + ts; + } + + System.err.println("group_name: " + group_name + ", remote_filename: " + remote_filename); + System.err.println(client.get_file_info(group_name, remote_filename)); + System.err.println("file url: " + file_url); + + errno = client.download_file(group_name, remote_filename, 0, 0, "c:\\" + remote_filename.replaceAll("/", "_")); + if (errno == 0) { + System.err.println("Download file success"); + } else { + System.err.println("Download file fail, error no: " + errno); + } + + errno = client.download_file(group_name, remote_filename, 0, 0, new DownloadFileWriter("c:\\" + remote_filename.replaceAll("/", "-"))); + if (errno == 0) { + System.err.println("Download file success"); + } else { + System.err.println("Download file fail, error no: " + errno); + } + + master_filename = remote_filename; + prefix_name = "-part2"; + file_ext_name = null; + startTime = System.currentTimeMillis(); + results = client.upload_file(group_name, master_filename, prefix_name, local_filename, null, meta_list); + System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (results != null) { + System.err.println("slave file group_name: " + results[0] + ", remote_filename: " + results[1]); + + generated_slave_filename = ProtoCommon.genSlaveFilename(master_filename, prefix_name, file_ext_name); + if (!generated_slave_filename.equals(results[1])) { + System.err.println("generated slave file: " + generated_slave_filename + "\n != returned slave file: " + results[1]); + } + + System.err.println(client.get_file_info(results[0], results[1])); + } + } + + File f; + f = new File(local_filename); + int nPos = local_filename.lastIndexOf('.'); + if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + file_ext_name = local_filename.substring(nPos + 1); + } else { + file_ext_name = null; + } + + results = client.upload_file(null, f.length(), + new UploadLocalFileSender(local_filename), file_ext_name, meta_list); + if (results != null) { + group_name = results[0]; + remote_filename = results[1]; + + System.out.println("group name: " + group_name + ", remote filename: " + remote_filename); + System.out.println(client.get_file_info(group_name, remote_filename)); + + master_filename = remote_filename; + prefix_name = "-part3"; + startTime = System.currentTimeMillis(); + results = client.upload_file(group_name, master_filename, prefix_name, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); + System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); + if (results != null) { + System.err.println("slave file group_name: " + results[0] + ", remote_filename: " + results[1]); + + generated_slave_filename = ProtoCommon.genSlaveFilename(master_filename, prefix_name, file_ext_name); + if (!generated_slave_filename.equals(results[1])) { + System.err.println("generated slave file: " + generated_slave_filename + "\n != returned slave file: " + results[1]); + } + + System.err.println(client.get_file_info(results[0], results[1])); + } + } else { + System.err.println("Upload file fail, error no: " + errno); + } + + storageServer = tracker.getFetchStorage(trackerServer, group_name, remote_filename); + if (storageServer == null) { + System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); + return; + } + + /* for test only */ + System.out.println("active test to storage server: " + storageServer.getConnection().activeTest()); + + /* for test only */ + System.out.println("active test to tracker server: " + trackerServer.getConnection().activeTest()); + } catch (Exception ex) { + ex.printStackTrace(); } - - meta_list = new NameValuePair[4]; - meta_list[0] = new NameValuePair("width", "1024"); - meta_list[1] = new NameValuePair("heigth", "768"); - meta_list[2] = new NameValuePair("bgcolor", "#000000"); - meta_list[3] = new NameValuePair("title", "Untitle"); - - startTime = System.currentTimeMillis(); - errno = client.set_metadata(group_name, remote_filename, meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE); - System.out.println("set_metadata time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println("set_metadata success"); - } else { - System.err.println("set_metadata fail, error no: " + errno); - } - - meta_list = client.get_metadata(group_name, remote_filename); - if (meta_list != null) { - for (int i = 0; i < meta_list.length; i++) { - System.out.println(meta_list[i].getName() + " " + meta_list[i].getValue()); - } - } - - //Thread.sleep(30000); - - startTime = System.currentTimeMillis(); - file_buff = client.download_file(group_name, remote_filename); - System.out.println("download_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - - if (file_buff != null) { - System.out.println("file length:" + file_buff.length); - System.out.println((new String(file_buff))); - } - - file_buff = "this is a slave buff".getBytes(ClientGlobal.g_charset); - master_filename = remote_filename; - prefix_name = "-part1"; - file_ext_name = "txt"; - startTime = System.currentTimeMillis(); - results = client.upload_file(group_name, master_filename, prefix_name, file_buff, file_ext_name, meta_list); - System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (results != null) { - System.err.println("slave file group_name: " + results[0] + ", remote_filename: " + results[1]); - - generated_slave_filename = ProtoCommon.genSlaveFilename(master_filename, prefix_name, file_ext_name); - if (!generated_slave_filename.equals(results[1])) { - System.err.println("generated slave file: " + generated_slave_filename + "\n != returned slave file: " + results[1]); - } - - System.err.println(client.get_file_info(results[0], results[1])); - } - - startTime = System.currentTimeMillis(); - errno = client.delete_file(group_name, remote_filename); - System.out.println("delete_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (errno == 0) { - System.err.println("Delete file success"); - } else { - System.err.println("Delete file fail, error no: " + errno); - } - } - - results = client.upload_file(local_filename, null, meta_list); - if (results != null) { - String file_id; - int ts; - String token; - String file_url; - InetSocketAddress inetSockAddr; - - group_name = results[0]; - remote_filename = results[1]; - file_id = group_name + StorageClient1.SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + remote_filename; - - inetSockAddr = trackerServer.getInetSocketAddress(); - file_url = "http://" + inetSockAddr.getAddress().getHostAddress(); - if (ClientGlobal.g_tracker_http_port != 80) { - file_url += ":" + ClientGlobal.g_tracker_http_port; - } - file_url += "/" + file_id; - if (ClientGlobal.g_anti_steal_token) { - ts = (int) (System.currentTimeMillis() / 1000); - token = ProtoCommon.getToken(file_id, ts, ClientGlobal.g_secret_key); - file_url += "?token=" + token + "&ts=" + ts; - } - - System.err.println("group_name: " + group_name + ", remote_filename: " + remote_filename); - System.err.println(client.get_file_info(group_name, remote_filename)); - System.err.println("file url: " + file_url); - - errno = client.download_file(group_name, remote_filename, 0, 0, "c:\\" + remote_filename.replaceAll("/", "_")); - if (errno == 0) { - System.err.println("Download file success"); - } else { - System.err.println("Download file fail, error no: " + errno); - } - - errno = client.download_file(group_name, remote_filename, 0, 0, new DownloadFileWriter("c:\\" + remote_filename.replaceAll("/", "-"))); - if (errno == 0) { - System.err.println("Download file success"); - } else { - System.err.println("Download file fail, error no: " + errno); - } - - master_filename = remote_filename; - prefix_name = "-part2"; - file_ext_name = null; - startTime = System.currentTimeMillis(); - results = client.upload_file(group_name, master_filename, prefix_name, local_filename, null, meta_list); - System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (results != null) { - System.err.println("slave file group_name: " + results[0] + ", remote_filename: " + results[1]); - - generated_slave_filename = ProtoCommon.genSlaveFilename(master_filename, prefix_name, file_ext_name); - if (!generated_slave_filename.equals(results[1])) { - System.err.println("generated slave file: " + generated_slave_filename + "\n != returned slave file: " + results[1]); - } - - System.err.println(client.get_file_info(results[0], results[1])); - } - } - - File f; - f = new File(local_filename); - int nPos = local_filename.lastIndexOf('.'); - if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { - file_ext_name = local_filename.substring(nPos + 1); - } else { - file_ext_name = null; - } - - results = client.upload_file(null, f.length(), - new UploadLocalFileSender(local_filename), file_ext_name, meta_list); - if (results != null) { - group_name = results[0]; - remote_filename = results[1]; - - System.out.println("group name: " + group_name + ", remote filename: " + remote_filename); - System.out.println(client.get_file_info(group_name, remote_filename)); - - master_filename = remote_filename; - prefix_name = "-part3"; - startTime = System.currentTimeMillis(); - results = client.upload_file(group_name, master_filename, prefix_name, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); - System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); - if (results != null) { - System.err.println("slave file group_name: " + results[0] + ", remote_filename: " + results[1]); - - generated_slave_filename = ProtoCommon.genSlaveFilename(master_filename, prefix_name, file_ext_name); - if (!generated_slave_filename.equals(results[1])) { - System.err.println("generated slave file: " + generated_slave_filename + "\n != returned slave file: " + results[1]); - } - - System.err.println(client.get_file_info(results[0], results[1])); - } - } else { - System.err.println("Upload file fail, error no: " + errno); - } - - storageServer = tracker.getFetchStorage(trackerServer, group_name, remote_filename); - if (storageServer == null) { - System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); - return; - } - /* for test only */ - System.out.println("active test to storage server: " + ProtoCommon.activeTest(storageServer.getSocket())); - - storageServer.close(); - - /* for test only */ - System.out.println("active test to tracker server: " + ProtoCommon.activeTest(trackerServer.getSocket())); - - trackerServer.close(); - } catch (Exception ex) { - ex.printStackTrace(); } - } } diff --git a/src/test/java/org/csource/fastdfs/TestClient1.java b/src/test/java/org/csource/fastdfs/TestClient1.java index 663b571..c19c1ab 100644 --- a/src/test/java/org/csource/fastdfs/TestClient1.java +++ b/src/test/java/org/csource/fastdfs/TestClient1.java @@ -9,7 +9,6 @@ package org.csource.fastdfs; import org.csource.common.NameValuePair; -import org.csource.fastdfs.*; import java.io.File; import java.net.InetSocketAddress; @@ -21,40 +20,40 @@ import java.net.InetSocketAddress; * @version Version 1.16 */ public class TestClient1 { - private TestClient1() { - } - - /** - * entry point - * - * @param args comand arguments - *
  • args[0]: config filename
- *
  • args[1]: local filename to upload
- */ - public static void main(String args[]) { - if (args.length < 2) { - System.out.println("Error: Must have 2 parameters, one is config filename, " - + "the other is the local filename to upload"); - return; + private TestClient1() { } - System.out.println("java.version=" + System.getProperty("java.version")); + /** + * entry point + * + * @param args comand arguments + *
  • args[0]: config filename
+ *
  • args[1]: local filename to upload
+ */ + public static void main(String args[]) { + if (args.length < 2) { + System.out.println("Error: Must have 2 parameters, one is config filename, " + + "the other is the local filename to upload"); + return; + } - String conf_filename = args[0]; - String local_filename = args[1]; - String group_name; + System.out.println("java.version=" + System.getProperty("java.version")); - try { - ClientGlobal.init(conf_filename); - System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); - System.out.println("charset=" + ClientGlobal.g_charset); + String conf_filename = args[0]; + String local_filename = args[1]; + String group_name; - String file_id; + try { + ClientGlobal.init(conf_filename); + System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); + System.out.println("charset=" + ClientGlobal.g_charset); - TrackerClient tracker = new TrackerClient(); - TrackerServer trackerServer = tracker.getConnection(); + String file_id; - StorageServer storageServer = null; + TrackerClient tracker = new TrackerClient(); + TrackerServer trackerServer = tracker.getTrackerServer(); + + StorageServer storageServer = null; /* storageServer = tracker.getStoreStorage(trackerServer); if (storageServer == null) @@ -63,204 +62,202 @@ public class TestClient1 { return; } */ - StorageClient1 client = new StorageClient1(trackerServer, storageServer); - byte[] file_buff; - NameValuePair[] meta_list; - String master_file_id; - String prefix_name; - String file_ext_name; - String slave_file_id; - String generated_slave_file_id; - int errno; + StorageClient1 client = new StorageClient1(trackerServer, storageServer); + byte[] file_buff; + NameValuePair[] meta_list; + String master_file_id; + String prefix_name; + String file_ext_name; + String slave_file_id; + String generated_slave_file_id; + int errno; - group_name = "group1"; - StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); - if (storageServers == null) { - System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); - } else { - System.err.println("store storage servers count: " + storageServers.length); - for (int k = 0; k < storageServers.length; k++) { - System.err.println((k + 1) + ". " + storageServers[k].getInetSocketAddress().getAddress().getHostAddress() + ":" + storageServers[k].getInetSocketAddress().getPort()); - } - System.err.println(""); - } + group_name = "group1"; + StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); + if (storageServers == null) { + System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); + } else { + System.err.println("store storage servers count: " + storageServers.length); + for (int k = 0; k < storageServers.length; k++) { + System.err.println((k + 1) + ". " + storageServers[k].getInetSocketAddress().getAddress().getHostAddress() + ":" + storageServers[k].getInetSocketAddress().getPort()); + } + System.err.println(""); + } - meta_list = new NameValuePair[4]; - meta_list[0] = new NameValuePair("width", "800"); - meta_list[1] = new NameValuePair("heigth", "600"); - meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); - meta_list[3] = new NameValuePair("author", "Mike"); + meta_list = new NameValuePair[4]; + meta_list[0] = new NameValuePair("width", "800"); + meta_list[1] = new NameValuePair("heigth", "600"); + meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); + meta_list[3] = new NameValuePair("author", "Mike"); - file_buff = "this is a test".getBytes(ClientGlobal.g_charset); - System.out.println("file length: " + file_buff.length); + file_buff = "this is a test".getBytes(ClientGlobal.g_charset); + System.out.println("file length: " + file_buff.length); - file_id = client.upload_file1(file_buff, "txt", meta_list); + file_id = client.upload_file1(file_buff, "txt", meta_list); /* group_name = "group1"; file_id = client.upload_file1(group_name, file_buff, "txt", meta_list); */ - if (file_id == null) { - System.err.println("upload file fail, error code: " + client.getErrorCode()); - return; - } else { - System.err.println("file_id: " + file_id); - System.err.println(client.get_file_info1(file_id)); + if (file_id == null) { + System.err.println("upload file fail, error code: " + client.getErrorCode()); + return; + } else { + System.err.println("file_id: " + file_id); + System.err.println(client.get_file_info1(file_id)); - ServerInfo[] servers = tracker.getFetchStorages1(trackerServer, file_id); - if (servers == null) { - System.err.println("get storage servers fail, error code: " + tracker.getErrorCode()); - } else { - System.err.println("storage servers count: " + servers.length); - for (int k = 0; k < servers.length; k++) { - System.err.println((k + 1) + ". " + servers[k].getIpAddr() + ":" + servers[k].getPort()); - } - System.err.println(""); + ServerInfo[] servers = tracker.getFetchStorages1(trackerServer, file_id); + if (servers == null) { + System.err.println("get storage servers fail, error code: " + tracker.getErrorCode()); + } else { + System.err.println("storage servers count: " + servers.length); + for (int k = 0; k < servers.length; k++) { + System.err.println((k + 1) + ". " + servers[k].getIpAddr() + ":" + servers[k].getPort()); + } + System.err.println(""); + } + + meta_list = new NameValuePair[4]; + meta_list[0] = new NameValuePair("width", "1024"); + meta_list[1] = new NameValuePair("heigth", "768"); + meta_list[2] = new NameValuePair("bgcolor", "#000000"); + meta_list[3] = new NameValuePair("title", "Untitle"); + + if ((errno = client.set_metadata1(file_id, meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE)) == 0) { + System.err.println("set_metadata success"); + } else { + System.err.println("set_metadata fail, error no: " + errno); + } + + meta_list = client.get_metadata1(file_id); + if (meta_list != null) { + for (int i = 0; i < meta_list.length; i++) { + System.out.println(meta_list[i].getName() + " " + meta_list[i].getValue()); + } + } + + //Thread.sleep(30000); + + file_buff = client.download_file1(file_id); + if (file_buff != null) { + System.out.println("file length:" + file_buff.length); + System.out.println((new String(file_buff))); + } + + master_file_id = file_id; + prefix_name = "-part1"; + file_ext_name = "txt"; + file_buff = "this is a slave buff.".getBytes(ClientGlobal.g_charset); + slave_file_id = client.upload_file1(master_file_id, prefix_name, file_buff, file_ext_name, meta_list); + if (slave_file_id != null) { + System.err.println("slave file_id: " + slave_file_id); + System.err.println(client.get_file_info1(slave_file_id)); + + generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name); + if (!generated_slave_file_id.equals(slave_file_id)) { + System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id); + } + } + + //Thread.sleep(10000); + if ((errno = client.delete_file1(file_id)) == 0) { + System.err.println("Delete file success"); + } else { + System.err.println("Delete file fail, error no: " + errno); + } + } + + if ((file_id = client.upload_file1(local_filename, null, meta_list)) != null) { + int ts; + String token; + String file_url; + InetSocketAddress inetSockAddr; + + System.err.println("file_id: " + file_id); + System.err.println(client.get_file_info1(file_id)); + + inetSockAddr = trackerServer.getInetSocketAddress(); + file_url = "http://" + inetSockAddr.getAddress().getHostAddress(); + if (ClientGlobal.g_tracker_http_port != 80) { + file_url += ":" + ClientGlobal.g_tracker_http_port; + } + file_url += "/" + file_id; + if (ClientGlobal.g_anti_steal_token) { + ts = (int) (System.currentTimeMillis() / 1000); + token = ProtoCommon.getToken(file_id, ts, ClientGlobal.g_secret_key); + file_url += "?token=" + token + "&ts=" + ts; + } + System.err.println("file url: " + file_url); + + errno = client.download_file1(file_id, 0, 100, "c:\\" + file_id.replaceAll("/", "_")); + if (errno == 0) { + System.err.println("Download file success"); + } else { + System.err.println("Download file fail, error no: " + errno); + } + + errno = client.download_file1(file_id, new DownloadFileWriter("c:\\" + file_id.replaceAll("/", "-"))); + if (errno == 0) { + System.err.println("Download file success"); + } else { + System.err.println("Download file fail, error no: " + errno); + } + + master_file_id = file_id; + prefix_name = "-part2"; + file_ext_name = null; + slave_file_id = client.upload_file1(master_file_id, prefix_name, local_filename, file_ext_name, meta_list); + if (slave_file_id != null) { + System.err.println("slave file_id: " + slave_file_id); + System.err.println(client.get_file_info1(slave_file_id)); + + generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name); + if (!generated_slave_file_id.equals(slave_file_id)) { + System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id); + } + } + } + + File f; + f = new File(local_filename); + int nPos = local_filename.lastIndexOf('.'); + if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + file_ext_name = local_filename.substring(nPos + 1); + } else { + file_ext_name = null; + } + + file_id = client.upload_file1(null, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); + if (file_id != null) { + System.out.println("file id: " + file_id); + System.out.println(client.get_file_info1(file_id)); + master_file_id = file_id; + prefix_name = "-part3"; + slave_file_id = client.upload_file1(master_file_id, prefix_name, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); + if (slave_file_id != null) { + System.err.println("slave file_id: " + slave_file_id); + generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name); + if (!generated_slave_file_id.equals(slave_file_id)) { + System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id); + } + } + } else { + System.err.println("Upload file fail, error no: " + errno); + } + + storageServer = tracker.getFetchStorage1(trackerServer, file_id); + if (storageServer == null) { + System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); + return; + } + + + /* for test only */ + System.out.println("active test to storage server: " + storageServer.getConnection().activeTest()); + + /* for test only */ + System.out.println("active test to tracker server: " + trackerServer.getConnection().activeTest()); + } catch (Exception ex) { + ex.printStackTrace(); } - - meta_list = new NameValuePair[4]; - meta_list[0] = new NameValuePair("width", "1024"); - meta_list[1] = new NameValuePair("heigth", "768"); - meta_list[2] = new NameValuePair("bgcolor", "#000000"); - meta_list[3] = new NameValuePair("title", "Untitle"); - - if ((errno = client.set_metadata1(file_id, meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE)) == 0) { - System.err.println("set_metadata success"); - } else { - System.err.println("set_metadata fail, error no: " + errno); - } - - meta_list = client.get_metadata1(file_id); - if (meta_list != null) { - for (int i = 0; i < meta_list.length; i++) { - System.out.println(meta_list[i].getName() + " " + meta_list[i].getValue()); - } - } - - //Thread.sleep(30000); - - file_buff = client.download_file1(file_id); - if (file_buff != null) { - System.out.println("file length:" + file_buff.length); - System.out.println((new String(file_buff))); - } - - master_file_id = file_id; - prefix_name = "-part1"; - file_ext_name = "txt"; - file_buff = "this is a slave buff.".getBytes(ClientGlobal.g_charset); - slave_file_id = client.upload_file1(master_file_id, prefix_name, file_buff, file_ext_name, meta_list); - if (slave_file_id != null) { - System.err.println("slave file_id: " + slave_file_id); - System.err.println(client.get_file_info1(slave_file_id)); - - generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name); - if (!generated_slave_file_id.equals(slave_file_id)) { - System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id); - } - } - - //Thread.sleep(10000); - if ((errno = client.delete_file1(file_id)) == 0) { - System.err.println("Delete file success"); - } else { - System.err.println("Delete file fail, error no: " + errno); - } - } - - if ((file_id = client.upload_file1(local_filename, null, meta_list)) != null) { - int ts; - String token; - String file_url; - InetSocketAddress inetSockAddr; - - System.err.println("file_id: " + file_id); - System.err.println(client.get_file_info1(file_id)); - - inetSockAddr = trackerServer.getInetSocketAddress(); - file_url = "http://" + inetSockAddr.getAddress().getHostAddress(); - if (ClientGlobal.g_tracker_http_port != 80) { - file_url += ":" + ClientGlobal.g_tracker_http_port; - } - file_url += "/" + file_id; - if (ClientGlobal.g_anti_steal_token) { - ts = (int) (System.currentTimeMillis() / 1000); - token = ProtoCommon.getToken(file_id, ts, ClientGlobal.g_secret_key); - file_url += "?token=" + token + "&ts=" + ts; - } - System.err.println("file url: " + file_url); - - errno = client.download_file1(file_id, 0, 100, "c:\\" + file_id.replaceAll("/", "_")); - if (errno == 0) { - System.err.println("Download file success"); - } else { - System.err.println("Download file fail, error no: " + errno); - } - - errno = client.download_file1(file_id, new DownloadFileWriter("c:\\" + file_id.replaceAll("/", "-"))); - if (errno == 0) { - System.err.println("Download file success"); - } else { - System.err.println("Download file fail, error no: " + errno); - } - - master_file_id = file_id; - prefix_name = "-part2"; - file_ext_name = null; - slave_file_id = client.upload_file1(master_file_id, prefix_name, local_filename, file_ext_name, meta_list); - if (slave_file_id != null) { - System.err.println("slave file_id: " + slave_file_id); - System.err.println(client.get_file_info1(slave_file_id)); - - generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name); - if (!generated_slave_file_id.equals(slave_file_id)) { - System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id); - } - } - } - - File f; - f = new File(local_filename); - int nPos = local_filename.lastIndexOf('.'); - if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { - file_ext_name = local_filename.substring(nPos + 1); - } else { - file_ext_name = null; - } - - file_id = client.upload_file1(null, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); - if (file_id != null) { - System.out.println("file id: " + file_id); - System.out.println(client.get_file_info1(file_id)); - master_file_id = file_id; - prefix_name = "-part3"; - slave_file_id = client.upload_file1(master_file_id, prefix_name, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); - if (slave_file_id != null) { - System.err.println("slave file_id: " + slave_file_id); - generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name); - if (!generated_slave_file_id.equals(slave_file_id)) { - System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id); - } - } - } else { - System.err.println("Upload file fail, error no: " + errno); - } - - storageServer = tracker.getFetchStorage1(trackerServer, file_id); - if (storageServer == null) { - System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); - return; - } - - /* for test only */ - System.out.println("active test to storage server: " + ProtoCommon.activeTest(storageServer.getSocket())); - storageServer.close(); - - /* for test only */ - System.out.println("active test to tracker server: " + ProtoCommon.activeTest(trackerServer.getSocket())); - - trackerServer.close(); - } catch (Exception ex) { - ex.printStackTrace(); } - } } diff --git a/src/test/java/org/csource/fastdfs/TestLoad.java b/src/test/java/org/csource/fastdfs/TestLoad.java index f3bab37..c80b51a 100644 --- a/src/test/java/org/csource/fastdfs/TestLoad.java +++ b/src/test/java/org/csource/fastdfs/TestLoad.java @@ -8,8 +8,6 @@ package org.csource.fastdfs; -import org.csource.fastdfs.*; - /** * load test class * @@ -88,7 +86,7 @@ public class TestLoad { public Uploader() throws Exception { this.tracker = new TrackerClient(); - this.trackerServer = tracker.getConnection(); + this.trackerServer = tracker.getTrackerServer(); } public int uploadFile() throws Exception { @@ -129,7 +127,7 @@ public class TestLoad { public Downloader() throws Exception { this.tracker = new TrackerClient(); - this.trackerServer = tracker.getConnection(); + this.trackerServer = tracker.getTrackerServer(); this.callback = new DownloadFileDiscard(); }