mirror of
https://github.com/happyfish100/fastdfs-client-java.git
synced 2026-09-18 18:59:00 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c954e697b | ||
|
|
7e644f1ba4 | ||
|
|
9d9b1d7fdb | ||
|
|
bb203bdc71 | ||
|
|
020857dbf1 | ||
|
|
da417c7d1c | ||
|
|
31eb6beb09 | ||
|
|
208f63f14c | ||
|
|
a04626523a | ||
|
|
697bf97442 | ||
|
|
45d9a89e25 | ||
|
|
42132c694c | ||
|
|
1b263e6436 | ||
|
|
41655defd8 | ||
|
|
a1df79c50e | ||
|
|
2b4693643a | ||
|
|
4de15ae592 | ||
|
|
0087216c0a | ||
|
|
77946b2382 | ||
|
|
0b2ec3aa10 | ||
|
|
8d966af4a4 | ||
|
|
9cc79ed75d | ||
|
|
8db4ff7dd0 | ||
|
|
4987967e0b | ||
|
|
56af1ae72f | ||
|
|
987e9194ad | ||
|
|
670909eed1 | ||
|
|
1ba6fb7975 | ||
|
|
aafd0b4b8c | ||
|
|
06f5624a8d | ||
|
|
47d53c9a19 | ||
|
|
bb13294205 | ||
|
|
f742f3c6aa |
+2
-1
@@ -12,6 +12,7 @@ target
|
||||
*.iws
|
||||
*.log
|
||||
.idea
|
||||
|
||||
*.conf
|
||||
*.PNG
|
||||
*.class
|
||||
*.swp
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
|
||||
Version 1.32 2024-02-12
|
||||
* change FDFS_VERSION_SIZE from 6 to 8
|
||||
you must upgrade your FastDFS server to V6.12 or higher version
|
||||
|
||||
Version 1.31 2023-12-13
|
||||
* adapt to FastDFS server V6.11 for IPv6
|
||||
you must upgrade your FastDFS server to V6.11 or higher version
|
||||
* connect to storage server failover with multi IPs
|
||||
|
||||
Version 1.30 2023-01-29
|
||||
* support tracker server fail over
|
||||
If the tracker server is not specified, when the tracker server fails to
|
||||
get the connection, it will try to get the connection from other tracker servers.
|
||||
The maximum number of attempts is the number of tracker servers minus 1
|
||||
|
||||
Version 1.29 2020-01-03
|
||||
* support active test for connection pool.
|
||||
when the tracker / storage server restarts or the network burst failure
|
||||
occurs, only one request will be sacrificed (failed), the rest of
|
||||
the connections in the pool will be enabled to active test for validation.
|
||||
|
||||
Version 1.28 2019-12-30
|
||||
* support connection pool. you can use connection pool or a short connection.
|
||||
configuration items please see fdfs_client.conf and client.properties
|
||||
|
||||
@@ -26,7 +26,7 @@ mvn install:install-file -DgroupId=org.csource -DartifactId=fastdfs-client-java
|
||||
<dependency>
|
||||
<groupId>org.csource</groupId>
|
||||
<artifactId>fastdfs-client-java</artifactId>
|
||||
<version>1.28-SNAPSHOT</version>
|
||||
<version>1.31-SNAPSHOT</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
@@ -5,10 +5,23 @@ http.tracker_http_port = 8080
|
||||
http.anti_steal_token = no
|
||||
http.secret_key = FastDFS1234567890
|
||||
|
||||
#tracker_server
|
||||
# IPv4:
|
||||
# for example: 192.168.2.100,122.244.141.46:22122
|
||||
#
|
||||
# IPv6:
|
||||
# for example: [2409:8a20:42d:2f40:587a:4c47:72c0:ad8e]:22122
|
||||
#
|
||||
tracker_server = 10.0.11.247:22122
|
||||
tracker_server = 10.0.11.248:22122
|
||||
tracker_server = 10.0.11.249:22122
|
||||
|
||||
# connect which ip address first for multi IPs of a storage server, value list:
|
||||
## tracker: connect to the ip address return by tracker server first
|
||||
## last-connected: connect to the ip address last connected first
|
||||
# default value is tracker
|
||||
connect_first_by = tracker
|
||||
|
||||
connection_pool.enabled = true
|
||||
connection_pool.max_count_per_entry = 500
|
||||
connection_pool.max_idle_time = 3600
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>org.csource</groupId>
|
||||
<artifactId>fastdfs-client-java</artifactId>
|
||||
<version>1.28-SNAPSHOT</version>
|
||||
<version>1.32-SNAPSHOT</version>
|
||||
<name>fastdfs-client-java</name>
|
||||
<description>fastdfs client for java</description>
|
||||
<packaging>jar</packaging>
|
||||
@@ -15,19 +15,26 @@
|
||||
<maven.test.failure.ignore>true</maven.test.failure.ignore>
|
||||
<maven.test.skip>true</maven.test.skip>
|
||||
<jdk.version>1.6</jdk.version>
|
||||
<slf4j.version>1.7.26</slf4j.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.7.26</version>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -155,13 +155,13 @@ public class IniFileReader {
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) in.close();
|
||||
//System.out.println("loadFrom...finally...in.close(); done");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void readToParamTable(InputStream in) throws IOException {
|
||||
this.paramTable = new Hashtable();
|
||||
if (in == null) return;
|
||||
@@ -206,7 +206,6 @@ public class IniFileReader {
|
||||
try {
|
||||
if (bufferedReader != null) bufferedReader.close();
|
||||
if (inReader != null) inReader.close();
|
||||
//System.out.println("readToParamTable...finally...bufferedReader.close();inReader.close(); done");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.csource.common.MyException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
@@ -41,14 +42,13 @@ public class ClientGlobal {
|
||||
public static final String PROP_KEY_HTTP_SECRET_KEY = "fastdfs.http_secret_key";
|
||||
public static final String PROP_KEY_HTTP_TRACKER_HTTP_PORT = "fastdfs.http_tracker_http_port";
|
||||
public static final String PROP_KEY_TRACKER_SERVERS = "fastdfs.tracker_servers";
|
||||
|
||||
public static final String PROP_KEY_CONNECT_FIRST_BY = "fastdfs.connect_first_by";
|
||||
|
||||
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_IN_MS = "fastdfs.connection_pool.max_wait_time_in_ms";
|
||||
|
||||
|
||||
public static final int DEFAULT_CONNECT_TIMEOUT = 5; //second
|
||||
public static final int DEFAULT_NETWORK_TIMEOUT = 30; //second
|
||||
public static final String DEFAULT_CHARSET = "UTF-8";
|
||||
@@ -56,6 +56,9 @@ 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 int CONNECT_FIRST_BY_TRACKER = 0;
|
||||
public static final int CONNECT_FIRST_BY_LAST_CONNECTED = 1;
|
||||
|
||||
public static final boolean DEFAULT_CONNECTION_POOL_ENABLED = true;
|
||||
public static final int DEFAULT_CONNECTION_POOL_MAX_COUNT_PER_ENTRY = 100;
|
||||
public static final int DEFAULT_CONNECTION_POOL_MAX_IDLE_TIME = 3600 ;//second
|
||||
@@ -67,6 +70,9 @@ public class ClientGlobal {
|
||||
public static boolean g_anti_steal_token = DEFAULT_HTTP_ANTI_STEAL_TOKEN; //if anti-steal token
|
||||
public static String g_secret_key = DEFAULT_HTTP_SECRET_KEY; //generage token secret key
|
||||
public static int g_tracker_http_port = DEFAULT_HTTP_TRACKER_HTTP_PORT;
|
||||
public static int g_connect_first_by = CONNECT_FIRST_BY_TRACKER;
|
||||
public static boolean g_multi_storage_ips = false;
|
||||
public static StorageAddressMap g_storages_address_map;
|
||||
|
||||
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;
|
||||
@@ -78,6 +84,74 @@ public class ClientGlobal {
|
||||
private ClientGlobal() {
|
||||
}
|
||||
|
||||
private static void loadStorageServersFromTracker() throws IOException, MyException {
|
||||
TrackerClient tracker = new TrackerClient();
|
||||
StringBuilder builder = tracker.fetchStorageIds();
|
||||
if (builder.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean without_port = true;
|
||||
int count = 0;
|
||||
String[] lines = builder.toString().split("\n");
|
||||
String[] ipAddresses = new String[lines.length];
|
||||
for (String line : lines) {
|
||||
String[] cols = line.split(" ");
|
||||
if (cols.length != 3) {
|
||||
throw new MyException("invalid line: " + line);
|
||||
}
|
||||
|
||||
String ipAddrs = cols[2];
|
||||
if (ipAddrs.indexOf(',') > 0) {
|
||||
ipAddresses[count++] = ipAddrs;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int startIndex;
|
||||
if (ipAddresses[0].charAt(0) == '[') { //IPv6
|
||||
if ((startIndex=ipAddresses[0].indexOf(']')) < 0) {
|
||||
throw new MyException("invalid IPv6 address: " + ipAddresses[0]);
|
||||
}
|
||||
} else {
|
||||
startIndex = 0;
|
||||
}
|
||||
if (ipAddresses[0].indexOf(':', startIndex) > 0) {
|
||||
without_port = false;
|
||||
}
|
||||
|
||||
g_multi_storage_ips = true;
|
||||
g_storages_address_map = new StorageAddressMap(without_port);
|
||||
if (without_port) {
|
||||
for (String ipAddr: ipAddresses) {
|
||||
if (ipAddr.charAt(0) == '[') { //IPv6
|
||||
ipAddr = ipAddr.substring(1, ipAddr.length() - 1);
|
||||
}
|
||||
String[] cols = ipAddr.split(",");
|
||||
g_storages_address_map.puts(cols[0], cols[1]);
|
||||
}
|
||||
} else {
|
||||
for (String ipPort: ipAddresses) {
|
||||
int colonIndex = ipPort.lastIndexOf(':');
|
||||
if (colonIndex < 0) {
|
||||
throw new MyException("invalid ip and port: " + ipPort);
|
||||
}
|
||||
|
||||
String ipAddr = ipPort.substring(0, colonIndex);
|
||||
int port = Integer.parseInt(ipPort.substring(colonIndex + 1));
|
||||
|
||||
if (ipAddr.charAt(0) == '[') { //IPv6
|
||||
ipAddr = ipAddr.substring(1, ipAddr.length() - 1);
|
||||
}
|
||||
String[] cols = ipAddr.split(",");
|
||||
g_storages_address_map.puts(cols[0], cols[1], port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* load global variables
|
||||
*
|
||||
@@ -114,15 +188,27 @@ public class ClientGlobal {
|
||||
|
||||
InetSocketAddress[] tracker_servers = new InetSocketAddress[szTrackerServers.length];
|
||||
for (int i = 0; i < szTrackerServers.length; i++) {
|
||||
parts = szTrackerServers[i].split("\\:", 2);
|
||||
if (szTrackerServers[i].contains("[")) {
|
||||
parts = new String[2];
|
||||
parts[0] = szTrackerServers[i].substring(1, szTrackerServers[i].indexOf("]"));
|
||||
parts[1] = szTrackerServers[i].substring(szTrackerServers[i].lastIndexOf(":") + 1);
|
||||
} else {
|
||||
parts = szTrackerServers[i].split("\\:", 2);
|
||||
}
|
||||
|
||||
if (parts.length != 2) {
|
||||
throw new MyException("the value of item \"tracker_server\" is invalid, the correct format is host:port");
|
||||
}
|
||||
|
||||
tracker_servers[i] = new InetSocketAddress(parts[0].trim(), Integer.parseInt(parts[1].trim()));
|
||||
tracker_servers[i] = new InetSocketAddress(InetAddress.getByName(parts[0].trim()), Integer.parseInt(parts[1].trim()));
|
||||
}
|
||||
g_tracker_group = new TrackerGroup(tracker_servers);
|
||||
|
||||
String connect_first_by = iniReader.getStrValue("connect_first_by");
|
||||
if (connect_first_by != null && connect_first_by.equalsIgnoreCase("last-connected")) {
|
||||
g_connect_first_by = CONNECT_FIRST_BY_LAST_CONNECTED;
|
||||
}
|
||||
|
||||
g_tracker_http_port = iniReader.getIntValue("http.tracker_http_port", 80);
|
||||
g_anti_steal_token = iniReader.getBoolValue("http.anti_steal_token", false);
|
||||
if (g_anti_steal_token) {
|
||||
@@ -139,6 +225,8 @@ public class ClientGlobal {
|
||||
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;
|
||||
}
|
||||
|
||||
loadStorageServersFromTracker();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,11 +264,12 @@ public class ClientGlobal {
|
||||
String httpAntiStealTokenConf = props.getProperty(PROP_KEY_HTTP_ANTI_STEAL_TOKEN);
|
||||
String httpSecretKeyConf = props.getProperty(PROP_KEY_HTTP_SECRET_KEY);
|
||||
String httpTrackerHttpPortConf = props.getProperty(PROP_KEY_HTTP_TRACKER_HTTP_PORT);
|
||||
|
||||
String connectFirstBy = props.getProperty(PROP_KEY_CONNECT_FIRST_BY);
|
||||
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 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;
|
||||
}
|
||||
@@ -199,6 +288,10 @@ public class ClientGlobal {
|
||||
if (httpTrackerHttpPortConf != null && httpTrackerHttpPortConf.trim().length() != 0) {
|
||||
g_tracker_http_port = Integer.parseInt(httpTrackerHttpPortConf);
|
||||
}
|
||||
|
||||
if (connectFirstBy != null && connectFirstBy.equalsIgnoreCase("last-connected")) {
|
||||
g_connect_first_by = CONNECT_FIRST_BY_LAST_CONNECTED;
|
||||
}
|
||||
if (poolEnabled != null && poolEnabled.trim().length() != 0) {
|
||||
g_connection_pool_enabled = Boolean.parseBoolean(poolEnabled);
|
||||
}
|
||||
@@ -211,6 +304,8 @@ public class ClientGlobal {
|
||||
if (poolMaxWaitTimeInMS != null && poolMaxWaitTimeInMS.trim().length() != 0) {
|
||||
g_connection_pool_max_wait_time_in_ms = Integer.parseInt(poolMaxWaitTimeInMS);
|
||||
}
|
||||
|
||||
loadStorageServersFromTracker();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,15 +316,21 @@ public class ClientGlobal {
|
||||
* server之间用逗号','分隔
|
||||
*/
|
||||
public static void initByTrackers(String trackerServers) throws IOException, MyException {
|
||||
List<InetSocketAddress> list = new ArrayList();
|
||||
List<InetSocketAddress> list = new ArrayList<InetSocketAddress>();
|
||||
String spr1 = ",";
|
||||
String spr2 = ":";
|
||||
String[] arr1 = trackerServers.trim().split(spr1);
|
||||
for (String addrStr : arr1) {
|
||||
String[] arr2 = addrStr.trim().split(spr2);
|
||||
String host = arr2[0].trim();
|
||||
int port = Integer.parseInt(arr2[1].trim());
|
||||
list.add(new InetSocketAddress(host, port));
|
||||
if(addrStr.contains("[")) {
|
||||
String host = addrStr.substring(1, addrStr.indexOf("]"));
|
||||
int port = Integer.parseInt(addrStr.substring(addrStr.lastIndexOf(":") + 1));
|
||||
list.add(new InetSocketAddress(InetAddress.getByName(host), port));
|
||||
} else {
|
||||
String[] arr2 = addrStr.trim().split(spr2);
|
||||
String host = arr2[0].trim();
|
||||
int port = Integer.parseInt(arr2[1].trim());
|
||||
list.add(new InetSocketAddress(InetAddress.getByName(host), port));
|
||||
}
|
||||
}
|
||||
InetSocketAddress[] trackerAddresses = list.toArray(new InetSocketAddress[list.size()]);
|
||||
initByTrackers(trackerAddresses);
|
||||
@@ -249,7 +350,7 @@ public class ClientGlobal {
|
||||
public static Socket getSocket(String ip_addr, int port) throws IOException {
|
||||
Socket sock = new Socket();
|
||||
sock.setSoTimeout(ClientGlobal.g_network_timeout);
|
||||
sock.connect(new InetSocketAddress(ip_addr, port), ClientGlobal.g_connect_timeout);
|
||||
sock.connect(new InetSocketAddress(InetAddress.getByName(ip_addr), port), ClientGlobal.g_connect_timeout);
|
||||
return sock;
|
||||
}
|
||||
|
||||
@@ -337,7 +438,8 @@ public class ClientGlobal {
|
||||
InetSocketAddress[] trackerAddresses = g_tracker_group.tracker_servers;
|
||||
for (InetSocketAddress inetSocketAddress : trackerAddresses) {
|
||||
if(trackerServers.length() > 0) trackerServers += ",";
|
||||
trackerServers += inetSocketAddress.toString().substring(1);
|
||||
String address = inetSocketAddress.toString();
|
||||
trackerServers += address.startsWith("/") ? address.substring(1) : address;
|
||||
}
|
||||
}
|
||||
return "{"
|
||||
@@ -347,6 +449,8 @@ public class ClientGlobal {
|
||||
+ "\n g_anti_steal_token = " + g_anti_steal_token
|
||||
+ "\n g_secret_key = " + g_secret_key
|
||||
+ "\n g_tracker_http_port = " + g_tracker_http_port
|
||||
+ "\n g_multi_storage_ips = " + g_multi_storage_ips
|
||||
+ "\n g_connect_first_by = " + (g_connect_first_by == CONNECT_FIRST_BY_TRACKER ? "tracker" : "last-connected")
|
||||
+ "\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(ms) = " + g_connection_pool_max_idle_time
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.Arrays;
|
||||
*/
|
||||
public class ProtoCommon {
|
||||
public static final byte FDFS_PROTO_CMD_QUIT = 82;
|
||||
public static final byte TRACKER_PROTO_CMD_FETCH_STORAGE_IDS = 69;
|
||||
public static final byte TRACKER_PROTO_CMD_SERVER_LIST_GROUP = 91;
|
||||
public static final byte TRACKER_PROTO_CMD_SERVER_LIST_STORAGE = 92;
|
||||
public static final byte TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE = 93;
|
||||
@@ -72,9 +73,9 @@ public class ProtoCommon {
|
||||
public static final int FDFS_PROTO_PKG_LEN_SIZE = 8;
|
||||
public static final int FDFS_PROTO_CMD_SIZE = 1;
|
||||
public static final int FDFS_GROUP_NAME_MAX_LEN = 16;
|
||||
public static final int FDFS_IPADDR_SIZE = 16;
|
||||
public static final int FDFS_IPADDR_SIZE = 46;
|
||||
public static final int FDFS_DOMAIN_NAME_MAX_SIZE = 128;
|
||||
public static final int FDFS_VERSION_SIZE = 6;
|
||||
public static final int FDFS_VERSION_SIZE = 8;
|
||||
public static final int FDFS_STORAGE_ID_MAX_SIZE = 16;
|
||||
public static final String FDFS_RECORD_SEPERATOR = "\u0001";
|
||||
public static final String FDFS_FIELD_SEPERATOR = "\u0002";
|
||||
@@ -310,6 +311,23 @@ public class ProtoCommon {
|
||||
return headerInfo.errno == 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* int convert to buff (big-endian)
|
||||
*
|
||||
* @param n int number
|
||||
* @return 4 bytes buff
|
||||
*/
|
||||
public static byte[] int2buff(int n) {
|
||||
byte[] bs;
|
||||
|
||||
bs = new byte[4];
|
||||
bs[0] = (byte) ((n >> 24) & 0xFF);
|
||||
bs[1] = (byte) ((n >> 16) & 0xFF);
|
||||
bs[2] = (byte) ((n >> 8) & 0xFF);
|
||||
bs[3] = (byte) (n & 0xFF);
|
||||
return bs;
|
||||
}
|
||||
|
||||
/**
|
||||
* long convert to buff (big-endian)
|
||||
*
|
||||
@@ -317,19 +335,18 @@ public class ProtoCommon {
|
||||
* @return 8 bytes buff
|
||||
*/
|
||||
public static byte[] long2buff(long n) {
|
||||
byte[] bs;
|
||||
byte[] bs;
|
||||
|
||||
bs = new byte[8];
|
||||
bs[0] = (byte) ((n >> 56) & 0xFF);
|
||||
bs[1] = (byte) ((n >> 48) & 0xFF);
|
||||
bs[2] = (byte) ((n >> 40) & 0xFF);
|
||||
bs[3] = (byte) ((n >> 32) & 0xFF);
|
||||
bs[4] = (byte) ((n >> 24) & 0xFF);
|
||||
bs[5] = (byte) ((n >> 16) & 0xFF);
|
||||
bs[6] = (byte) ((n >> 8) & 0xFF);
|
||||
bs[7] = (byte) (n & 0xFF);
|
||||
|
||||
return bs;
|
||||
bs = new byte[8];
|
||||
bs[0] = (byte) ((n >> 56) & 0xFF);
|
||||
bs[1] = (byte) ((n >> 48) & 0xFF);
|
||||
bs[2] = (byte) ((n >> 40) & 0xFF);
|
||||
bs[3] = (byte) ((n >> 32) & 0xFF);
|
||||
bs[4] = (byte) ((n >> 24) & 0xFF);
|
||||
bs[5] = (byte) ((n >> 16) & 0xFF);
|
||||
bs[6] = (byte) ((n >> 8) & 0xFF);
|
||||
bs[7] = (byte) (n & 0xFF);
|
||||
return bs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ public class ProtoStructDecoder<T extends StructBase> {
|
||||
/**
|
||||
* decode byte buffer
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T[] decode(byte[] bs, Class<T> clazz, int fieldsTotalSize) throws Exception {
|
||||
if (bs.length % fieldsTotalSize != 0) {
|
||||
throw new IOException("byte array length: " + bs.length + " is invalid!");
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (C) 2023 Happy Fish / YuQing
|
||||
* <p>
|
||||
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
|
||||
* General Public License (LGPL).
|
||||
* Please visit the FastDFS Home Page https://github.com/happyfish100/fastdfs for more detail.
|
||||
*/
|
||||
|
||||
package org.csource.fastdfs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* Storage Server Address Map
|
||||
*
|
||||
* @author Happy Fish / YuQing
|
||||
* @version Version 1.31
|
||||
*/
|
||||
public class StorageAddressMap {
|
||||
|
||||
protected boolean without_port;
|
||||
protected HashMap<String, InetSocketAddress> storages;
|
||||
|
||||
public StorageAddressMap(boolean without_port) {
|
||||
this.without_port = without_port;
|
||||
this.storages = new HashMap<String, InetSocketAddress>();
|
||||
}
|
||||
|
||||
protected String getKey(String ipAddr, int port) {
|
||||
return ipAddr + "@" + port;
|
||||
}
|
||||
|
||||
public void puts(String srcIpAddr, String destIpAddr, int port) {
|
||||
storages.put(this.getKey(srcIpAddr, port),
|
||||
new InetSocketAddress(destIpAddr, port));
|
||||
storages.put(this.getKey(destIpAddr, port),
|
||||
new InetSocketAddress(srcIpAddr, port));
|
||||
}
|
||||
|
||||
public void puts(String srcIpAddr, String destIpAddr) {
|
||||
storages.put(srcIpAddr, new InetSocketAddress(destIpAddr, 0));
|
||||
storages.put(destIpAddr, new InetSocketAddress(srcIpAddr, 0));
|
||||
}
|
||||
|
||||
public InetSocketAddress get(String ipAddr, int port) {
|
||||
if (this.without_port) {
|
||||
InetSocketAddress sockAddr;
|
||||
if ((sockAddr=storages.get(ipAddr)) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new InetSocketAddress(sockAddr.getAddress(), port);
|
||||
} else {
|
||||
return storages.get(this.getKey(ipAddr, port));
|
||||
}
|
||||
}
|
||||
|
||||
public InetSocketAddress get(InetSocketAddress sockAddr) {
|
||||
return this.get(sockAddr.getAddress().getHostAddress(), sockAddr.getPort());
|
||||
}
|
||||
}
|
||||
@@ -731,7 +731,6 @@ public class StorageClient {
|
||||
|
||||
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) {
|
||||
@@ -848,7 +847,6 @@ public class StorageClient {
|
||||
throw ex;
|
||||
} finally {
|
||||
releaseConnection(connection, bNewStorageServer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
package org.csource.fastdfs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import org.csource.common.MyException;
|
||||
import org.csource.fastdfs.pool.Connection;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
@@ -18,40 +21,112 @@ import java.net.InetSocketAddress;
|
||||
* @version Version 1.11
|
||||
*/
|
||||
public class StorageServer extends TrackerServer {
|
||||
protected int store_path_index = 0;
|
||||
protected int store_path_index = 0;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ip_addr the ip address of storage server
|
||||
* @param port the port of storage server
|
||||
* @param store_path the store path index on the storage server
|
||||
*/
|
||||
public StorageServer(String ip_addr, int port, int store_path) throws IOException {
|
||||
super(new InetSocketAddress(ip_addr, port));
|
||||
this.store_path_index = store_path;
|
||||
}
|
||||
protected static Hashtable<String, InetSocketAddress> sockAddressCache = new Hashtable<String, InetSocketAddress>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ip_addr the ip address of storage server
|
||||
* @param port the port of storage server
|
||||
* @param store_path the store path index on the storage server
|
||||
*/
|
||||
public StorageServer(String ip_addr, int port, byte store_path) throws IOException {
|
||||
super(new InetSocketAddress(ip_addr, port));
|
||||
if (store_path < 0) {
|
||||
this.store_path_index = 256 + store_path;
|
||||
} else {
|
||||
this.store_path_index = store_path;
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ip_addr the ip address of storage server
|
||||
* @param port the port of storage server
|
||||
* @param store_path the store path index on the storage server
|
||||
*/
|
||||
public StorageServer(String ip_addr, int port, int store_path) throws IOException {
|
||||
super(new InetSocketAddress(ip_addr, port));
|
||||
this.store_path_index = store_path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the store path index on the storage server
|
||||
*/
|
||||
public int getStorePathIndex() {
|
||||
return this.store_path_index;
|
||||
}
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ip_addr the ip address of storage server
|
||||
* @param port the port of storage server
|
||||
* @param store_path the store path index on the storage server
|
||||
*/
|
||||
public StorageServer(String ip_addr, int port, byte store_path) throws IOException {
|
||||
super(new InetSocketAddress(ip_addr, port));
|
||||
if (store_path < 0) {
|
||||
this.store_path_index = 256 + store_path;
|
||||
} else {
|
||||
this.store_path_index = store_path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the store path index on the storage server
|
||||
*/
|
||||
public int getStorePathIndex() {
|
||||
return this.store_path_index;
|
||||
}
|
||||
|
||||
public Connection getConnection() throws MyException, IOException {
|
||||
Connection connection;
|
||||
InetSocketAddress sockAddr;
|
||||
MyException myException = null;
|
||||
IOException ioException = null;
|
||||
|
||||
if (!ClientGlobal.g_multi_storage_ips) {
|
||||
return super.getConnection();
|
||||
}
|
||||
|
||||
if (ClientGlobal.g_connect_first_by == ClientGlobal.CONNECT_FIRST_BY_TRACKER) {
|
||||
try {
|
||||
if ((connection=super.getConnection()) != null) {
|
||||
return connection;
|
||||
}
|
||||
} catch (MyException ex1) {
|
||||
myException = ex1;
|
||||
} catch (IOException ex2) {
|
||||
ioException = ex2;
|
||||
}
|
||||
|
||||
sockAddr = ClientGlobal.g_storages_address_map.get(this.inetSockAddr);
|
||||
if (sockAddr != null) {
|
||||
return super.getConnection(sockAddr);
|
||||
} else if (myException != null) {
|
||||
throw myException;
|
||||
} else if (ioException != null) {
|
||||
throw ioException;
|
||||
}
|
||||
} else {
|
||||
String key = this.inetSockAddr.getAddress().getHostAddress() +
|
||||
"@" + this.inetSockAddr.getPort();
|
||||
sockAddr = sockAddressCache.get(key);
|
||||
try {
|
||||
if (sockAddr == null) {
|
||||
sockAddr = this.inetSockAddr;
|
||||
if ((connection=super.getConnection(sockAddr)) != null) {
|
||||
sockAddressCache.put(key, sockAddr);
|
||||
return connection;
|
||||
}
|
||||
} else {
|
||||
if ((connection=super.getConnection(sockAddr)) != null) {
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
} catch (MyException ex1) {
|
||||
myException = ex1;
|
||||
} catch (IOException ex2) {
|
||||
ioException = ex2;
|
||||
}
|
||||
|
||||
//retry another ip address
|
||||
if ((sockAddr=ClientGlobal.g_storages_address_map.get(sockAddr)) == null) {
|
||||
if (myException != null) {
|
||||
throw myException;
|
||||
} else if (ioException != null) {
|
||||
throw ioException;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((connection=super.getConnection(sockAddr)) != null) {
|
||||
sockAddressCache.put(key, sockAddr);
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class StructStorageStat extends StructBase {
|
||||
protected static final int FIELD_INDEX_ID = 1;
|
||||
protected static final int FIELD_INDEX_IP_ADDR = 2;
|
||||
protected static final int FIELD_INDEX_DOMAIN_NAME = 3;
|
||||
protected static final int FIELD_INDEX_SRC_IP_ADDR = 4;
|
||||
protected static final int FIELD_INDEX_SRC_ID = 4;
|
||||
protected static final int FIELD_INDEX_VERSION = 5;
|
||||
protected static final int FIELD_INDEX_JOIN_TIME = 6;
|
||||
protected static final int FIELD_INDEX_UP_TIME = 7;
|
||||
@@ -100,8 +100,8 @@ public class StructStorageStat extends StructBase {
|
||||
fieldsArray[FIELD_INDEX_DOMAIN_NAME] = new StructBase.FieldInfo("domainName", offset, ProtoCommon.FDFS_DOMAIN_NAME_MAX_SIZE);
|
||||
offset += ProtoCommon.FDFS_DOMAIN_NAME_MAX_SIZE;
|
||||
|
||||
fieldsArray[FIELD_INDEX_SRC_IP_ADDR] = new StructBase.FieldInfo("srcIpAddr", offset, ProtoCommon.FDFS_IPADDR_SIZE);
|
||||
offset += ProtoCommon.FDFS_IPADDR_SIZE;
|
||||
fieldsArray[FIELD_INDEX_SRC_ID] = new StructBase.FieldInfo("srcId", offset, ProtoCommon.FDFS_STORAGE_ID_MAX_SIZE);
|
||||
offset += ProtoCommon.FDFS_STORAGE_ID_MAX_SIZE;
|
||||
|
||||
fieldsArray[FIELD_INDEX_VERSION] = new StructBase.FieldInfo("version", offset, ProtoCommon.FDFS_VERSION_SIZE);
|
||||
offset += ProtoCommon.FDFS_VERSION_SIZE;
|
||||
@@ -280,7 +280,7 @@ public class StructStorageStat extends StructBase {
|
||||
protected byte status;
|
||||
protected String id;
|
||||
protected String ipAddr;
|
||||
protected String srcIpAddr;
|
||||
protected String srcId;
|
||||
protected String domainName; //http domain name
|
||||
protected String version;
|
||||
protected long totalMB; //total disk storage in MB
|
||||
@@ -377,12 +377,12 @@ public class StructStorageStat extends StructBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* get source storage ip address
|
||||
* get source storage id
|
||||
*
|
||||
* @return source storage ip address
|
||||
* @return source storage id
|
||||
*/
|
||||
public String getSrcIpAddr() {
|
||||
return this.srcIpAddr;
|
||||
public String getSrcId() {
|
||||
return this.srcId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -917,7 +917,7 @@ public class StructStorageStat extends StructBase {
|
||||
this.status = byteValue(bs, offset, fieldsArray[FIELD_INDEX_STATUS]);
|
||||
this.id = stringValue(bs, offset, fieldsArray[FIELD_INDEX_ID]);
|
||||
this.ipAddr = stringValue(bs, offset, fieldsArray[FIELD_INDEX_IP_ADDR]);
|
||||
this.srcIpAddr = stringValue(bs, offset, fieldsArray[FIELD_INDEX_SRC_IP_ADDR]);
|
||||
this.srcId = stringValue(bs, offset, fieldsArray[FIELD_INDEX_SRC_ID]);
|
||||
this.domainName = stringValue(bs, offset, fieldsArray[FIELD_INDEX_DOMAIN_NAME]);
|
||||
this.version = stringValue(bs, offset, fieldsArray[FIELD_INDEX_VERSION]);
|
||||
this.totalMB = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_MB]);
|
||||
|
||||
@@ -71,6 +71,71 @@ public class TrackerClient {
|
||||
return this.getStoreStorage(trackerServer, groupName);
|
||||
}
|
||||
|
||||
public Connection getConnection(TrackerServer trackerServer) throws IOException, MyException {
|
||||
Connection connection = null;
|
||||
int length = this.tracker_group.tracker_servers.length;
|
||||
boolean failOver = length > 1 && trackerServer == null;
|
||||
try {
|
||||
if (trackerServer == null) {
|
||||
trackerServer = getTrackerServer();
|
||||
if (trackerServer == null) {
|
||||
throw new MyException("tracker server is empty!");
|
||||
}
|
||||
}
|
||||
connection = trackerServer.getConnection();
|
||||
} catch (IOException e) {
|
||||
if (failOver) {
|
||||
System.err.println("trackerServer get connection error, emsg:" + e.getMessage());
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
} catch (MyException e) {
|
||||
if (failOver) {
|
||||
System.err.println("trackerServer get connection error, emsg:" + e.getMessage());
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (connection != null || !failOver) {
|
||||
return connection;
|
||||
}
|
||||
//do fail over
|
||||
int currentIndex = 0;
|
||||
if (trackerServer != null) {
|
||||
currentIndex = trackerServer.getIndex();
|
||||
}
|
||||
int failOverCount = 0;
|
||||
while (failOverCount < length - 1) {
|
||||
failOverCount++;
|
||||
currentIndex++;
|
||||
if (currentIndex >= length) {
|
||||
currentIndex = 0;
|
||||
}
|
||||
try {
|
||||
trackerServer = this.tracker_group.getTrackerServer(currentIndex);
|
||||
if (trackerServer == null) {
|
||||
throw new MyException("tracker server is empty!");
|
||||
}
|
||||
return trackerServer.getConnection();
|
||||
} catch (IOException e) {
|
||||
System.err.println("fail over trackerServer get connection error, failOverCount:" + failOverCount + "," + e.getMessage());
|
||||
if (failOverCount == length - 1) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
} catch (MyException e) {
|
||||
System.err.println("fail over trackerServer get connection error, failOverCount:" + failOverCount + ", " + e.getMessage());
|
||||
if (failOverCount == length - 1) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* query storage server to upload file
|
||||
*
|
||||
@@ -85,12 +150,7 @@ public class TrackerClient {
|
||||
byte cmd;
|
||||
int out_len;
|
||||
byte store_path;
|
||||
Connection connection;
|
||||
|
||||
if (trackerServer == null) {
|
||||
trackerServer = getTrackerServer();
|
||||
}
|
||||
connection = trackerServer.getConnection();
|
||||
Connection connection = getConnection(trackerServer);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
|
||||
try {
|
||||
@@ -170,16 +230,7 @@ public class TrackerClient {
|
||||
int port;
|
||||
byte cmd;
|
||||
int out_len;
|
||||
Connection connection;
|
||||
|
||||
if (trackerServer == null) {
|
||||
trackerServer = getTrackerServer();
|
||||
if (trackerServer == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
connection = trackerServer.getConnection();
|
||||
Connection connection = getConnection(trackerServer);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
|
||||
try {
|
||||
@@ -343,15 +394,7 @@ public class TrackerClient {
|
||||
int len;
|
||||
String ip_addr;
|
||||
int port;
|
||||
Connection connection;
|
||||
|
||||
if (trackerServer == null) {
|
||||
trackerServer = getTrackerServer();
|
||||
if (trackerServer == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
connection = trackerServer.getConnection();
|
||||
Connection connection = getConnection(trackerServer);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
|
||||
try {
|
||||
@@ -473,16 +516,7 @@ public class TrackerClient {
|
||||
byte cmd;
|
||||
int out_len;
|
||||
byte store_path;
|
||||
Connection connection;
|
||||
|
||||
if (trackerServer == null) {
|
||||
trackerServer = getTrackerServer();
|
||||
if (trackerServer == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
connection = trackerServer.getConnection();
|
||||
Connection connection = getConnection(trackerServer);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
|
||||
try {
|
||||
@@ -548,15 +582,7 @@ public class TrackerClient {
|
||||
byte[] bGroupName;
|
||||
byte[] bs;
|
||||
int len;
|
||||
Connection connection;
|
||||
|
||||
if (trackerServer == null) {
|
||||
trackerServer = getTrackerServer();
|
||||
if (trackerServer == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
connection = trackerServer.getConnection();
|
||||
Connection connection = getConnection(trackerServer);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
|
||||
try {
|
||||
@@ -709,8 +735,9 @@ public class TrackerClient {
|
||||
* @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 {
|
||||
public boolean deleteStorage(TrackerGroup trackerGroup, String groupName,
|
||||
String storageIpAddr) throws IOException, MyException
|
||||
{
|
||||
int serverIndex;
|
||||
int notFoundCount;
|
||||
TrackerServer trackerServer;
|
||||
@@ -779,4 +806,78 @@ public class TrackerClient {
|
||||
|
||||
return this.errno == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 StringBuilder fetchStorageIds() throws IOException, MyException {
|
||||
byte[] header;
|
||||
int offset = 0;
|
||||
int length;
|
||||
int total_count;
|
||||
int current_count;
|
||||
|
||||
Connection connection = getConnection(null);
|
||||
try {
|
||||
OutputStream out = connection.getOutputStream();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_FETCH_STORAGE_IDS, 5, (byte)0);
|
||||
byte[] wholePkg = new byte[header.length + 5];
|
||||
System.arraycopy(header, 0, wholePkg, 0, header.length);
|
||||
wholePkg[wholePkg.length - 1] = 1;
|
||||
do {
|
||||
byte[] bs = ProtoCommon.int2buff(offset);
|
||||
System.arraycopy(bs, 0, wholePkg, header.length, bs.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 < 8) {
|
||||
throw new MyException("invalid body length: " + pkgInfo.body.length);
|
||||
}
|
||||
|
||||
total_count = ProtoCommon.buff2int(pkgInfo.body, 0);
|
||||
current_count = ProtoCommon.buff2int(pkgInfo.body, 4);
|
||||
if (current_count < 0) {
|
||||
throw new MyException("invalid current count: " + current_count);
|
||||
}
|
||||
|
||||
length = pkgInfo.body.length - 8;
|
||||
if (length == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
bs = new byte[length];
|
||||
System.arraycopy(pkgInfo.body, 8, bs, 0, length);
|
||||
builder.append(new String(bs, ClientGlobal.g_charset));
|
||||
|
||||
offset += current_count;
|
||||
} while (offset < total_count);
|
||||
|
||||
return builder;
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
connection.close();
|
||||
} finally {
|
||||
connection = null;
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,84 +18,83 @@ import java.net.InetSocketAddress;
|
||||
* @version Version 1.17
|
||||
*/
|
||||
public class TrackerGroup {
|
||||
public int tracker_server_index;
|
||||
public InetSocketAddress[] tracker_servers;
|
||||
protected Integer lock;
|
||||
public int tracker_server_index;
|
||||
public InetSocketAddress[] tracker_servers;
|
||||
protected Integer lock;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param tracker_servers tracker servers
|
||||
*/
|
||||
public TrackerGroup(InetSocketAddress[] tracker_servers) {
|
||||
this.tracker_servers = tracker_servers;
|
||||
this.lock = new Integer(0);
|
||||
this.tracker_server_index = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* return connected tracker server
|
||||
*
|
||||
* @return connected tracker server, null for fail
|
||||
*/
|
||||
public TrackerServer getTrackerServer(int serverIndex) throws IOException {
|
||||
return new TrackerServer(this.tracker_servers[serverIndex]);
|
||||
}
|
||||
|
||||
/**
|
||||
* return connected tracker server
|
||||
*
|
||||
* @return connected tracker server, null for fail
|
||||
*/
|
||||
public TrackerServer getTrackerServer() throws IOException {
|
||||
int current_index;
|
||||
|
||||
synchronized (this.lock) {
|
||||
this.tracker_server_index++;
|
||||
if (this.tracker_server_index >= this.tracker_servers.length) {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param tracker_servers tracker servers
|
||||
*/
|
||||
public TrackerGroup(InetSocketAddress[] tracker_servers) {
|
||||
this.tracker_servers = tracker_servers;
|
||||
this.lock = new Integer(0);
|
||||
this.tracker_server_index = 0;
|
||||
}
|
||||
|
||||
current_index = this.tracker_server_index;
|
||||
}
|
||||
|
||||
try {
|
||||
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);
|
||||
/**
|
||||
* return connected tracker server
|
||||
*
|
||||
* @return connected tracker server, null for fail
|
||||
*/
|
||||
public TrackerServer getTrackerServer(int serverIndex) throws IOException {
|
||||
return new TrackerServer(this.tracker_servers[serverIndex], serverIndex);
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.tracker_servers.length; i++) {
|
||||
if (i == current_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
TrackerServer trackerServer = this.getTrackerServer(i);
|
||||
/**
|
||||
* return connected tracker server
|
||||
*
|
||||
* @return connected tracker server, null for fail
|
||||
*/
|
||||
public TrackerServer getTrackerServer() throws IOException {
|
||||
int current_index;
|
||||
|
||||
synchronized (this.lock) {
|
||||
if (this.tracker_server_index == current_index) {
|
||||
this.tracker_server_index = i;
|
||||
}
|
||||
this.tracker_server_index++;
|
||||
if (this.tracker_server_index >= this.tracker_servers.length) {
|
||||
this.tracker_server_index = 0;
|
||||
}
|
||||
|
||||
current_index = this.tracker_server_index;
|
||||
}
|
||||
|
||||
return trackerServer;
|
||||
} catch (IOException ex) {
|
||||
System.err.println("connect to server " + this.tracker_servers[i].getAddress().getHostAddress() + ":" + this.tracker_servers[i].getPort() + " fail");
|
||||
ex.printStackTrace(System.err);
|
||||
}
|
||||
try {
|
||||
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);
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.tracker_servers.length; i++) {
|
||||
if (i == current_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
TrackerServer trackerServer = this.getTrackerServer(i);
|
||||
|
||||
synchronized (this.lock) {
|
||||
if (this.tracker_server_index == current_index) {
|
||||
this.tracker_server_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return trackerServer;
|
||||
} catch (IOException ex) {
|
||||
System.err.println("connect to server " + this.tracker_servers[i].getAddress().getHostAddress() + ":" + this.tracker_servers[i].getPort() + " fail");
|
||||
ex.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public Object clone() {
|
||||
InetSocketAddress[] trackerServers = new InetSocketAddress[this.tracker_servers.length];
|
||||
for (int i = 0; i < trackerServers.length; i++) {
|
||||
trackerServers[i] = new InetSocketAddress(this.tracker_servers[i].getAddress().getHostAddress(), this.tracker_servers[i].getPort());
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
InetSocketAddress[] trackerServers = new InetSocketAddress[this.tracker_servers.length];
|
||||
for (int i = 0; i < trackerServers.length; i++) {
|
||||
trackerServers[i] = new InetSocketAddress(this.tracker_servers[i].getAddress().getHostAddress(), this.tracker_servers[i].getPort());
|
||||
return new TrackerGroup(trackerServers);
|
||||
}
|
||||
|
||||
return new TrackerGroup(trackerServers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,20 +25,32 @@ import java.net.InetSocketAddress;
|
||||
public class TrackerServer {
|
||||
protected InetSocketAddress inetSockAddr;
|
||||
|
||||
protected int index;
|
||||
|
||||
|
||||
public TrackerServer(InetSocketAddress inetSockAddr) throws IOException {
|
||||
this.inetSockAddr = inetSockAddr;
|
||||
}
|
||||
|
||||
public Connection getConnection() throws MyException, IOException {
|
||||
public TrackerServer(InetSocketAddress inetSockAddr, int index) {
|
||||
this.inetSockAddr = inetSockAddr;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
protected Connection getConnection(InetSocketAddress sockAddr) throws MyException, IOException {
|
||||
Connection connection;
|
||||
if (ClientGlobal.g_connection_pool_enabled) {
|
||||
connection = ConnectionPool.getConnection(this.inetSockAddr);
|
||||
connection = ConnectionPool.getConnection(sockAddr);
|
||||
} else {
|
||||
connection = ConnectionFactory.create(this.inetSockAddr);
|
||||
connection = ConnectionFactory.create(sockAddr);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
public Connection getConnection() throws MyException, IOException {
|
||||
return this.getConnection(this.inetSockAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the server info
|
||||
*
|
||||
@@ -48,4 +60,11 @@ public class TrackerServer {
|
||||
return this.inetSockAddr;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ public class Connection {
|
||||
private InetSocketAddress inetSockAddr;
|
||||
private Long lastAccessTime = System.currentTimeMillis();
|
||||
|
||||
private boolean needActiveTest = false;
|
||||
|
||||
public Connection(Socket sock, InetSocketAddress inetSockAddr) {
|
||||
this.sock = sock;
|
||||
this.inetSockAddr = inetSockAddr;
|
||||
@@ -117,11 +119,21 @@ public class Connection {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isNeedActiveTest() {
|
||||
return needActiveTest;
|
||||
}
|
||||
|
||||
public void setNeedActiveTest(boolean needActiveTest) {
|
||||
this.needActiveTest = needActiveTest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TrackerServer{" +
|
||||
return "Connection{" +
|
||||
"sock=" + sock +
|
||||
", inetSockAddr=" + inetSockAddr +
|
||||
", lastAccessTime=" + lastAccessTime +
|
||||
", needActiveTest=" + needActiveTest +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,21 @@ public class ConnectionManager {
|
||||
closeConnection(connection);
|
||||
continue;
|
||||
}
|
||||
if (connection.isNeedActiveTest()) {
|
||||
boolean isActive = false;
|
||||
try {
|
||||
isActive = connection.activeTest();
|
||||
} catch (IOException e) {
|
||||
System.err.println("send to server[" + inetSocketAddress.getAddress().getHostAddress() + ":" + inetSocketAddress.getPort() + "] active test error ,emsg:" + e.getMessage());
|
||||
isActive = false;
|
||||
}
|
||||
if (!isActive) {
|
||||
closeConnection(connection);
|
||||
continue;
|
||||
} else {
|
||||
connection.setNeedActiveTest(false);
|
||||
}
|
||||
}
|
||||
} else if (ClientGlobal.g_connection_pool_max_count_per_entry == 0 || totalCount.get() < ClientGlobal.g_connection_pool_max_count_per_entry) {
|
||||
connection = ConnectionFactory.create(this.inetSocketAddress);
|
||||
totalCount.incrementAndGet();
|
||||
@@ -107,6 +122,20 @@ public class ConnectionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void setActiveTestFlag() {
|
||||
if (freeCount.get() > 0) {
|
||||
lock.lock();
|
||||
try {
|
||||
for (Connection freeConnection : freeConnections) {
|
||||
freeConnection.setNeedActiveTest(true);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConnectionManager{" +
|
||||
|
||||
@@ -54,6 +54,7 @@ public class ConnectionPool {
|
||||
ConnectionManager connectionManager = CP.get(key);
|
||||
if (connectionManager != null) {
|
||||
connectionManager.closeConnection(connection);
|
||||
connectionManager.setActiveTestFlag();
|
||||
} else {
|
||||
connection.closeDirectly();
|
||||
}
|
||||
|
||||
@@ -9,8 +9,23 @@ fastdfs.http_anti_steal_token = false
|
||||
fastdfs.http_secret_key = FastDFS1234567890
|
||||
fastdfs.http_tracker_http_port = 80
|
||||
|
||||
#tracker_server
|
||||
# IPv4:
|
||||
# for example: 192.168.2.100:22122,122.244.141.46:22122
|
||||
#
|
||||
# IPv6:
|
||||
# for example: [2409:8a20:42d:2f40:587a:4c47:72c0:ad8e]:22122
|
||||
#
|
||||
fastdfs.tracker_servers = 185.245.40.70:22122
|
||||
|
||||
|
||||
# connect which ip address first for multi IPs of a storage server, value list:
|
||||
## tracker: connect to the ip address return by tracker server first
|
||||
## last-connected: connect to the ip address last connected first
|
||||
# default value is tracker
|
||||
fastdfs.connect_first_by = tracker
|
||||
|
||||
|
||||
## Whether to open the connection pool, if not, create a new connection every time
|
||||
fastdfs.connection_pool.enabled = true
|
||||
|
||||
@@ -21,4 +36,4 @@ fastdfs.connection_pool.max_count_per_entry = 500
|
||||
fastdfs.connection_pool.max_idle_time = 3600
|
||||
|
||||
## Maximum waiting time when the maximum number of connections is reached, unit: millisecond, default value is 1000
|
||||
fastdfs.connection_pool.max_wait_time_in_ms = 1000
|
||||
fastdfs.connection_pool.max_wait_time_in_ms = 1000
|
||||
|
||||
@@ -5,10 +5,25 @@ http.tracker_http_port = 8080
|
||||
http.anti_steal_token = no
|
||||
http.secret_key = FastDFS1234567890
|
||||
|
||||
#tracker_server
|
||||
# IPv4:
|
||||
# for example: 192.168.2.100,122.244.141.46:22122
|
||||
#
|
||||
# IPv6:
|
||||
# for example: [2409:8a20:42d:2f40:587a:4c47:72c0:ad8e]:22122
|
||||
#
|
||||
tracker_server = 10.0.11.243:22122
|
||||
tracker_server = 10.0.11.244:22122
|
||||
|
||||
|
||||
# connect which ip address first for multi IPs of a storage server, value list:
|
||||
## tracker: connect to the ip address return by tracker server first
|
||||
## last-connected: connect to the ip address last connected first
|
||||
# default value is tracker
|
||||
connect_first_by = tracker
|
||||
|
||||
|
||||
connection_pool.enabled = true
|
||||
connection_pool.max_count_per_entry = 500
|
||||
connection_pool.max_idle_time = 3600
|
||||
connection_pool.max_wait_time_in_ms = 1000
|
||||
connection_pool.max_wait_time_in_ms = 1000
|
||||
|
||||
@@ -21,6 +21,9 @@ public class ClientGlobalTests {
|
||||
ClientGlobal.initByProperties(props);
|
||||
System.out.println("ClientGlobal.configInfo(): " + ClientGlobal.configInfo());
|
||||
|
||||
String trackerServer = "www.baidu.com:22122";
|
||||
ClientGlobal.initByTrackers(trackerServer);
|
||||
System.out.println("Host >>> ClientGlobal.configInfo() : " + ClientGlobal.configInfo());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -87,9 +87,9 @@ public class FdfsTest {
|
||||
|
||||
@Test
|
||||
public void download() throws Exception {
|
||||
String[] uploadresult = {"group1", "M00/00/00/wKgBZV0phl2ASV1nAACk1tFxwrM3814331"};
|
||||
String[] uploadresult = {"group1", "M00/00/00/J2fL12PVypeAWiGcAAM_gDeWVyw5817085"};
|
||||
byte[] result = storageClient.download_file(uploadresult[0], uploadresult[1]);
|
||||
String local_filename = "build.PNG";
|
||||
String local_filename = "commitment.d2f57e10.jpg";
|
||||
writeByteToFile(result, local_filename);
|
||||
File file = new File(local_filename);
|
||||
Assert.assertTrue(file.isFile());
|
||||
@@ -98,17 +98,17 @@ public class FdfsTest {
|
||||
@Test
|
||||
public void testUploadDownload() throws Exception {
|
||||
NameValuePair[] metaList = new NameValuePair[1];
|
||||
String local_filename = "build.PNG";
|
||||
String local_filename = "commitment.d2f57e10 (2).jpg";
|
||||
metaList[0] = new NameValuePair("fileName", local_filename);
|
||||
File file = new File("C:/Users/chengdu/Desktop/build.PNG");
|
||||
File file = new File("/Users/iyw/Downloads/commitment.d2f57e10 (2).jpg");
|
||||
InputStream inputStream = new FileInputStream(file);
|
||||
int length = inputStream.available();
|
||||
byte[] bytes = new byte[length];
|
||||
inputStream.read(bytes);
|
||||
String[] result = storageClient.upload_file(bytes, null, metaList);
|
||||
Assert.assertTrue(storageClient.isConnected());
|
||||
//Assert.assertTrue(storageClient.isConnected());
|
||||
// pool testOnborrow isAvaliable
|
||||
Assert.assertTrue(storageClient.isAvaliable());
|
||||
// Assert.assertTrue(storageClient.isAvaliable());
|
||||
LOGGER.info("result {}", Arrays.asList(result));
|
||||
byte[] resultbytes = storageClient.download_file(result[0], result[1]);
|
||||
writeByteToFile(resultbytes, local_filename);
|
||||
|
||||
@@ -106,7 +106,7 @@ public class Monitor {
|
||||
System.out.println("\t\tstorage_port = " + storageStat.getStoragePort());
|
||||
System.out.println("\t\tstorage_http_port = " + storageStat.getStorageHttpPort());
|
||||
System.out.println("\t\tcurrent_write_path = " + storageStat.getCurrentWritePath());
|
||||
System.out.println("\t\tsource ip_addr = " + storageStat.getSrcIpAddr());
|
||||
System.out.println("\t\tsource ip_id = " + storageStat.getSrcId());
|
||||
System.out.println("\t\tif_trunk_server = " + storageStat.isTrunkServer());
|
||||
System.out.println("\t\tconntion.alloc_count = " + storageStat.getConnectionAllocCount());
|
||||
System.out.println("\t\tconntion.current_count = " + storageStat.getConnectionCurrentCount());
|
||||
|
||||
Reference in New Issue
Block a user