org.csource.fastdfs.StorageClient Maven / Gradle / Ivy
The newest version!
/**
* 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 org.csource.common.Base64;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import java.io.*;
import java.net.Socket;
import java.util.Arrays;
/**
* 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;
}
public TrackerServer getTrackerServer() {
return trackerServer;
}
public StorageServer getStorageServer() {
return 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - results[0]: the group name to store the file
* - results[1]: the new created filename
* 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:
* - ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE: overwrite all old
* metadata items
* - ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE: merge, insert when
* the metadata item not exist, otherwise update it
* @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);
}
}