分析一下FastDFS_java_client中TestClient.java这个文件以及跟它关联的这条线
本来先打算上个图来说明一下这条线的,可是我的画图工具还没有安装好,我先把跟TestClient.java相关的几个文件代码贴上来,但是由于代码行数还是不少的,所以请大家阅读文章的时候先不要展开代码,等读到有关代码解释的时候再返回去查看。代码源自FastDFS老大鱼大大的。
TestClient.java:
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/
package org.csource.fastdfs.test;
import java.io.*;
import java.net.*;
import java.util.*;
import org.csource.common.*;
import org.csource.fastdfs.*;
/**
* client test
* @author Happy Fish / YuQing
* @version Version 1.18
*/
public class TestClient
{
private TestClient()
{
}
/**
* entry point
* @param args comand arguments
* <ul><li>args[0]: config filename</li></ul>
* <ul><li>args[1]: local filename to upload</li></ul>
*/
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;
}
System.out.println("java.version=" + System.getProperty("java.version"));
String conf_filename = args[0];
String local_filename = args[1];
try
{
ClientGlobal.init(conf_filename);
System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms");
System.out.println("charset=" + ClientGlobal.g_charset);
long startTime;
String group_name;
String remote_filename;
ServerInfo[] servers;
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;
/*
storageServer = tracker.getStoreStorage(trackerServer);
if (storageServer == null)
{
System.out.println("getStoreStorage fail, error code: " + tracker.getErrorCode());
return;
}
*/
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");
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("");
}
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));
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: " + 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();
}
}
}
ClientGlobal.java:
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/
package org.csource.fastdfs;
import java.net.*;
import java.io.*;
import java.net.*;
import org.csource.common.*;
/**
* Global variables
* @author Happy Fish / YuQing
* @version Version 1.11
*/
public class ClientGlobal
{
public static int g_connect_timeout; //millisecond
public static int g_network_timeout; //millisecond
public static String g_charset;
public static int g_tracker_http_port;
public static boolean g_anti_steal_token; //if anti-steal token
public static String g_secret_key; //generage token secret key
public static TrackerGroup g_tracker_group;
public static final int DEFAULT_CONNECT_TIMEOUT = 5; //second
public static final int DEFAULT_NETWORK_TIMEOUT = 30; //second
private ClientGlobal()
{
}
/**
* load global variables
* @param conf_filename config filename
*/
public static void init(String conf_filename) throws FileNotFoundException, IOException, MyException
{
IniFileReader iniReader;
String[] szTrackerServers;
String[] parts;
iniReader = new IniFileReader(conf_filename);
g_connect_timeout = iniReader.getIntValue("connect_timeout", DEFAULT_CONNECT_TIMEOUT);
if (g_connect_timeout < 0)
{
g_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
}
g_connect_timeout *= 1000; //millisecond
g_network_timeout = iniReader.getIntValue("network_timeout", DEFAULT_NETWORK_TIMEOUT);
if (g_network_timeout < 0)
{
g_network_timeout = DEFAULT_NETWORK_TIMEOUT;
}
g_network_timeout *= 1000; //millisecond
g_charset = iniReader.getStrValue("charset");
if (g_charset == null || g_charset.length() == 0)
{
g_charset = "ISO8859-1";
}
szTrackerServers = iniReader.getValues("tracker_server");
if (szTrackerServers == null)
{
throw new MyException("item \"tracker_server\" in " + conf_filename + " not found");
}
InetSocketAddress[] tracker_servers = new InetSocketAddress[szTrackerServers.length];
for (int i=0; i<szTrackerServers.length; i++)
{
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()));
}
g_tracker_group = new TrackerGroup(tracker_servers);
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)
{
g_secret_key = iniReader.getStrValue("http.secret_key");
}
}
/**
* construct Socket object
* @param ip_addr ip address or hostname
* @param port port number
* @return connected Socket object
*/
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);
return sock;
}
/**
* construct Socket object
* @param addr InetSocketAddress object, including ip address and port
* @return connected Socket object
*/
public static Socket getSocket(InetSocketAddress addr) throws IOException
{
Socket sock = new Socket();
sock.setSoTimeout(ClientGlobal.g_network_timeout);
sock.connect(addr, ClientGlobal.g_connect_timeout);
return sock;
}
public static int getG_connect_timeout()
{
return g_connect_timeout;
}
public static void setG_connect_timeout(int connect_timeout)
{
ClientGlobal.g_connect_timeout = connect_timeout;
}
public static int getG_network_timeout()
{
return g_network_timeout;
}
public static void setG_network_timeout(int network_timeout)
{
ClientGlobal.g_network_timeout = network_timeout;
}
public static String getG_charset()
{
return g_charset;
}
public static void setG_charset(String charset)
{
ClientGlobal.g_charset = charset;
}
public static int getG_tracker_http_port()
{
return g_tracker_http_port;
}
public static void setG_tracker_http_port(int tracker_http_port)
{
ClientGlobal.g_tracker_http_port = tracker_http_port;
}
public static boolean getG_anti_steal_token()
{
return g_anti_steal_token;
}
public static boolean isG_anti_steal_token()
{
return g_anti_steal_token;
}
public static void setG_anti_steal_token(boolean anti_steal_token)
{
ClientGlobal.g_anti_steal_token = anti_steal_token;
}
public static String getG_secret_key()
{
return g_secret_key;
}
public static void setG_secret_key(String secret_key)
{
ClientGlobal.g_secret_key = secret_key;
}
public static TrackerGroup getG_tracker_group()
{
return g_tracker_group;
}
public static void setG_tracker_group(TrackerGroup tracker_group)
{
ClientGlobal.g_tracker_group = tracker_group;
}
}
TrackerClient.java:
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
*/
package org.csource.fastdfs;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.net.Socket;
/**
* Tracker client
* @author Happy Fish / YuQing
* @version Version 1.19
*/
public class TrackerClient
{
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;
}
trackerSocket = trackerServer.getSocket();
OutputStream out = trackerSocket.getOutputStream();
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);
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,
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<StructGroupStat> decoder = new ProtoStructDecoder<StructGroupStat>();
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<StructStorageStat> decoder = new ProtoStructDecoder<StructStorageStat>();
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;
}
}
}
}
finally
{
try
{
trackerServer.close();
}
catch(IOException ex1)
{
ex1.printStackTrace();
}
}
}
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;
}
}
TrackerGroup.java:
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
*/
package org.csource.fastdfs;
import java.io.*;
import java.util.*;
import java.net.*;
import org.csource.common.*;
/**
* Tracker server group
* @author Happy Fish / YuQing
* @version Version 1.17
*/
public class TrackerGroup
{
protected Integer lock;
public int tracker_server_index;
public InetSocketAddress[] tracker_servers;
/**
* 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 getConnection(int serverIndex) throws IOException
{
Socket sock = new Socket();
sock.setReuseAddress(true);
sock.setSoTimeout(ClientGlobal.g_network_timeout);
sock.connect(this.tracker_servers[serverIndex], ClientGlobal.g_connect_timeout);
return new TrackerServer(sock, this.tracker_servers[serverIndex]);
}
/**
* return connected tracker server
* @return connected tracker server, null for fail
*/
public TrackerServer getConnection() throws IOException
{
int current_index;
synchronized(this.lock)
{
this.tracker_server_index++;
if (this.tracker_server_index >= this.tracker_servers.length)
{
this.tracker_server_index = 0;
}
current_index = this.tracker_server_index;
}
try
{
return this.getConnection(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.getConnection(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;
}
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);
}
}
StorageClient.java:
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
*/
package org.csource.fastdfs;
import java.io.IOException;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.File;
import java.util.Arrays;
import java.net.Socket;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.common.Base64;
/**
* Storage client for 2 fields file id: group name and filename
* @author Happy Fish / YuQing
* @version Version 1.24
*/
public class StorageClient
{
/**
* 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;
}
}
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 and storage server
* @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:<br>
* <ul><li>results[0]: the group name to store the file </li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file </li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file </li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file </li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file </li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file </li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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:<br>
* <ul><li>results[0]: the group name to store the file</li></ul>
* <ul><li>results[1]: the new created filename</li></ul>
* 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);
}
/**
* 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:<br>
* <ul><li> results[0]: the group name to store the file</li></ul>
* <ul><li> results[1]: the new created filename</li></ul>
* 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: <br>
* <ul><li> ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE: overwrite all old
* metadata items</li></ul>
* <ul><li> ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE: merge, insert when
* the metadata item not exist, otherwise update it</li></ul>
* @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));
long file_size = ProtoCommon.buff2long(buff, 4 * 2);
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_size & ProtoCommon.APPENDER_FILE_SIZE) != 0))
{ //slave file or appender file
FileInfo fi = this.query_file_info(group_name, remote_filename);
if (fi == null)
{
return null;
}
return fi;
}
FileInfo fileInfo = new FileInfo(file_size, 0, 0, ProtoCommon.getIpAddress(buff, 0));
fileInfo.setCreateTimestamp(ProtoCommon.buff2int(buff, 4));
if ((file_size >> 63) != 0)
{
file_size &= 0xFFFFFFFFL; //low 32 bits is file size
fileInfo.setFileSize(file_size);
}
fileInfo.setCrc32(ProtoCommon.buff2int(buff, 4 * 4));
return fileInfo;
}
/**
* 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(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);
}
}
ProtoCommon.java:
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/
package org.csource.fastdfs;
import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.net.Socket;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
/**
* protocol common functions
* @author Happy Fish / YuQing
* @version Version 1.18
*/
public class ProtoCommon
{
/**
* receive package info
*/
public static class RecvPackageInfo
{
public byte errno;
public byte[] body;
public RecvPackageInfo(byte errno, byte[] body)
{
this.errno = errno;
this.body = body;
}
}
/**
* receive header info
*/
public static class RecvHeaderInfo
{
public byte errno;
public long body_len;
public RecvHeaderInfo(byte errno, long body_len)
{
this.errno = errno;
this.body_len = body_len;
}
}
public static final byte FDFS_PROTO_CMD_QUIT = 82;
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;
public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE = 101;
public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE = 102;
public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE = 103;
public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE = 104;
public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL = 105;
public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL = 106;
public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL = 107;
public static final byte TRACKER_PROTO_CMD_RESP = 100;
public static final byte FDFS_PROTO_CMD_ACTIVE_TEST = 111;
public static final byte STORAGE_PROTO_CMD_UPLOAD_FILE = 11;
public static final byte STORAGE_PROTO_CMD_DELETE_FILE = 12;
public static final byte STORAGE_PROTO_CMD_SET_METADATA = 13;
public static final byte STORAGE_PROTO_CMD_DOWNLOAD_FILE = 14;
public static final byte STORAGE_PROTO_CMD_GET_METADATA = 15;
public static final byte STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE = 21;
public static final byte STORAGE_PROTO_CMD_QUERY_FILE_INFO = 22;
public static final byte STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE= 23; //create appender file
public static final byte STORAGE_PROTO_CMD_APPEND_FILE = 24; //append file
public static final byte STORAGE_PROTO_CMD_MODIFY_FILE = 34; //modify appender file
public static final byte STORAGE_PROTO_CMD_TRUNCATE_FILE = 36; //truncate appender file
public static final byte STORAGE_PROTO_CMD_RESP = TRACKER_PROTO_CMD_RESP;
public static final byte FDFS_STORAGE_STATUS_INIT = 0;
public static final byte FDFS_STORAGE_STATUS_WAIT_SYNC = 1;
public static final byte FDFS_STORAGE_STATUS_SYNCING = 2;
public static final byte FDFS_STORAGE_STATUS_IP_CHANGED = 3;
public static final byte FDFS_STORAGE_STATUS_DELETED = 4;
public static final byte FDFS_STORAGE_STATUS_OFFLINE = 5;
public static final byte FDFS_STORAGE_STATUS_ONLINE = 6;
public static final byte FDFS_STORAGE_STATUS_ACTIVE = 7;
public static final byte FDFS_STORAGE_STATUS_NONE = 99;
/**
* for overwrite all old metadata
*/
public static final byte STORAGE_SET_METADATA_FLAG_OVERWRITE = 'O';
/**
* for replace, insert when the meta item not exist, otherwise update it
*/
public static final byte STORAGE_SET_METADATA_FLAG_MERGE = 'M';
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_DOMAIN_NAME_MAX_SIZE = 128;
public static final int FDFS_VERSION_SIZE = 6;
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";
public static final int TRACKER_QUERY_STORAGE_FETCH_BODY_LEN = FDFS_GROUP_NAME_MAX_LEN
+ FDFS_IPADDR_SIZE - 1 + FDFS_PROTO_PKG_LEN_SIZE;
public static final int TRACKER_QUERY_STORAGE_STORE_BODY_LEN = FDFS_GROUP_NAME_MAX_LEN
+ FDFS_IPADDR_SIZE + FDFS_PROTO_PKG_LEN_SIZE;
protected static final int PROTO_HEADER_CMD_INDEX = FDFS_PROTO_PKG_LEN_SIZE;
protected static final int PROTO_HEADER_STATUS_INDEX = FDFS_PROTO_PKG_LEN_SIZE+1;
public static final byte FDFS_FILE_EXT_NAME_MAX_LEN = 6;
public static final byte FDFS_FILE_PREFIX_MAX_LEN = 16;
public static final byte FDFS_FILE_PATH_LEN = 10;
public static final byte FDFS_FILENAME_BASE64_LENGTH = 27;
public static final byte FDFS_TRUNK_FILE_INFO_LEN = 16;
public static final byte ERR_NO_ENOENT = 2;
public static final byte ERR_NO_EIO = 5;
public static final byte ERR_NO_EBUSY = 16;
public static final byte ERR_NO_EINVAL = 22;
public static final byte ERR_NO_ENOSPC = 28;
public static final byte ECONNREFUSED = 61;
public static final byte ERR_NO_EALREADY = 114;
public static final long INFINITE_FILE_SIZE = 256 * 1024L * 1024 * 1024 * 1024 * 1024L;
public static final long APPENDER_FILE_SIZE = INFINITE_FILE_SIZE;
public static final long TRUNK_FILE_MARK_SIZE = 512 * 1024L * 1024 * 1024 * 1024 * 1024L;
public static final long NORMAL_LOGIC_FILENAME_LENGTH = FDFS_FILE_PATH_LEN + FDFS_FILENAME_BASE64_LENGTH + FDFS_FILE_EXT_NAME_MAX_LEN + 1;
public static final long TRUNK_LOGIC_FILENAME_LENGTH = NORMAL_LOGIC_FILENAME_LENGTH + FDFS_TRUNK_FILE_INFO_LEN;
private ProtoCommon()
{
}
public static String getStorageStatusCaption(byte status)
{
switch(status)
{
case FDFS_STORAGE_STATUS_INIT:
return "INIT";
case FDFS_STORAGE_STATUS_WAIT_SYNC:
return "WAIT_SYNC";
case FDFS_STORAGE_STATUS_SYNCING:
return "SYNCING";
case FDFS_STORAGE_STATUS_IP_CHANGED:
return "IP_CHANGED";
case FDFS_STORAGE_STATUS_DELETED:
return "DELETED";
case FDFS_STORAGE_STATUS_OFFLINE:
return "OFFLINE";
case FDFS_STORAGE_STATUS_ONLINE:
return "ONLINE";
case FDFS_STORAGE_STATUS_ACTIVE:
return "ACTIVE";
case FDFS_STORAGE_STATUS_NONE:
return "NONE";
default:
return "UNKOWN";
}
}
/**
* pack header by FastDFS transfer protocol
* @param cmd which command to send
* @param pkg_len package body length
* @param errno status code, should be (byte)0
* @return packed byte buffer
*/
public static byte[] packHeader(byte cmd, long pkg_len, byte errno) throws UnsupportedEncodingException
{
byte[] header;
byte[] hex_len;
header = new byte[FDFS_PROTO_PKG_LEN_SIZE + 2];
Arrays.fill(header, (byte)0);
hex_len = ProtoCommon.long2buff(pkg_len);
System.arraycopy(hex_len, 0, header, 0, hex_len.length);
header[PROTO_HEADER_CMD_INDEX] = cmd;
header[PROTO_HEADER_STATUS_INDEX] = errno;
return header;
}
/**
* receive pack header
* @param in input stream
* @param expect_cmd expect response command
* @param expect_body_len expect response package body length
* @return RecvHeaderInfo: errno and pkg body length
*/
public static RecvHeaderInfo recvHeader(InputStream in, byte expect_cmd, long expect_body_len) throws IOException
{
byte[] header;
int bytes;
long pkg_len;
header = new byte[FDFS_PROTO_PKG_LEN_SIZE + 2];
if ((bytes=in.read(header)) != header.length)
{
throw new IOException("recv package size " + bytes + " != " + header.length);
}
if (header[PROTO_HEADER_CMD_INDEX] != expect_cmd)
{
throw new IOException("recv cmd: " + header[PROTO_HEADER_CMD_INDEX] + " is not correct, expect cmd: " + expect_cmd);
}
if (header[PROTO_HEADER_STATUS_INDEX] != 0)
{
return new RecvHeaderInfo(header[PROTO_HEADER_STATUS_INDEX], 0);
}
pkg_len = ProtoCommon.buff2long(header, 0);
if (pkg_len < 0)
{
throw new IOException("recv body length: " + pkg_len + " < 0!");
}
if (expect_body_len >= 0 && pkg_len != expect_body_len)
{
throw new IOException("recv body length: " + pkg_len + " is not correct, expect length: " + expect_body_len);
}
return new RecvHeaderInfo((byte)0, pkg_len);
}
/**
* receive whole pack
* @param in input stream
* @param expect_cmd expect response command
* @param expect_body_len expect response package body length
* @return RecvPackageInfo: errno and reponse body(byte buff)
*/
public static RecvPackageInfo recvPackage(InputStream in, byte expect_cmd, long expect_body_len) throws IOException
{
RecvHeaderInfo header = recvHeader(in, expect_cmd, expect_body_len);
if (header.errno != 0)
{
return new RecvPackageInfo(header.errno, null);
}
byte[] body = new byte[(int)header.body_len];
int totalBytes = 0;
int remainBytes = (int)header.body_len;
int bytes;
while (totalBytes < header.body_len)
{
if ((bytes=in.read(body, totalBytes, remainBytes)) < 0)
{
break;
}
totalBytes += bytes;
remainBytes -= bytes;
}
if (totalBytes != header.body_len)
{
throw new IOException("recv package size " + totalBytes + " != " + header.body_len);
}
return new RecvPackageInfo((byte)0, body);
}
/**
* split metadata to name value pair array
* @param meta_buff metadata
* @return name value pair array
*/
public static NameValuePair[] split_metadata(String meta_buff)
{
return split_metadata(meta_buff, FDFS_RECORD_SEPERATOR, FDFS_FIELD_SEPERATOR);
}
/**
* split metadata to name value pair array
* @param meta_buff metadata
* @param recordSeperator record/row seperator
* @param filedSeperator field/column seperator
* @return name value pair array
*/
public static NameValuePair[] split_metadata(String meta_buff,
String recordSeperator, String filedSeperator)
{
String[] rows;
String[] cols;
NameValuePair[] meta_list;
rows = meta_buff.split(recordSeperator);
meta_list = new NameValuePair[rows.length];
for (int i=0; i<rows.length; i++)
{
cols = rows[i].split(filedSeperator, 2);
meta_list[i] = new NameValuePair(cols[0]);
if (cols.length == 2)
{
meta_list[i].setValue(cols[1]);
}
}
return meta_list;
}
/**
* pack metadata array to string
* @param meta_list metadata array
* @return packed metadata
*/
public static String pack_metadata(NameValuePair[] meta_list)
{
if (meta_list.length == 0)
{
return "";
}
StringBuffer sb = new StringBuffer(32 * meta_list.length);
sb.append(meta_list[0].getName()).append(FDFS_FIELD_SEPERATOR).append(meta_list[0].getValue());
for (int i=1; i<meta_list.length; i++)
{
sb.append(FDFS_RECORD_SEPERATOR);
sb.append(meta_list[i].getName()).append(FDFS_FIELD_SEPERATOR).append(meta_list[i].getValue());
}
return sb.toString();
}
/**
* send quit command to server and close socket
* @param sock the Socket object
*/
public static void closeSocket(Socket sock) throws IOException
{
byte[] header;
header = packHeader(FDFS_PROTO_CMD_QUIT, 0, (byte)0);
sock.getOutputStream().write(header);
sock.close();
}
/**
* send ACTIVE_TEST command to server, test if network is ok and the server is alive
* @param sock the Socket object
*/
public static boolean activeTest(Socket sock) throws IOException
{
byte[] header;
header = packHeader(FDFS_PROTO_CMD_ACTIVE_TEST, 0, (byte)0);
sock.getOutputStream().write(header);
RecvHeaderInfo headerInfo = recvHeader(sock.getInputStream(), TRACKER_PROTO_CMD_RESP, 0);
return headerInfo.errno == 0 ? true : false;
}
/**
* long convert to buff (big-endian)
* @param n long number
* @return 8 bytes buff
*/
public static byte[] long2buff(long n)
{
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;
}
/**
* buff convert to long
* @param bs the buffer (big-endian)
* @param offset the start position based 0
* @return long number
*/
public static long buff2long(byte[] bs, int offset)
{
return (((long)(bs[offset] >= 0 ? bs[offset] : 256+bs[offset])) << 56) |
(((long)(bs[offset+1] >= 0 ? bs[offset+1] : 256+bs[offset+1])) << 48) |
(((long)(bs[offset+2] >= 0 ? bs[offset+2] : 256+bs[offset+2])) << 40) |
(((long)(bs[offset+3] >= 0 ? bs[offset+3] : 256+bs[offset+3])) << 32) |
(((long)(bs[offset+4] >= 0 ? bs[offset+4] : 256+bs[offset+4])) << 24) |
(((long)(bs[offset+5] >= 0 ? bs[offset+5] : 256+bs[offset+5])) << 16) |
(((long)(bs[offset+6] >= 0 ? bs[offset+6] : 256+bs[offset+6])) << 8) |
((long)(bs[offset+7] >= 0 ? bs[offset+7] : 256+bs[offset+7]));
}
/**
* buff convert to int
* @param bs the buffer (big-endian)
* @param offset the start position based 0
* @return int number
*/
public static int buff2int(byte[] bs, int offset)
{
return (((int)(bs[offset] >= 0 ? bs[offset] : 256+bs[offset])) << 24) |
(((int)(bs[offset+1] >= 0 ? bs[offset+1] : 256+bs[offset+1])) << 16) |
(((int)(bs[offset+2] >= 0 ? bs[offset+2] : 256+bs[offset+2])) << 8) |
((int)(bs[offset+3] >= 0 ? bs[offset+3] : 256+bs[offset+3]));
}
/**
* buff convert to ip address
* @param bs the buffer (big-endian)
* @param offset the start position based 0
* @return ip address
*/
public static String getIpAddress(byte[] bs, int offset)
{
if (bs[0] == 0 || bs[3] == 0) //storage server ID
{
return "";
}
int n;
StringBuilder sbResult = new StringBuilder(16);
for (int i=offset; i<offset+4; i++)
{
n = (bs[i] >= 0) ? bs[i] : 256 + bs[i];
if (sbResult.length() > 0)
{
sbResult.append(".");
}
sbResult.append(String.valueOf(n));
}
return sbResult.toString();
}
/**
* md5 function
* @param source the input buffer
* @return md5 string
*/
public static String md5(byte[] source) throws NoSuchAlgorithmException
{
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
md.update(source);
byte tmp[] = md.digest();
char str[] = new char[32];
int k = 0;
for (int i = 0; i < 16; i++)
{
str[k++] = hexDigits[tmp[i] >>> 4 & 0xf];
str[k++] = hexDigits[tmp[i] & 0xf];
}
return new String(str);
}
/**
* get token for file URL
* @param remote_filename the filename return by FastDFS server
* @param ts unix timestamp, unit: second
* @param secret_key the secret key
* @return token string
*/
public static String getToken(String remote_filename, int ts, String secret_key) throws UnsupportedEncodingException, NoSuchAlgorithmException, MyException
{
byte[] bsFilename = remote_filename.getBytes(ClientGlobal.g_charset);
byte[] bsKey = secret_key.getBytes(ClientGlobal.g_charset);
byte[] bsTimestamp = (new Integer(ts)).toString().getBytes(ClientGlobal.g_charset);
byte[] buff = new byte[bsFilename.length + bsKey.length + bsTimestamp.length];
System.arraycopy(bsFilename, 0, buff, 0, bsFilename.length);
System.arraycopy(bsKey, 0, buff, bsFilename.length, bsKey.length);
System.arraycopy(bsTimestamp, 0, buff, bsFilename.length + bsKey.length, bsTimestamp.length);
return md5(buff);
}
/**
* generate slave filename
* @param master_filename the master filename to generate the slave filename
* @param prefix_name the prefix name to generate the slave filename
* @param ext_name the extension name of slave filename, null for same as the master extension name
* @return slave filename string
*/
public static String genSlaveFilename(String master_filename,
String prefix_name, String ext_name) throws MyException
{
String true_ext_name;
int dotIndex;
if (master_filename.length() < 28 + FDFS_FILE_EXT_NAME_MAX_LEN)
{
throw new MyException("master filename \"" + master_filename + "\" is invalid");
}
dotIndex = master_filename.indexOf('.', master_filename.length() - (FDFS_FILE_EXT_NAME_MAX_LEN + 1));
if (ext_name != null)
{
if (ext_name.length() == 0)
{
true_ext_name = "";
}
else if (ext_name.charAt(0) == '.')
{
true_ext_name = ext_name;
}
else
{
true_ext_name = "." + ext_name;
}
}
else
{
if (dotIndex < 0)
{
true_ext_name = "";
}
else
{
true_ext_name = master_filename.substring(dotIndex);
}
}
if (true_ext_name.length() == 0 && prefix_name.equals("-m"))
{
throw new MyException("prefix_name \"" + prefix_name + "\" is invalid");
}
if (dotIndex < 0)
{
return master_filename + prefix_name + true_ext_name;
}
else
{
return master_filename.substring(0, dotIndex) + prefix_name + true_ext_name;
}
}
}
差不多就这几个程序了。接下来分析一下。
TestClient中首先就调用ClientGlobal中的static方法init对程序运行时传进来的参数conf_filename文件进行了处理,把里面的一些相关参数进行的初始化,其中最重要的就是g_tracker_group这个东西的初始化,它是通过调用TrackerGroup的init函数完成的,这一下之后,g_tracker_group和TrackerGroup中的三个变量便都有值了。接下来TestClient程序构造TrackerClient对象,大家一步步找过去会发现这个对象就是咱之前的g_tracker_group,也就是说现在TrackerClient对象中已经保存了配置文件中的跟tracker_server相关的列表了。接下来,通过TrackerClient对象的getConnection操作去生成一个TrackerServer对象,最终源头在TrackerGroup中的getConnection函数。而这一步说到底是通过TrackerClient来调用的,而tracker_group已经在咱之前生成TrackerClient对象的时候初始化完毕,所以说还是对那配置文件里面的那个tracker_server列表进行处理,TrackerGroup中的getConnection函数部分有个synchronized(同步),而tracker_server_index初始化是0,所以最终返回给TestClient的是一个可用的且尚未被使用的TrackerServer对象。接下来是生成一个StorageClient对象,然后是group_name = null;
StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name);这一步要做的事情是,把和TrackerClient能建立起连接的StorageServer对象保存在一个数组里存起来。到此为止,TrackerServer跟StorageServer的对应关系已经建立起来了,TestClient中剩下的部分就是通过StorageClient对象client去upload_file,delete_file,download_file等等的测试。但是之前返回来的StorageServer的数组对象有什么用我还没有看出来,我也是刚开始看客户端源码,如果有对文中描述不清楚的地方欢迎留言交流。
我自己接下来要做的事情:
1.把(ip,port)这个二元组与TrackerServer的对应关系先保存下来。(客户端代码中原来是track连过去,因为有进程锁,所以取一个当前可用的trackerServer对象,那么我猜想自己需要做的部分是在ClientGlobal中的init这个地方。
2.trackerServer的getStoreStorages操作结束之后,会返回当前可用且尚未被使用的StorageServer对象的数组。我要做的事情是把storageServer跟(ip,port)这个二元组的对应关系先找出来。
我为什么要做这些事情呢,是因为想到每次去连接,都会去找一次那些storageserver是可用的,保存起来之后通过ip地址+port映射过去,那么我就知道当前可用的storageserver,然后就可以进行上传下载等操作了。
最后想反应一下,关于FastDFS的相关资料实在是太少了,昨天想找一个关于协议的东西,官网上喊了好久都没人理。这篇东西是我在中午吃饭之前赶出来的,可能会比较粗糙,请见谅。欢迎大家留言交流。
----------------------------------------------------------
完成了那两个部分,现在来贴上代码,其中有三个类做过改动,改动的部分我用//做了标记。
ClientGlobal.java:其中init部分有添加
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/
package org.csource.fastdfs;
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.csource.common.*;
/**
* Global variables
* @author Happy Fish / YuQing
* @version Version 1.11
*/
public class ClientGlobal
{
public static int g_connect_timeout; //millisecond
public static int g_network_timeout; //millisecond
public static String g_charset;
public static int g_tracker_http_port;
public static boolean g_anti_steal_token; //if anti-steal token
public static String g_secret_key; //generage token secret key
public static TrackerGroup g_tracker_group;
public static final int DEFAULT_CONNECT_TIMEOUT = 5; //second
public static final int DEFAULT_NETWORK_TIMEOUT = 30; //second
///////////////////////////////////////////////////////
public static Map<String,ArrayList<TrackerServer> > mp;
public static Map<String,ArrayList<StorageServer> >mp2;
//////////////////////////////////////////////////////
private ClientGlobal()
{
}
/**
* load global variables
* @param conf_filename config filename
*/
public static void init(String conf_filename) throws FileNotFoundException, IOException, MyException
{
IniFileReader iniReader;
String[] szTrackerServers;
String[] parts;
iniReader = new IniFileReader(conf_filename);
g_connect_timeout = iniReader.getIntValue("connect_timeout", DEFAULT_CONNECT_TIMEOUT);
if (g_connect_timeout < 0)
{
g_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
}
g_connect_timeout *= 1000; //millisecond
g_network_timeout = iniReader.getIntValue("network_timeout", DEFAULT_NETWORK_TIMEOUT);
if (g_network_timeout < 0)
{
g_network_timeout = DEFAULT_NETWORK_TIMEOUT;
}
g_network_timeout *= 1000; //millisecond
g_charset = iniReader.getStrValue("charset");
if (g_charset == null || g_charset.length() == 0)
{
g_charset = "ISO8859-1";
}
szTrackerServers = iniReader.getValues("tracker_server");
if (szTrackerServers == null)
{
throw new MyException("item \"tracker_server\" in " + conf_filename + " not found");
}
InetSocketAddress[] tracker_servers = new InetSocketAddress[szTrackerServers.length];
for (int i=0; i<szTrackerServers.length; i++)
{
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()));
}
g_tracker_group = new TrackerGroup(tracker_servers);
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)
{
g_secret_key = iniReader.getStrValue("http.secret_key");
}
///////////////////////////////////////////////////////
mp=new HashMap<String,ArrayList<TrackerServer> >();
mp.clear();
for(int i=0;i<tracker_servers.length;i++)
{
Socket sock = new Socket();
sock.setReuseAddress(true);
sock.setSoTimeout(ClientGlobal.g_network_timeout);
sock.connect(tracker_servers[i], ClientGlobal.g_connect_timeout);
String tmp=tracker_servers[i].getAddress().toString();
TrackerServer trackerserver=new TrackerServer(sock, tracker_servers[i]);
if(mp.get(tmp)==null)
{
ArrayList<TrackerServer> al=new ArrayList<TrackerServer>();
al.add(trackerserver);
mp.put(tmp, al);
}
else
{
ArrayList<TrackerServer> al=mp.get(tmp);
al.add(trackerserver);
mp.put(tmp, al);
}
}
//////////////////////////////////////////////////////
}
/**
* construct Socket object
* @param ip_addr ip address or hostname
* @param port port number
* @return connected Socket object
*/
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);
return sock;
}
/**
* construct Socket object
* @param addr InetSocketAddress object, including ip address and port
* @return connected Socket object
*/
public static Socket getSocket(InetSocketAddress addr) throws IOException
{
Socket sock = new Socket();
sock.setSoTimeout(ClientGlobal.g_network_timeout);
sock.connect(addr, ClientGlobal.g_connect_timeout);
return sock;
}
public static int getG_connect_timeout()
{
return g_connect_timeout;
}
public static void setG_connect_timeout(int connect_timeout)
{
ClientGlobal.g_connect_timeout = connect_timeout;
}
public static int getG_network_timeout()
{
return g_network_timeout;
}
public static void setG_network_timeout(int network_timeout)
{
ClientGlobal.g_network_timeout = network_timeout;
}
public static String getG_charset()
{
return g_charset;
}
public static void setG_charset(String charset)
{
ClientGlobal.g_charset = charset;
}
public static int getG_tracker_http_port()
{
return g_tracker_http_port;
}
public static void setG_tracker_http_port(int tracker_http_port)
{
ClientGlobal.g_tracker_http_port = tracker_http_port;
}
public static boolean getG_anti_steal_token()
{
return g_anti_steal_token;
}
public static boolean isG_anti_steal_token()
{
return g_anti_steal_token;
}
public static void setG_anti_steal_token(boolean anti_steal_token)
{
ClientGlobal.g_anti_steal_token = anti_steal_token;
}
public static String getG_secret_key()
{
return g_secret_key;
}
public static void setG_secret_key(String secret_key)
{
ClientGlobal.g_secret_key = secret_key;
}
public static TrackerGroup getG_tracker_group()
{
return g_tracker_group;
}
public static void setG_tracker_group(TrackerGroup tracker_group)
{
ClientGlobal.g_tracker_group = tracker_group;
}
}
TrackerClient.java:其中我把原来代码中的getStoreStorages函数复制了一份,也可以不复制,反正返回的数组只是为了测试用,并无实际用途。
/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
*/
package org.csource.fastdfs;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.net.InetSocketAddress;
import java.net.Socket;
/**
* Tracker client
* @author Happy Fish / YuQing
* @version Version 1.19
*/
public class TrackerClient
{
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;
}
trackerSocket = trackerServer.getSocket();
OutputStream out = trackerSocket.getOutputStream();
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);
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,
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[] getStoreStorages1(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();
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
public void getStoreStorages2(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 ;
}
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 ;
}
if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN)
{
this.errno = ProtoCommon.ERR_NO_EINVAL;
return ;
}
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 ;
}
int serverCount = ipPortLen / recordLength;
if (serverCount > 16)
{
this.errno = ProtoCommon.ERR_NO_ENOSPC;
return ;
}
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;
///////////////////////////////////////////////////////////////////
ClientGlobal.mp2=new HashMap<String,ArrayList<StorageServer> >();
ClientGlobal.mp2.clear();
String s=(new InetSocketAddress(ip_addr,port)).getAddress().toString();
StorageServer storageserver=new StorageServer(ip_addr, port, store_path);
if(ClientGlobal.mp2.get(s)==null)
{
ArrayList<StorageServer> al=new ArrayList<StorageServer>();
al.add(storageserver);
ClientGlobal.mp2.put(s, al);
}
else
{
ArrayList<StorageServer> al=ClientGlobal.mp2.get(s);
al.add(storageserver);
ClientGlobal.mp2.put(s, al);
}
////////////////////////////////////////////////////////////////////
}
return ;
}
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<StructGroupStat> decoder = new ProtoStructDecoder<StructGroupStat>();
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<StructStorageStat> decoder = new ProtoStructDecoder<StructStorageStat>();
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;
}
}
}
}
finally
{
try
{
trackerServer.close();
}
catch(IOException ex1)
{
ex1.printStackTrace();
}
}
}
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;
}
}
ForReady.java:这个我自己新建的一个类,也在org.csource.fastdfs包下。其中前半部分是自己为了测试加进去的,后半部分与org.csource.fastdfs.test包下的TestClient.java的后半部分差不多。
package org.csource.fastdfs;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.Iterator;
import java.util.Set;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.test.DownloadFileWriter;
import org.csource.fastdfs.test.UploadLocalFileSender;
public class ForReady {
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;
}
System.out.println("java.version=" + System.getProperty("java.version"));
String conf_filename = args[0];
String local_filename = args[1];
// String str="/home/niuguoqin/workspace/FastDFS_Test/src/fdfs_client.conf";
try
{
ClientGlobal.init(conf_filename);
// ClientGlobal.init(str);
System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms");
System.out.println("charset=" + ClientGlobal.g_charset);
long startTime;
String group_name;
String remote_filename;
ServerInfo[] servers;
TrackerClient tracker = new TrackerClient();
Set<String> ss=ClientGlobal.mp.keySet();
Iterator<String> it=ss.iterator();
while(it.hasNext())
{
String s=it.next();
// System.out.println(s);
// System.out.println(ClientGlobal.mp.get(s).size());
Iterator<TrackerServer> i=ClientGlobal.mp.get(s).iterator();
while(i.hasNext())
{
TrackerServer trackerServer=i.next();
// trackerServer.sock.connect(trackerServer.getInetSocketAddress(), ClientGlobal.g_connect_timeout);
group_name = null;
tracker.getStoreStorages2(trackerServer, group_name);
// System.out.println(i.next());
}
}
/////////test
Set<String> s1=ClientGlobal.mp.keySet();
Iterator<String> it1=ss.iterator();
while(it1.hasNext())
{
String s=it1.next();
System.out.println(s);
Iterator<TrackerServer> i1=ClientGlobal.mp.get(s).iterator();
while(i1.hasNext())
{
TrackerServer trackerserver=i1.next();
// System.out.println(trackerserver.toString());
//////////////////////////////////////////////////////////////////////
String ip=trackerserver.getInetSocketAddress().getAddress().toString();
int port=trackerserver.getInetSocketAddress().getPort();
System.out.println("The ip of the trackerServer is " + ip);
System.out.println("The port of the trackerServer is " + port);
//////////////////////////////////////////////////////////////////////
Iterator<StorageServer> i2=ClientGlobal.mp2.get(s).iterator();
while(i2.hasNext())
{
StorageServer storageserver=i2.next();
System.out.println(storageserver.toString());
StorageClient client = new StorageClient(trackerserver, storageserver);//////////////////
/////////////////upload
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");
file_buff = "this is a test".getBytes(ClientGlobal.g_charset);
System.out.println("file length: " + file_buff.length);
startTime = System.currentTimeMillis();
results = client.upload_file(file_buff, "txt", meta_list);
System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms");
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));
////////////////////////////////////////////////////////////////
ip=storageserver.getInetSocketAddress().getAddress().toString();
port=storageserver.getInetSocketAddress().getPort();
System.out.println("The ip of the storageServer is " + ip);
System.out.println("The port of the storageServer is " + port);
////////////////////////////////////////////////////////////////
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);
}
////////////////////////////////////////////////////////////////
ip=storageserver.getInetSocketAddress().getAddress().toString();
port=storageserver.getInetSocketAddress().getPort();
System.out.println("The ip of the storageServer is " + ip);
System.out.println("The port of the storageServer is " + port);
////////////////////////////////////////////////////////////////
/* 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();
}
}
}
测试的时候配置文件也需要再新写几个,因为我只是在自己机器上测试,所以只是改变了其中的tracker_port和监听端口而已。
很希望大家留言交流,自己学习太孤单了。
分析一下FastDFS_java_client中TestClient.java这个文件以及跟它关联的这条线的更多相关文章
- matlab中增加Java VM 的堆空间(解决xml_io_tools出现的OutOfMemory问题)
今天用MATLAB写程序,调用了xml_io_tools(很赞的一个xml读写工具包)中的函数,但是由于我要书写的文件比较大,5m左右,运行时不知道xml_io_tools中的哪一块超出了java中的 ...
- Java中常用到的文件操作那些事(二)——使用POI解析Excel的两种常用方式对比
最近生产环境有个老项目一直内存报警,不时的还出现内存泄漏,导致需要重启服务器,已经严重影响正常服务了.获取生成dump文件后,使用MAT工具进行分析,发现是其中有个Excel文件上传功能时,经常会导致 ...
- Java Web文件上传原理分析(不借助开源fileupload上传jar包)
Java Web文件上传原理分析(不借助开源fileupload上传jar包) 博客分类: Java Web 最近在面试IBM时,面试官突然问到:如果让你自己实现一个文件上传,你的代码要如何写,不 ...
- java通过文件路径读取该路径下的所有文件并将其放入list中
java通过文件路径读取该路径下的所有文件并将其放入list中 java中可以通过递归的方式获取指定路径下的所有文件并将其放入List集合中.假设指定路径为path,目标集合为fileList,遍 ...
- HTML文件中使用Java程序
HTML文件中使用Java程序:简而言之,在HTML文件中引入java应用程序,并通过javascript调用其方法. 一. 运行环境 1.JAVA_HOME.CLASSPATH.PATH配置正确 ...
- 类A是公共的,应在名为A.java的文件中声明错误
第一种!!! “类A是公共的,应在名为A.java的文件中声明”这句话需要分两步来理解: 1.如果类A被声明为公共的(public),那么必须将类A保存在名为A.java的文件中: 2.反之,在一个文 ...
- JAVA中比较两个文件夹不同的方法
JAVA中比较两个文件夹不同的方法,可以通过两步来完成,首先遍历获取到文件夹下的所有文件夹和文件,再通过文件路径和文件的MD5值来判断文件的异同.具体例子如下: public class TestFo ...
- Java入门-类HelloWorld是公共的,应在名为HelloWorld.java的文件中声明
开始学习java了,搭好环境,notepad++中新建一个java文件,新建一个HelloWorld类, public class HelloWorld { public static void ma ...
- 在存放源程序的文件夹中建立一个子文件夹 myPackage。例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage)。在 myPackage 包中创建一个YMD类,该类具有计算今年的年份、可以输出一个带有年月日的字符串的功能。设计程序SY31.java,给定某人姓名和出生日期,计算该人年龄,并输出该人姓名、年龄、出生日期。程序使用YM
题目补充: 在存放源程序的文件夹中建立一个子文件夹 myPackage.例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage).在 m ...
随机推荐
- 剑指offer--面试题4
题目:替换字符串中的空格为“%20”. 说明:在浏览器的地址栏中输入某个网址,在解析过程中会看到类似“%20”的字样,这应该就是网络编程涉及的内容... 该题总体来说比较简单(连我都能想到!),个人认 ...
- libcurl编程学习
一.curl简介 curl是一个利用URL语法在命令行方式下工作的文件传输工具.它支持的协议有:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以 ...
- Unity手游:自动寻路Navmesh 跳跃 攀爬 斜坡
原地址:http://dong2008hong.blog.163.com/blog/static/46968827201403114644210/ 步骤 1.在场景中摆放各种模型,包括地板,斜坡,山体 ...
- Openstack Grizzily 单节点测试机安装( All In One CentOS/RHEL)
Openstack Grizzily版本已经相当完善,根据官方文档安装基本不存在什么问题,但是想快速测试了解Openstack功能的用户非常多,devstack的安 装需要check最新的代码,时常碰 ...
- What is the difference between Views and Materialized Views in Oracle?
aterialized views are disk based and update periodically base upon the query definition. Views are v ...
- [转载]Spring Autowire自动装配介绍
转自: http://www.cnblogs.com/zhishan/p/3190757.html 在应用中,我们常常使用<ref>标签为JavaBean注入它依赖的对象.但是对于一个大型 ...
- Intent (一)
1,简介 Intent 是一种消息传递机制,可以理解为一种对消息的封装,执行某操作的抽象描述,可用于应用程序内部及应用程序之间 其组成包括: 要执行的动作(action) 如VIEW_ACTION(查 ...
- POJ1416Shredding Company
http://poj.org/problem?id=1416 题意 : 要为碎纸机公司开发一种新的碎纸机,这种碎纸机要具有3个特性 :一是粉碎机以一个目标数 t 作为输入,并且粉碎的纸上写有一个数字n ...
- Ubuntu环境下手动配置ant
配置ant 1. 下载ant(http://ant.apache.org/bindownload.cgi) 例如我下载的是:apache-ant-1.9.4-bin.tar.gz 解压ant,将文件夹 ...
- lintcode 中等题:k Sum ii k数和 II
题目: k数和 II 给定n个不同的正整数,整数k(1<= k <= n)以及一个目标数字. 在这n个数里面找出K个数,使得这K个数的和等于目标数字,你需要找出所有满足要求的方案. 样例 ...