@@ -23,7 +23,6 @@ import (
2323 "sync"
2424 "sync/atomic"
2525 "time"
26- "unsafe"
2726
2827 "github.com/apache/pulsar-client-go/pulsar/crypto"
2928 "github.com/apache/pulsar-client-go/pulsar/internal"
@@ -48,13 +47,10 @@ const (
4847)
4948
5049type producer struct {
51- sync.RWMutex
5250 client * client
5351 options * ProducerOptions
5452 topic string
55- producers []Producer
56- producersPtr unsafe.Pointer
57- numPartitions uint32
53+ producers atomic.Value
5854 messageRouter func (* ProducerMessage , TopicMetadata ) int
5955 closeOnce sync.Once
6056 stopDiscovery func ()
@@ -195,10 +191,7 @@ func (p *producer) internalCreatePartitionsProducers() error {
195191 oldNumPartitions := 0
196192 newNumPartitions := len (partitions )
197193
198- p .Lock ()
199- defer p .Unlock ()
200-
201- oldProducers := p .producers
194+ oldProducers := p .getProducers ()
202195 oldNumPartitions = len (oldProducers )
203196
204197 if oldProducers != nil {
@@ -213,14 +206,14 @@ func (p *producer) internalCreatePartitionsProducers() error {
213206
214207 }
215208
216- p . producers = make ([]Producer , newNumPartitions )
209+ producers : = make ([]Producer , newNumPartitions )
217210
218211 // When for some reason (eg: forced deletion of sub partition) causes oldNumPartitions> newNumPartitions,
219212 // we need to rebuild the cache of new producers, otherwise the array will be out of bounds.
220213 if oldProducers != nil && oldNumPartitions < newNumPartitions {
221214 // Copy over the existing consumer instances
222215 for i := 0 ; i < oldNumPartitions ; i ++ {
223- p . producers [i ] = oldProducers [i ]
216+ producers [i ] = oldProducers [i ]
224217 }
225218 }
226219
@@ -251,20 +244,23 @@ func (p *producer) internalCreatePartitionsProducers() error {
251244 }(partitionIdx , partition )
252245 }
253246
247+ var newProducers []Producer
248+
254249 for i := 0 ; i < partitionsToAdd ; i ++ {
255250 pe , ok := <- c
256251 if ok {
257252 if pe .err != nil {
258253 err = pe .err
259254 } else {
260- p .producers [pe .partition ] = pe .prod
255+ producers [pe .partition ] = pe .prod
256+ newProducers = append (newProducers , pe .prod )
261257 }
262258 }
263259 }
264260
265261 if err != nil {
266262 // Since there were some failures, cleanup all the partitions that succeeded in creating the producers
267- for _ , producer := range p . producers {
263+ for _ , producer := range newProducers {
268264 if producer != nil {
269265 producer .Close ()
270266 }
@@ -277,8 +273,7 @@ func (p *producer) internalCreatePartitionsProducers() error {
277273 } else {
278274 p .metrics .ProducersPartitions .Add (float64 (partitionsToAdd ))
279275 }
280- atomic .StorePointer (& p .producersPtr , unsafe .Pointer (& p .producers ))
281- atomic .StoreUint32 (& p .numPartitions , uint32 (len (p .producers )))
276+ p .producers .Store (producers )
282277 return nil
283278}
284279
@@ -287,14 +282,11 @@ func (p *producer) Topic() string {
287282}
288283
289284func (p * producer ) Name () string {
290- p .RLock ()
291- defer p .RUnlock ()
292-
293- return p .producers [0 ].Name ()
285+ return p .getProducer (0 ).Name ()
294286}
295287
296288func (p * producer ) NumPartitions () uint32 {
297- return atomic . LoadUint32 ( & p . numPartitions )
289+ return uint32 ( len ( p . getProducers ()) )
298290}
299291
300292func (p * producer ) Send (ctx context.Context , msg * ProducerMessage ) (MessageID , error ) {
@@ -306,11 +298,11 @@ func (p *producer) SendAsync(ctx context.Context, msg *ProducerMessage,
306298 p .getPartition (msg ).SendAsync (ctx , msg , callback )
307299}
308300
309- func (p * producer ) getPartition ( msg * ProducerMessage ) Producer {
310- // Since partitions can only increase, it's ok if the producers list
311- // is updated in between. The numPartition is updated only after the list.
312- partition := p . messageRouter ( msg , p )
313- producers := * ( * [] Producer )( atomic . LoadPointer ( & p . producersPtr ))
301+ func (p * producer ) getProducer ( partition int ) Producer {
302+ producers := p . getProducers ()
303+ if len ( producers ) == 0 {
304+ panic ( "producer has not been initialized properly" )
305+ }
314306 if partition >= len (producers ) {
315307 // We read the old producers list while the count was already
316308 // updated
@@ -319,12 +311,23 @@ func (p *producer) getPartition(msg *ProducerMessage) Producer {
319311 return producers [partition ]
320312}
321313
322- func (p * producer ) LastSequenceID () int64 {
323- p .RLock ()
324- defer p .RUnlock ()
314+ func (p * producer ) getProducers () []Producer {
315+ if producers := p .producers .Load (); producers != nil {
316+ return producers .([]Producer )
317+ }
318+ return []Producer {}
319+ }
320+
321+ func (p * producer ) getPartition (msg * ProducerMessage ) Producer {
322+ // Since partitions can only increase, it's ok if the producers list
323+ // is updated in between. The numPartition is updated only after the list.
324+ partition := p .messageRouter (msg , p )
325+ return p .getProducer (partition )
326+ }
325327
328+ func (p * producer ) LastSequenceID () int64 {
326329 var maxSeq int64 = - 1
327- for _ , pp := range p .producers {
330+ for _ , pp := range p .getProducers () {
328331 s := pp .LastSequenceID ()
329332 if s > maxSeq {
330333 maxSeq = s
@@ -338,10 +341,7 @@ func (p *producer) Flush() error {
338341}
339342
340343func (p * producer ) FlushWithCtx (ctx context.Context ) error {
341- p .RLock ()
342- defer p .RUnlock ()
343-
344- for _ , pp := range p .producers {
344+ for _ , pp := range p .getProducers () {
345345 if err := pp .FlushWithCtx (ctx ); err != nil {
346346 return err
347347 }
@@ -354,14 +354,12 @@ func (p *producer) Close() {
354354 p .closeOnce .Do (func () {
355355 p .stopDiscovery ()
356356
357- p .Lock ()
358- defer p .Unlock ()
359-
360- for _ , pp := range p .producers {
357+ producers := p .getProducers ()
358+ for _ , pp := range producers {
361359 pp .Close ()
362360 }
363361 p .client .handlers .Del (p )
364- p .metrics .ProducersPartitions .Sub (float64 (len (p . producers )))
362+ p .metrics .ProducersPartitions .Sub (float64 (len (producers )))
365363 p .metrics .ProducersClosed .Inc ()
366364 })
367365}
0 commit comments