Skip to content
This repository has been archived by the owner on Jul 11, 2024. It is now read-only.

Commit

Permalink
patch race by rlock missunderstanding of crs
Browse files Browse the repository at this point in the history
  • Loading branch information
andersfylling committed Feb 17, 2021
1 parent 7b18f0c commit c6a91e4
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 66 deletions.
96 changes: 31 additions & 65 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ type CacheLFUImmutable struct {

var _ Cache = (*CacheLFUImmutable)(nil)

func (c *CacheLFUImmutable) getGuild(id Snowflake) (*crs.LFUItem, bool) {
c.Guilds.Lock()
defer c.Guilds.Unlock()
return c.Guilds.Get(id)
}

func (c *CacheLFUImmutable) createDMChannel(msg *Message) {
channelID := msg.ChannelID

Expand Down Expand Up @@ -142,15 +148,14 @@ func (c *CacheLFUImmutable) ChannelCreate(data []byte) (*ChannelCreate, error) {
}
c.Patch(channel)

c.Channels.Lock()
defer c.Channels.Unlock()
_ = c.saveChannel(channel)
return &ChannelCreate{Channel: DeepCopy(channel).(*Channel)}, nil
}

func (c *CacheLFUImmutable) saveChannel(channel *Channel) error {
item := c.Channels.CreateCacheableItem(channel)

c.Channels.Lock()
defer c.Channels.Unlock()
if _, exists := c.Channels.Get(channel.ID); exists {
return errors.New("already exists")
}
Expand Down Expand Up @@ -185,9 +190,9 @@ func (c *CacheLFUImmutable) ChannelUpdate(data []byte) (*ChannelUpdate, error) {
}
channelID := metadata.ID

c.Channels.RLock()
c.Channels.Lock()
item, exists := c.Channels.Get(channelID)
c.Channels.RUnlock()
c.Channels.Unlock()

var channel *Channel
var err error
Expand Down Expand Up @@ -381,9 +386,9 @@ func (c *CacheLFUImmutable) GuildMemberUpdate(data []byte) (evt *GuildMemberUpda

userwrap := &userHolder{}

c.Users.RLock()
c.Users.Lock()
cachedUser, userExists := c.Users.Get(uid)
c.Users.RUnlock()
c.Users.Unlock()

if userExists {
mutex := c.Mutex(&c.Users, uid)
Expand All @@ -393,7 +398,6 @@ func (c *CacheLFUImmutable) GuildMemberUpdate(data []byte) (evt *GuildMemberUpda
c.Patch(userwrap.User)
}
mutex.Unlock()
userwrap = nil
} else {
userwrap.User = &User{}
if err := json.Unmarshal(data, userwrap); err == nil {
Expand All @@ -406,13 +410,10 @@ func (c *CacheLFUImmutable) GuildMemberUpdate(data []byte) (evt *GuildMemberUpda
}
c.Users.Unlock()
}
userwrap = nil
}
userwrap = nil

c.Guilds.RLock()
item, exists := c.Guilds.Get(gid)
c.Guilds.RUnlock()

item, exists := c.getGuild(gid)
if exists {
mutex := c.Mutex(&c.Guilds, gid)
mutex.Lock()
Expand Down Expand Up @@ -454,9 +455,9 @@ func (c *CacheLFUImmutable) GuildMemberAdd(data []byte) (*GuildMemberAdd, error)
userID := gmr.Member.User.ID
guildID := gmr.Member.GuildID

c.Users.RLock()
c.Users.Lock()
cachedUser, userExists := c.Users.Get(userID)
c.Users.RUnlock()
c.Users.Unlock()

if userExists {
mutex := c.Mutex(&c.Users, userID)
Expand All @@ -479,10 +480,7 @@ func (c *CacheLFUImmutable) GuildMemberAdd(data []byte) (*GuildMemberAdd, error)
c.Users.Unlock()
}

c.Guilds.RLock()
item, exists := c.Guilds.Get(guildID)
c.Guilds.RUnlock()

item, exists := c.getGuild(guildID)
if exists {
mutex := c.Mutex(&c.Guilds, guildID)
mutex.Lock()
Expand Down Expand Up @@ -520,10 +518,7 @@ func (c *CacheLFUImmutable) GuildCreate(data []byte) (*GuildCreate, error) {
}
guildID := metadata.ID

c.Guilds.RLock()
item, exists := c.Guilds.Get(guildID)
c.Guilds.RUnlock()

item, exists := c.getGuild(guildID)
var guild *Guild
if exists && item.Val.(*Guild).Unavailable {
// pre-loaded from ready event
Expand Down Expand Up @@ -564,10 +559,12 @@ func (c *CacheLFUImmutable) GuildCreate(data []byte) (*GuildCreate, error) {
}

// cache channels
c.Channels.Lock()
for i := range guild.Channels {
channel := DeepCopy(guild.Channels[i]).(*Channel)
_ = c.saveChannel(channel)
}
c.Channels.Unlock()

return &GuildCreate{Guild: guild}, nil
}
Expand Down Expand Up @@ -596,10 +593,7 @@ func (c *CacheLFUImmutable) GuildUpdate(data []byte) (*GuildUpdate, error) {
}
guildID := metadata.ID

c.Guilds.RLock()
item, exists := c.Guilds.Get(guildID)
c.Guilds.RUnlock()

item, exists := c.getGuild(guildID)
var guild *Guild
var err error
if exists {
Expand Down Expand Up @@ -652,9 +646,9 @@ func (c *CacheLFUImmutable) GuildDelete(data []byte) (*GuildDelete, error) {
// return nil, nil
// }
func (c *CacheLFUImmutable) GetChannel(id Snowflake) (*Channel, error) {
c.Channels.RLock()
c.Channels.Lock()
cachedItem, exists := c.Channels.Get(id)
c.Channels.RUnlock()
c.Channels.Unlock()

if exists {
mutex := c.Mutex(&c.Channels, id)
Expand All @@ -667,10 +661,7 @@ func (c *CacheLFUImmutable) GetChannel(id Snowflake) (*Channel, error) {
return nil, nil
}
func (c *CacheLFUImmutable) GetGuildEmoji(guildID, emojiID Snowflake) (*Emoji, error) {
c.Guilds.RLock()
cachedItem, exists := c.Guilds.Get(guildID)
c.Guilds.RUnlock()

cachedItem, exists := c.getGuild(guildID)
if exists {
mutex := c.Mutex(&c.Guilds, guildID)
mutex.Lock()
Expand All @@ -683,10 +674,7 @@ func (c *CacheLFUImmutable) GetGuildEmoji(guildID, emojiID Snowflake) (*Emoji, e
return nil, errors.New("guild does not exist")
}
func (c *CacheLFUImmutable) GetGuildEmojis(id Snowflake) ([]*Emoji, error) {
c.Guilds.RLock()
cachedItem, exists := c.Guilds.Get(id)
c.Guilds.RUnlock()

cachedItem, exists := c.getGuild(id)
if exists {
mutex := c.Mutex(&c.Guilds, id)
mutex.Lock()
Expand All @@ -703,10 +691,7 @@ func (c *CacheLFUImmutable) GetGuildEmojis(id Snowflake) ([]*Emoji, error) {
return nil, errors.New("guild does not exist")
}
func (c *CacheLFUImmutable) GetGuild(id Snowflake) (*Guild, error) {
c.Guilds.RLock()
cachedItem, exists := c.Guilds.Get(id)
c.Guilds.RUnlock()

cachedItem, exists := c.getGuild(id)
var guild *Guild
if exists {
mutex := c.Mutex(&c.Guilds, id)
Expand All @@ -719,10 +704,7 @@ func (c *CacheLFUImmutable) GetGuild(id Snowflake) (*Guild, error) {
return guild, nil
}
func (c *CacheLFUImmutable) GetGuildChannels(id Snowflake) ([]*Channel, error) {
c.Guilds.RLock()
cachedItem, exists := c.Guilds.Get(id)
c.Guilds.RUnlock()

cachedItem, exists := c.getGuild(id)
if exists {
mutex := c.Mutex(&c.Guilds, id)
mutex.Lock()
Expand All @@ -746,23 +728,11 @@ func (c *CacheLFUImmutable) GetMember(guildID, userID Snowflake) (*Member, error
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
c.Users.RLock()
user, _ = c.GetUser(userID)
c.Users.RUnlock()

if user != nil {
mutex := c.Mutex(&c.Users, userID)
mutex.Lock()
user = DeepCopy(user).(*User)
mutex.Unlock()
}
wg.Done()
}()

c.Guilds.RLock()
cachedItem, exists := c.Guilds.Get(guildID)
c.Guilds.RUnlock()

cachedItem, exists := c.getGuild(guildID)
if exists {
mutex := c.Mutex(&c.Users, userID)
mutex.Lock()
Expand All @@ -775,7 +745,6 @@ func (c *CacheLFUImmutable) GetMember(guildID, userID Snowflake) (*Member, error

mutex.Unlock()
}

wg.Wait()

if member != nil {
Expand All @@ -786,10 +755,7 @@ func (c *CacheLFUImmutable) GetMember(guildID, userID Snowflake) (*Member, error
}
}
func (c *CacheLFUImmutable) GetGuildRoles(guildID Snowflake) ([]*Role, error) {
c.Guilds.RLock()
cachedItem, exists := c.Guilds.Get(guildID)
c.Guilds.RUnlock()

cachedItem, exists := c.getGuild(guildID)
if exists {
mutex := c.Mutex(&c.Guilds, guildID)
mutex.Lock()
Expand Down Expand Up @@ -819,9 +785,9 @@ func (c *CacheLFUImmutable) GetUser(id Snowflake) (*User, error) {
return c.GetCurrentUser()
}

c.Users.RLock()
c.Users.Lock()
item, exists := c.Users.Get(id)
c.Users.RUnlock()
c.Users.Unlock()

var user *User
if exists {
Expand Down
2 changes: 1 addition & 1 deletion internal/crs/lfu.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func SetLimit(v interface{}, limit uint) {
}

type LFU struct {
sync.RWMutex
sync.Mutex
items []LFUItem
table map[Snowflake]int
nilTable []int
Expand Down

0 comments on commit c6a91e4

Please sign in to comment.