fdfs_protol.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # filename: fdfs_protol.py
  4. import struct
  5. import socket
  6. from fdfs_client.exceptions import (
  7. FDFSError,
  8. ConnectionError,
  9. ResponseError,
  10. InvaildResponse,
  11. DataError
  12. )
  13. ## define FDFS protol constans
  14. TRACKER_PROTO_CMD_STORAGE_JOIN = 81
  15. FDFS_PROTO_CMD_QUIT = 82
  16. TRACKER_PROTO_CMD_STORAGE_BEAT = 83 #storage heart beat
  17. TRACKER_PROTO_CMD_STORAGE_REPORT_DISK_USAGE =84 #report disk usage
  18. TRACKER_PROTO_CMD_STORAGE_REPLICA_CHG = 85 #repl new storage servers
  19. TRACKER_PROTO_CMD_STORAGE_SYNC_SRC_REQ = 86 #src storage require sync
  20. TRACKER_PROTO_CMD_STORAGE_SYNC_DEST_REQ = 87 #dest storage require sync
  21. TRACKER_PROTO_CMD_STORAGE_SYNC_NOTIFY = 88 #sync done notify
  22. TRACKER_PROTO_CMD_STORAGE_SYNC_REPORT = 89 #report src last synced time as dest server
  23. TRACKER_PROTO_CMD_STORAGE_SYNC_DEST_QUERY = 79 #dest storage query sync src storage server
  24. TRACKER_PROTO_CMD_STORAGE_REPORT_IP_CHANGED = 78 #storage server report it's ip changed
  25. TRACKER_PROTO_CMD_STORAGE_CHANGELOG_REQ = 77 #storage server request storage server's changelog
  26. TRACKER_PROTO_CMD_STORAGE_REPORT_STATUS = 76 #report specified storage server status
  27. TRACKER_PROTO_CMD_STORAGE_PARAMETER_REQ = 75 #storage server request parameters
  28. TRACKER_PROTO_CMD_STORAGE_REPORT_TRUNK_FREE = 74 #storage report trunk free space
  29. TRACKER_PROTO_CMD_STORAGE_REPORT_TRUNK_FID = 73 #storage report current trunk file id
  30. TRACKER_PROTO_CMD_STORAGE_FETCH_TRUNK_FID = 72 #storage get current trunk file id
  31. TRACKER_PROTO_CMD_TRACKER_GET_SYS_FILES_START = 61 #start of tracker get system data files
  32. TRACKER_PROTO_CMD_TRACKER_GET_SYS_FILES_END = 62 #end of tracker get system data files
  33. TRACKER_PROTO_CMD_TRACKER_GET_ONE_SYS_FILE = 63 #tracker get a system data file
  34. TRACKER_PROTO_CMD_TRACKER_GET_STATUS = 64 #tracker get status of other tracker
  35. TRACKER_PROTO_CMD_TRACKER_PING_LEADER = 65 #tracker ping leader
  36. TRACKER_PROTO_CMD_TRACKER_NOTIFY_NEXT_LEADER = 66 #notify next leader to other trackers
  37. TRACKER_PROTO_CMD_TRACKER_COMMIT_NEXT_LEADER = 67 #commit next leader to other trackers
  38. TRACKER_PROTO_CMD_SERVER_LIST_ONE_GROUP = 90
  39. TRACKER_PROTO_CMD_SERVER_LIST_ALL_GROUPS = 91
  40. TRACKER_PROTO_CMD_SERVER_LIST_STORAGE = 92
  41. TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE = 93
  42. TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE = 101
  43. TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE = 102
  44. TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE = 103
  45. TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE = 104
  46. TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL = 105
  47. TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL = 106
  48. TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL = 107
  49. TRACKER_PROTO_CMD_RESP = 100
  50. FDFS_PROTO_CMD_ACTIVE_TEST = 111 #active test, tracker and storage both support since V1.28
  51. STORAGE_PROTO_CMD_REPORT_CLIENT_IP = 9 #ip as tracker client
  52. STORAGE_PROTO_CMD_UPLOAD_FILE = 11
  53. STORAGE_PROTO_CMD_DELETE_FILE = 12
  54. STORAGE_PROTO_CMD_SET_METADATA = 13
  55. STORAGE_PROTO_CMD_DOWNLOAD_FILE = 14
  56. STORAGE_PROTO_CMD_GET_METADATA = 15
  57. STORAGE_PROTO_CMD_SYNC_CREATE_FILE = 16
  58. STORAGE_PROTO_CMD_SYNC_DELETE_FILE = 17
  59. STORAGE_PROTO_CMD_SYNC_UPDATE_FILE = 18
  60. STORAGE_PROTO_CMD_SYNC_CREATE_LINK = 19
  61. STORAGE_PROTO_CMD_CREATE_LINK = 20
  62. STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE = 21
  63. STORAGE_PROTO_CMD_QUERY_FILE_INFO = 22
  64. STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE = 23 #create appender file
  65. STORAGE_PROTO_CMD_APPEND_FILE = 24 #append file
  66. STORAGE_PROTO_CMD_SYNC_APPEND_FILE = 25
  67. STORAGE_PROTO_CMD_FETCH_ONE_PATH_BINLOG = 26 #fetch binlog of one store path
  68. STORAGE_PROTO_CMD_RESP = TRACKER_PROTO_CMD_RESP
  69. STORAGE_PROTO_CMD_UPLOAD_MASTER_FILE = STORAGE_PROTO_CMD_UPLOAD_FILE
  70. STORAGE_PROTO_CMD_TRUNK_ALLOC_SPACE = 27 #since V3.00
  71. STORAGE_PROTO_CMD_TRUNK_ALLOC_CONFIRM = 28 #since V3.00
  72. STORAGE_PROTO_CMD_TRUNK_FREE_SPACE = 29 #since V3.00
  73. STORAGE_PROTO_CMD_TRUNK_SYNC_BINLOG = 30 #since V3.00
  74. STORAGE_PROTO_CMD_TRUNK_GET_BINLOG_SIZE = 31 #since V3.07
  75. STORAGE_PROTO_CMD_TRUNK_DELETE_BINLOG_MARKS = 32 #since V3.07
  76. STORAGE_PROTO_CMD_TRUNK_TRUNCATE_BINLOG_FILE = 33 #since V3.07
  77. STORAGE_PROTO_CMD_MODIFY_FILE = 34 #since V3.08
  78. STORAGE_PROTO_CMD_SYNC_MODIFY_FILE = 35 #since V3.08
  79. STORAGE_PROTO_CMD_TRUNCATE_FILE = 36 #since V3.08
  80. STORAGE_PROTO_CMD_SYNC_TRUNCATE_FILE = 37 #since V3.08
  81. #for overwrite all old metadata
  82. STORAGE_SET_METADATA_FLAG_OVERWRITE = 'O'
  83. STORAGE_SET_METADATA_FLAG_OVERWRITE_STR = "O"
  84. #for replace, insert when the meta item not exist, otherwise update it
  85. STORAGE_SET_METADATA_FLAG_MERGE = 'M'
  86. STORAGE_SET_METADATA_FLAG_MERGE_STR = "M"
  87. FDFS_RECORD_SEPERATOR = '\x01'
  88. FDFS_FIELD_SEPERATOR = '\x02'
  89. #common constants
  90. FDFS_STORAGE_ID_MAX_SIZE = 16
  91. FDFS_GROUP_NAME_MAX_LEN = 16
  92. IP_ADDRESS_SIZE = 16
  93. FDFS_PROTO_PKG_LEN_SIZE = 8
  94. FDFS_PROTO_CMD_SIZE = 1
  95. FDFS_PROTO_STATUS_SIZE = 1
  96. FDFS_PROTO_IP_PORT_SIZE = (IP_ADDRESS_SIZE + 6)
  97. FDFS_MAX_SERVERS_EACH_GROUP = 32
  98. FDFS_MAX_GROUPS = 512
  99. FDFS_MAX_TRACKERS = 16
  100. FDFS_DOMAIN_NAME_MAX_LEN = 128
  101. FDFS_MAX_META_NAME_LEN = 64
  102. FDFS_MAX_META_VALUE_LEN = 256
  103. FDFS_FILE_PREFIX_MAX_LEN = 16
  104. FDFS_LOGIC_FILE_PATH_LEN = 10
  105. FDFS_TRUE_FILE_PATH_LEN = 6
  106. FDFS_FILENAME_BASE64_LENGTH = 27
  107. FDFS_TRUNK_FILE_INFO_LEN = 16
  108. FDFS_FILE_EXT_NAME_MAX_LEN = 6
  109. FDFS_SPACE_SIZE_BASE_INDEX = 2 # storage space size based (MB)
  110. FDFS_UPLOAD_BY_BUFFER = 1
  111. FDFS_UPLOAD_BY_FILENAME = 2
  112. FDFS_UPLOAD_BY_FILE = 3
  113. FDFS_DOWNLOAD_TO_BUFFER = 1
  114. FDFS_DOWNLOAD_TO_FILE = 2
  115. FDFS_NORMAL_LOGIC_FILENAME_LENGTH = (FDFS_LOGIC_FILE_PATH_LEN + \
  116. FDFS_FILENAME_BASE64_LENGTH + FDFS_FILE_EXT_NAME_MAX_LEN + 1)
  117. FDFS_TRUNK_FILENAME_LENGTH = (FDFS_TRUE_FILE_PATH_LEN + \
  118. FDFS_FILENAME_BASE64_LENGTH + \
  119. FDFS_TRUNK_FILE_INFO_LEN + \
  120. 1 + FDFS_FILE_EXT_NAME_MAX_LEN)
  121. FDFS_TRUNK_LOGIC_FILENAME_LENGTH = (FDFS_TRUNK_FILENAME_LENGTH + \
  122. (FDFS_LOGIC_FILE_PATH_LEN - \
  123. FDFS_TRUE_FILE_PATH_LEN))
  124. FDFS_VERSION_SIZE = 6
  125. TRACKER_QUERY_STORAGE_FETCH_BODY_LEN = (FDFS_GROUP_NAME_MAX_LEN \
  126. + IP_ADDRESS_SIZE - 1 + FDFS_PROTO_PKG_LEN_SIZE)
  127. TRACKER_QUERY_STORAGE_STORE_BODY_LEN = (FDFS_GROUP_NAME_MAX_LEN \
  128. + IP_ADDRESS_SIZE - 1 + FDFS_PROTO_PKG_LEN_SIZE + 1)
  129. #status code, order is important!
  130. FDFS_STORAGE_STATUS_INIT = 0
  131. FDFS_STORAGE_STATUS_WAIT_SYNC = 1
  132. FDFS_STORAGE_STATUS_SYNCING = 2
  133. FDFS_STORAGE_STATUS_IP_CHANGED = 3
  134. FDFS_STORAGE_STATUS_DELETED = 4
  135. FDFS_STORAGE_STATUS_OFFLINE = 5
  136. FDFS_STORAGE_STATUS_ONLINE = 6
  137. FDFS_STORAGE_STATUS_ACTIVE = 7
  138. FDFS_STORAGE_STATUS_RECOVERY = 9
  139. FDFS_STORAGE_STATUS_NONE = 99
  140. class Storage_server(object):
  141. '''Class storage server for upload.'''
  142. def __init__(self):
  143. self.ip_addr = None
  144. self.port = None
  145. self.group_name = ''
  146. self.store_path_index = 0
  147. # Class tracker_header
  148. class Tracker_header(object):
  149. '''
  150. Class for Pack or Unpack tracker header
  151. struct tracker_header{
  152. char pkg_len[FDFS_PROTO_PKG_LEN_SIZE],
  153. char cmd,
  154. char status,
  155. }
  156. '''
  157. def __init__(self):
  158. self.fmt = '!QBB' # pkg_len[FDFS_PROTO_PKG_LEN_SIZE] + cmd + status
  159. self.st = struct.Struct(self.fmt)
  160. self.pkg_len = 0
  161. self.cmd = 0
  162. self.status = 0
  163. def _pack(self, pkg_len = 0, cmd = 0, status = 0):
  164. return self.st.pack(pkg_len, cmd, status)
  165. def _unpack(self, bytes_stream):
  166. self.pkg_len, self.cmd, self.status = self.st.unpack(bytes_stream)
  167. return True
  168. def header_len(self):
  169. return self.st.size
  170. def send_header(self, conn):
  171. '''Send Tracker header to server.'''
  172. header = self._pack(self.pkg_len, self.cmd, self.status)
  173. try:
  174. conn.sendall(header)
  175. except (socket.error, socket.timeout), e:
  176. raise ConnectionError('[-] Error: while writting to socket: %s' \
  177. % (e.args,))
  178. def recv_header(self, conn):
  179. '''Receive response from server.
  180. if sucess, class member (pkg_len, cmd, status) is response.
  181. '''
  182. try:
  183. header = conn.recv(self.header_len())
  184. except (socket.error, socket.timeout), e:
  185. raise ConnectionError('[-] Error: while reading from socket: %s' \
  186. % (e.args,))
  187. if not header:
  188. raise ConnectionError("Socket closed on remote end")
  189. self._unpack(header)
  190. def fdfs_pack_metadata(meta_dict):
  191. ret = ''
  192. for key in meta_dict:
  193. ret += '%s%c%s%c' % (key, FDFS_FIELD_SEPERATOR, \
  194. meta_dict[key], FDFS_RECORD_SEPERATOR)
  195. return ret[0:-1]
  196. def fdfs_unpack_metadata(bytes_stream):
  197. li = bytes_stream.split(FDFS_RECORD_SEPERATOR)
  198. return dict([item.split(FDFS_FIELD_SEPERATOR) for item in li])