Skip to content

Commit

Permalink
Fix deadlocks
Browse files Browse the repository at this point in the history
  • Loading branch information
karimodm committed Oct 19, 2023
1 parent 35c8cdc commit 5a3141e
Showing 1 changed file with 31 additions and 38 deletions.
69 changes: 31 additions & 38 deletions api/epoch_based_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ type EpochBasedProvider struct {
futureProtocolParametersByVersion map[iotago.Version]iotago.Identifier
protocolVersions *ProtocolEpochVersions

latestAPIMutex sync.RWMutex
latestAPI iotago.API
latestAPI iotago.API

committedAPIMutex sync.RWMutex
committedAPI iotago.API
committedAPI iotago.API

committedSlotMutex sync.RWMutex
committedSlot iotago.SlotIndex
Expand All @@ -44,43 +42,27 @@ func NewEpochBasedProvider(opts ...options.Option[EpochBasedProvider]) *EpochBas
}

func (e *EpochBasedProvider) SetCommittedSlot(slot iotago.SlotIndex) {
e.mutex.Lock()
defer e.mutex.Unlock()

e.committedSlotMutex.Lock()
e.committedSlot = slot
e.committedSlotMutex.Unlock()

e.updateCommittedAPI(slot)
}

func (e *EpochBasedProvider) updateCommittedAPI(slot iotago.SlotIndex) {
e.committedAPIMutex.Lock()
defer e.committedAPIMutex.Unlock()

latestAPI := e.LatestAPI()
if latestAPI == nil {
return
}

epoch := latestAPI.TimeProvider().EpochFromSlot(slot)
version := e.VersionForEpoch(epoch)

if e.committedAPI == nil || version > e.committedAPI.ProtocolParameters().Version() {
e.committedAPI = lo.PanicOnErr(e.apiForVersion(version))
}
}

func (e *EpochBasedProvider) AddProtocolParametersAtEpoch(protocolParameters iotago.ProtocolParameters, epoch iotago.EpochIndex) {
e.AddProtocolParameters(protocolParameters)
e.AddVersion(protocolParameters.Version(), epoch)
}

func (e *EpochBasedProvider) AddProtocolParameters(protocolParameters iotago.ProtocolParameters) {
e.mutex.Lock()
defer e.mutex.Unlock()

e.protocolParametersByVersion[protocolParameters.Version()] = protocolParameters
delete(e.futureProtocolParametersByVersion, protocolParameters.Version())
e.mutex.Unlock()

e.latestAPIMutex.Lock()
defer e.latestAPIMutex.Unlock()

if e.latestAPI == nil || e.latestAPI.Version() < protocolParameters.Version() {
e.latestAPI = lo.PanicOnErr(e.apiForVersion(protocolParameters.Version()))
Expand All @@ -89,8 +71,9 @@ func (e *EpochBasedProvider) AddProtocolParameters(protocolParameters iotago.Pro

func (e *EpochBasedProvider) AddVersion(version iotago.Version, epoch iotago.EpochIndex) {
e.mutex.Lock()
defer e.mutex.Unlock()

e.protocolVersions.Add(version, epoch)
e.mutex.Unlock()

e.committedSlotMutex.Lock()
defer e.committedSlotMutex.Unlock()
Expand All @@ -107,12 +90,12 @@ func (e *EpochBasedProvider) AddFutureVersion(version iotago.Version, protocolPa
}

func (e *EpochBasedProvider) apiForVersion(version iotago.Version) (iotago.API, error) {
if latestAPI := e.LatestAPI(); latestAPI != nil && latestAPI.Version() == version {
return latestAPI, nil
if e.latestAPI != nil && e.latestAPI.Version() == version {
return e.latestAPI, nil
}

if committedAPI := e.CommittedAPI(); committedAPI != nil && committedAPI.Version() == version {
return committedAPI, nil
if e.committedAPI != nil && e.committedAPI.Version() == version {
return e.committedAPI, nil
}

protocolParams, exists := e.protocolParametersByVersion[version]
Expand Down Expand Up @@ -167,15 +150,15 @@ func (e *EpochBasedProvider) APIForEpoch(epoch iotago.EpochIndex) iotago.API {
}

func (e *EpochBasedProvider) LatestAPI() iotago.API {
e.latestAPIMutex.RLock()
defer e.latestAPIMutex.RUnlock()
e.mutex.RLock()
defer e.mutex.RUnlock()

return e.latestAPI
}

func (e *EpochBasedProvider) CommittedAPI() iotago.API {
e.committedAPIMutex.RLock()
defer e.committedAPIMutex.RUnlock()
e.mutex.RLock()
defer e.mutex.RUnlock()

return e.committedAPI
}
Expand Down Expand Up @@ -242,18 +225,28 @@ func (e *EpochBasedProvider) EpochForVersion(version iotago.Version) (iotago.Epo
return e.protocolVersions.EpochForVersion(version)
}

func (e *EpochBasedProvider) VersionForEpoch(epoch iotago.EpochIndex) iotago.Version {
func (e *EpochBasedProvider) VersionForSlot(slot iotago.SlotIndex) iotago.Version {
e.mutex.RLock()
defer e.mutex.RUnlock()

epoch := e.latestAPI.TimeProvider().EpochFromSlot(slot)

return e.protocolVersions.VersionForEpoch(epoch)
}

func (e *EpochBasedProvider) VersionForSlot(slot iotago.SlotIndex) iotago.Version {
e.mutex.RLock()
defer e.mutex.RUnlock()
func (e *EpochBasedProvider) updateCommittedAPI(slot iotago.SlotIndex) {
if e.latestAPI == nil {
return
}

epoch := e.latestAPI.TimeProvider().EpochFromSlot(slot)
version := e.versionForEpoch(epoch)

if e.committedAPI == nil || version > e.committedAPI.ProtocolParameters().Version() {
e.committedAPI = lo.PanicOnErr(e.apiForVersion(version))
}
}

func (e *EpochBasedProvider) versionForEpoch(epoch iotago.EpochIndex) iotago.Version {
return e.protocolVersions.VersionForEpoch(epoch)
}

0 comments on commit 5a3141e

Please sign in to comment.