@@ -21,6 +21,7 @@ import (
2121 "encoding/binary"
2222 stderr "errors"
2323 "io"
24+ "sort"
2425 "sync"
2526 "time"
2627
@@ -110,11 +111,13 @@ type eventlog struct {
110111 writableSegments map [uint64 ]* segment
111112 writableMu sync.RWMutex
112113 logWriter * logWriter
114+ writerMu sync.RWMutex
113115
114116 readableWatcher * ReadableSegmentsWatcher
115117 readableSegments map [uint64 ]* segment
116118 readableMu sync.RWMutex
117119 logReader * logReader
120+ readerMu sync.RWMutex
118121 tracer * tracing.Tracer
119122}
120123
@@ -128,6 +131,8 @@ func (l *eventlog) ID() uint64 {
128131func (l * eventlog ) Close (ctx context.Context ) {
129132 l .writableWatcher .Close ()
130133 l .readableWatcher .Close ()
134+ l .logWriter = nil
135+ l .logReader = nil
131136
132137 for _ , segment := range l .writableSegments {
133138 segment .Close (ctx )
@@ -138,6 +143,11 @@ func (l *eventlog) Close(ctx context.Context) {
138143}
139144
140145func (l * eventlog ) Writer () LogWriter {
146+ if l .logWriter != nil {
147+ return l .logWriter
148+ }
149+ l .writerMu .Lock ()
150+ defer l .writerMu .Unlock ()
141151 if l .logWriter != nil {
142152 return l .logWriter
143153 }
@@ -151,6 +161,11 @@ func (l *eventlog) Reader(cfg ReaderConfig) LogReader {
151161 if l .logReader != nil {
152162 return l .logReader
153163 }
164+ l .readerMu .Lock ()
165+ defer l .readerMu .Unlock ()
166+ if l .logWriter != nil {
167+ return l .logReader
168+ }
154169 l .logReader = & logReader {
155170 elog : l ,
156171 pos : 0 ,
@@ -262,6 +277,8 @@ func (l *eventlog) selectWritableSegment(ctx context.Context) (*segment, error)
262277}
263278
264279func (l * eventlog ) nextWritableSegment (ctx context.Context , seg * segment ) (* segment , error ) {
280+ l .writableMu .RLock ()
281+ defer l .writableMu .RUnlock ()
265282 if s , ok := l .writableSegments [seg .nextSegmentId ]; ok {
266283 return s , nil
267284 }
@@ -345,15 +362,14 @@ func (l *eventlog) selectReadableSegment(ctx context.Context, offset int64) (*se
345362 return nil , errors .ErrUnderflow
346363 }
347364
348- for {
349- if offset >= target .EndOffset () {
350- target = l .writableSegments [target .nextSegmentId ]
351- } else {
352- // got target segment
353- break
354- }
365+ segmentNum := len (l .readableSegments )
366+ n := sort .Search (segmentNum , func (i int ) bool {
367+ return l .readableSegments [uint64 (i )].EndOffset () > offset
368+ })
369+ if n < segmentNum {
370+ return l .readableSegments [uint64 (n )], nil
355371 }
356- return target , nil
372+ return nil , errors . ErrNotReadable
357373}
358374
359375func (l * eventlog ) fetchReadableSegments (ctx context.Context ) map [uint64 ]* segment {
@@ -395,9 +411,9 @@ func (w *logWriter) Append(ctx context.Context, event *ce.Event) (string, error)
395411 // TODO: async for throughput
396412 retryTimes := defaultRetryTimes
397413 for i := 1 ; i <= retryTimes ; i ++ {
398- offset , err := w .doAppend (ctx , event )
414+ eid , err := w .doAppend (ctx , event )
399415 if err == nil {
400- return w . generateEventID ( offset ) , nil
416+ return eid , nil
401417 }
402418
403419 switch err {
@@ -422,28 +438,28 @@ func (w *logWriter) Append(ctx context.Context, event *ce.Event) (string, error)
422438 return "" , errors .ErrUnknown
423439}
424440
425- func (w * logWriter ) doAppend (ctx context.Context , event * ce.Event ) (int64 , error ) {
441+ func (w * logWriter ) doAppend (ctx context.Context , event * ce.Event ) (string , error ) {
426442 segment , err := w .selectWritableSegment (ctx )
427443 if err != nil {
428- return - 1 , err
444+ return "" , err
429445 }
430446 offset , err := segment .Append (ctx , event )
431447 if err != nil {
432448 switch err {
433449 case errors .ErrNotWritable , errors .ErrNotEnoughSpace , errors .ErrNoSpace :
434450 segment .SetNotWritable ()
435451 }
436- return - 1 , err
452+ return "" , err
437453 }
438- return offset , nil
454+ return w . generateEventID ( segment , offset ) , nil
439455}
440456
441- func (w * logWriter ) generateEventID (offset int64 ) string {
457+ func (w * logWriter ) generateEventID (s * segment , offset int64 ) string {
442458 var buf [32 ]byte
443- binary .BigEndian .PutUint64 (buf [0 :8 ], w . cur .id )
459+ binary .BigEndian .PutUint64 (buf [0 :8 ], s .id )
444460 binary .BigEndian .PutUint64 (buf [8 :16 ], uint64 (offset ))
445461 binary .BigEndian .PutUint64 (buf [16 :24 ], w .elog .ID ())
446- binary .BigEndian .PutUint64 (buf [24 :32 ], uint64 (offset + w . cur .startOffset ))
462+ binary .BigEndian .PutUint64 (buf [24 :32 ], uint64 (offset + s .startOffset ))
447463 return base64 .StdEncoding .EncodeToString (buf [:])
448464}
449465
0 commit comments