Fix status table race condition (#1835)

This commit is contained in:
Ethan Koenig 2017-05-31 04:57:17 -04:00 коммит произвёл Lunny Xiao
Родитель 0f5b399e35
Коммит bfb44f8854
5 изменённых файлов: 26 добавлений и 10 удалений

Просмотреть файл

@ -1881,10 +1881,9 @@ func DeleteRepositoryArchives() error {
// DeleteOldRepositoryArchives deletes old repository archives. // DeleteOldRepositoryArchives deletes old repository archives.
func DeleteOldRepositoryArchives() { func DeleteOldRepositoryArchives() {
if taskStatusTable.IsRunning(archiveCleanup) { if !taskStatusTable.StartIfNotRunning(archiveCleanup) {
return return
} }
taskStatusTable.Start(archiveCleanup)
defer taskStatusTable.Stop(archiveCleanup) defer taskStatusTable.Stop(archiveCleanup)
log.Trace("Doing: ArchiveCleanup") log.Trace("Doing: ArchiveCleanup")
@ -2025,10 +2024,9 @@ const (
// GitFsck calls 'git fsck' to check repository health. // GitFsck calls 'git fsck' to check repository health.
func GitFsck() { func GitFsck() {
if taskStatusTable.IsRunning(gitFsck) { if !taskStatusTable.StartIfNotRunning(gitFsck) {
return return
} }
taskStatusTable.Start(gitFsck)
defer taskStatusTable.Stop(gitFsck) defer taskStatusTable.Stop(gitFsck)
log.Trace("Doing: GitFsck") log.Trace("Doing: GitFsck")
@ -2097,10 +2095,9 @@ func repoStatsCheck(checker *repoChecker) {
// CheckRepoStats checks the repository stats // CheckRepoStats checks the repository stats
func CheckRepoStats() { func CheckRepoStats() {
if taskStatusTable.IsRunning(checkRepos) { if !taskStatusTable.StartIfNotRunning(checkRepos) {
return return
} }
taskStatusTable.Start(checkRepos)
defer taskStatusTable.Stop(checkRepos) defer taskStatusTable.Stop(checkRepos)
log.Trace("Doing: CheckRepoStats") log.Trace("Doing: CheckRepoStats")

Просмотреть файл

@ -202,10 +202,9 @@ func DeleteMirrorByRepoID(repoID int64) error {
// MirrorUpdate checks and updates mirror repositories. // MirrorUpdate checks and updates mirror repositories.
func MirrorUpdate() { func MirrorUpdate() {
if taskStatusTable.IsRunning(mirrorUpdate) { if !taskStatusTable.StartIfNotRunning(mirrorUpdate) {
return return
} }
taskStatusTable.Start(mirrorUpdate)
defer taskStatusTable.Stop(mirrorUpdate) defer taskStatusTable.Stop(mirrorUpdate)
log.Trace("Doing: MirrorUpdate") log.Trace("Doing: MirrorUpdate")

Просмотреть файл

@ -1334,10 +1334,9 @@ func GetWatchedRepos(userID int64, private bool) ([]*Repository, error) {
// SyncExternalUsers is used to synchronize users with external authorization source // SyncExternalUsers is used to synchronize users with external authorization source
func SyncExternalUsers() { func SyncExternalUsers() {
if taskStatusTable.IsRunning(syncExternalUsers) { if !taskStatusTable.StartIfNotRunning(syncExternalUsers) {
return return
} }
taskStatusTable.Start(syncExternalUsers)
defer taskStatusTable.Stop(syncExternalUsers) defer taskStatusTable.Stop(syncExternalUsers)
log.Trace("Doing: SyncExternalUsers") log.Trace("Doing: SyncExternalUsers")

Просмотреть файл

@ -24,6 +24,18 @@ func NewStatusTable() *StatusTable {
} }
} }
// StartIfNotRunning sets value of given name to true if not already in pool.
// Returns whether set value was set to true
func (p *StatusTable) StartIfNotRunning(name string) bool {
p.lock.Lock()
_, ok := p.pool[name]
if !ok {
p.pool[name] = struct{}{}
}
p.lock.Unlock()
return !ok
}
// Start sets value of given name to true in the pool. // Start sets value of given name to true in the pool.
func (p *StatusTable) Start(name string) { func (p *StatusTable) Start(name string) {
p.lock.Lock() p.lock.Lock()

Просмотреть файл

@ -18,6 +18,15 @@ func Test_StatusTable(t *testing.T) {
table.Start("xyz") table.Start("xyz")
assert.True(t, table.IsRunning("xyz")) assert.True(t, table.IsRunning("xyz"))
assert.False(t, table.StartIfNotRunning("xyz"))
assert.True(t, table.IsRunning("xyz"))
table.Stop("xyz")
assert.False(t, table.IsRunning("xyz"))
assert.True(t, table.StartIfNotRunning("xyz"))
assert.True(t, table.IsRunning("xyz"))
table.Stop("xyz") table.Stop("xyz")
assert.False(t, table.IsRunning("xyz")) assert.False(t, table.IsRunning("xyz"))
} }