fetch_request.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. package sarama
  2. type fetchRequestBlock struct {
  3. Version int16
  4. currentLeaderEpoch int32
  5. fetchOffset int64
  6. logStartOffset int64
  7. maxBytes int32
  8. }
  9. func (b *fetchRequestBlock) encode(pe packetEncoder, version int16) error {
  10. b.Version = version
  11. if b.Version >= 9 {
  12. pe.putInt32(b.currentLeaderEpoch)
  13. }
  14. pe.putInt64(b.fetchOffset)
  15. if b.Version >= 5 {
  16. pe.putInt64(b.logStartOffset)
  17. }
  18. pe.putInt32(b.maxBytes)
  19. return nil
  20. }
  21. func (b *fetchRequestBlock) decode(pd packetDecoder, version int16) (err error) {
  22. b.Version = version
  23. if b.Version >= 9 {
  24. if b.currentLeaderEpoch, err = pd.getInt32(); err != nil {
  25. return err
  26. }
  27. }
  28. if b.fetchOffset, err = pd.getInt64(); err != nil {
  29. return err
  30. }
  31. if b.Version >= 5 {
  32. if b.logStartOffset, err = pd.getInt64(); err != nil {
  33. return err
  34. }
  35. }
  36. if b.maxBytes, err = pd.getInt32(); err != nil {
  37. return err
  38. }
  39. return nil
  40. }
  41. // FetchRequest (API key 1) will fetch Kafka messages. Version 3 introduced the MaxBytes field. See
  42. // https://issues.apache.org/jira/browse/KAFKA-2063 for a discussion of the issues leading up to that. The KIP is at
  43. // https://cwiki.apache.org/confluence/display/KAFKA/KIP-74%3A+Add+Fetch+Response+Size+Limit+in+Bytes
  44. type FetchRequest struct {
  45. MaxWaitTime int32
  46. MinBytes int32
  47. MaxBytes int32
  48. Version int16
  49. Isolation IsolationLevel
  50. SessionID int32
  51. SessionEpoch int32
  52. blocks map[string]map[int32]*fetchRequestBlock
  53. forgotten map[string][]int32
  54. }
  55. type IsolationLevel int8
  56. const (
  57. ReadUncommitted IsolationLevel = iota
  58. ReadCommitted
  59. )
  60. func (r *FetchRequest) encode(pe packetEncoder) (err error) {
  61. pe.putInt32(-1) // replica ID is always -1 for clients
  62. pe.putInt32(r.MaxWaitTime)
  63. pe.putInt32(r.MinBytes)
  64. if r.Version >= 3 {
  65. pe.putInt32(r.MaxBytes)
  66. }
  67. if r.Version >= 4 {
  68. pe.putInt8(int8(r.Isolation))
  69. }
  70. if r.Version >= 7 {
  71. pe.putInt32(r.SessionID)
  72. pe.putInt32(r.SessionEpoch)
  73. }
  74. err = pe.putArrayLength(len(r.blocks))
  75. if err != nil {
  76. return err
  77. }
  78. for topic, blocks := range r.blocks {
  79. err = pe.putString(topic)
  80. if err != nil {
  81. return err
  82. }
  83. err = pe.putArrayLength(len(blocks))
  84. if err != nil {
  85. return err
  86. }
  87. for partition, block := range blocks {
  88. pe.putInt32(partition)
  89. err = block.encode(pe, r.Version)
  90. if err != nil {
  91. return err
  92. }
  93. }
  94. }
  95. if r.Version >= 7 {
  96. err = pe.putArrayLength(len(r.forgotten))
  97. if err != nil {
  98. return err
  99. }
  100. for topic, partitions := range r.forgotten {
  101. err = pe.putString(topic)
  102. if err != nil {
  103. return err
  104. }
  105. err = pe.putArrayLength(len(partitions))
  106. if err != nil {
  107. return err
  108. }
  109. for _, partition := range partitions {
  110. pe.putInt32(partition)
  111. }
  112. }
  113. }
  114. return nil
  115. }
  116. func (r *FetchRequest) decode(pd packetDecoder, version int16) (err error) {
  117. r.Version = version
  118. if _, err = pd.getInt32(); err != nil {
  119. return err
  120. }
  121. if r.MaxWaitTime, err = pd.getInt32(); err != nil {
  122. return err
  123. }
  124. if r.MinBytes, err = pd.getInt32(); err != nil {
  125. return err
  126. }
  127. if r.Version >= 3 {
  128. if r.MaxBytes, err = pd.getInt32(); err != nil {
  129. return err
  130. }
  131. }
  132. if r.Version >= 4 {
  133. isolation, err := pd.getInt8()
  134. if err != nil {
  135. return err
  136. }
  137. r.Isolation = IsolationLevel(isolation)
  138. }
  139. if r.Version >= 7 {
  140. r.SessionID, err = pd.getInt32()
  141. if err != nil {
  142. return err
  143. }
  144. r.SessionEpoch, err = pd.getInt32()
  145. if err != nil {
  146. return err
  147. }
  148. }
  149. topicCount, err := pd.getArrayLength()
  150. if err != nil {
  151. return err
  152. }
  153. if topicCount == 0 {
  154. return nil
  155. }
  156. r.blocks = make(map[string]map[int32]*fetchRequestBlock)
  157. for i := 0; i < topicCount; i++ {
  158. topic, err := pd.getString()
  159. if err != nil {
  160. return err
  161. }
  162. partitionCount, err := pd.getArrayLength()
  163. if err != nil {
  164. return err
  165. }
  166. r.blocks[topic] = make(map[int32]*fetchRequestBlock)
  167. for j := 0; j < partitionCount; j++ {
  168. partition, err := pd.getInt32()
  169. if err != nil {
  170. return err
  171. }
  172. fetchBlock := &fetchRequestBlock{}
  173. if err = fetchBlock.decode(pd, r.Version); err != nil {
  174. return err
  175. }
  176. r.blocks[topic][partition] = fetchBlock
  177. }
  178. }
  179. if r.Version >= 7 {
  180. forgottenCount, err := pd.getArrayLength()
  181. if err != nil {
  182. return err
  183. }
  184. if forgottenCount == 0 {
  185. return nil
  186. }
  187. r.forgotten = make(map[string][]int32)
  188. for i := 0; i < forgottenCount; i++ {
  189. topic, err := pd.getString()
  190. if err != nil {
  191. return err
  192. }
  193. partitionCount, err := pd.getArrayLength()
  194. if err != nil {
  195. return err
  196. }
  197. r.forgotten[topic] = make([]int32, partitionCount)
  198. for j := 0; j < partitionCount; j++ {
  199. partition, err := pd.getInt32()
  200. if err != nil {
  201. return err
  202. }
  203. r.forgotten[topic][j] = partition
  204. }
  205. }
  206. }
  207. return nil
  208. }
  209. func (r *FetchRequest) key() int16 {
  210. return 1
  211. }
  212. func (r *FetchRequest) version() int16 {
  213. return r.Version
  214. }
  215. func (r *FetchRequest) requiredVersion() KafkaVersion {
  216. switch r.Version {
  217. case 0:
  218. return MinVersion
  219. case 1:
  220. return V0_9_0_0
  221. case 2:
  222. return V0_10_0_0
  223. case 3:
  224. return V0_10_1_0
  225. case 4, 5:
  226. return V0_11_0_0
  227. case 6:
  228. return V1_0_0_0
  229. case 7:
  230. return V1_1_0_0
  231. case 8:
  232. return V2_0_0_0
  233. case 9, 10:
  234. return V2_1_0_0
  235. case 11:
  236. return V2_3_0_0
  237. default:
  238. return MaxVersion
  239. }
  240. }
  241. func (r *FetchRequest) AddBlock(topic string, partitionID int32, fetchOffset int64, maxBytes int32) {
  242. if r.blocks == nil {
  243. r.blocks = make(map[string]map[int32]*fetchRequestBlock)
  244. }
  245. if r.Version >= 7 && r.forgotten == nil {
  246. r.forgotten = make(map[string][]int32)
  247. }
  248. if r.blocks[topic] == nil {
  249. r.blocks[topic] = make(map[int32]*fetchRequestBlock)
  250. }
  251. tmp := new(fetchRequestBlock)
  252. tmp.Version = r.Version
  253. tmp.maxBytes = maxBytes
  254. tmp.fetchOffset = fetchOffset
  255. if r.Version >= 9 {
  256. tmp.currentLeaderEpoch = int32(-1)
  257. }
  258. r.blocks[topic][partitionID] = tmp
  259. }