Do no access nsLockMap.lockMap when using dsync (#7464)

There is no need to access nsLockMap.lockMap when using dsync
master
Krishna Srinivas 6 years ago committed by kannappanr
parent 53011606a5
commit ef791764e0
  1. 82
      cmd/namespace-lock.go

@ -51,14 +51,6 @@ type RWLocker interface {
RUnlock() RUnlock()
} }
// RWLockerSync - internal locker interface.
type RWLockerSync interface {
GetLock(id, source string, timeout time.Duration) bool
Unlock()
GetRLock(id, source string, timeout time.Duration) bool
RUnlock()
}
// Initialize distributed locking only in case of distributed setup. // Initialize distributed locking only in case of distributed setup.
// Returns lock clients and the node index for the current server. // Returns lock clients and the node index for the current server.
func newDsyncNodes(endpoints EndpointList) (clnts []dsync.NetLocker, myNode int) { func newDsyncNodes(endpoints EndpointList) (clnts []dsync.NetLocker, myNode int) {
@ -101,8 +93,11 @@ func newDsyncNodes(endpoints EndpointList) (clnts []dsync.NetLocker, myNode int)
func newNSLock(isDistXL bool) *nsLockMap { func newNSLock(isDistXL bool) *nsLockMap {
nsMutex := nsLockMap{ nsMutex := nsLockMap{
isDistXL: isDistXL, isDistXL: isDistXL,
lockMap: make(map[nsParam]*nsLock),
} }
if isDistXL {
return &nsMutex
}
nsMutex.lockMap = make(map[nsParam]*nsLock)
return &nsMutex return &nsMutex
} }
@ -119,7 +114,7 @@ type nsParam struct {
// nsLock - provides primitives for locking critical namespace regions. // nsLock - provides primitives for locking critical namespace regions.
type nsLock struct { type nsLock struct {
RWLockerSync *lsync.LRWMutex
ref uint ref uint
} }
@ -141,13 +136,8 @@ func (n *nsLockMap) lock(volume, path string, lockSource, opsID string, readLock
nsLk, found := n.lockMap[param] nsLk, found := n.lockMap[param]
if !found { if !found {
n.lockMap[param] = &nsLock{ n.lockMap[param] = &nsLock{
RWLockerSync: func() RWLockerSync { LRWMutex: &lsync.LRWMutex{},
if n.isDistXL { ref: 1,
return dsync.NewDRWMutex(pathJoin(volume, path), globalDsync)
}
return &lsync.LRWMutex{}
}(),
ref: 1,
} }
nsLk = n.lockMap[param] nsLk = n.lockMap[param]
} else { } else {
@ -259,8 +249,49 @@ func (n *nsLockMap) ForceUnlock(volume, path string) {
delete(n.lockMap, nsParam{volume, path}) delete(n.lockMap, nsParam{volume, path})
} }
// lockInstance - frontend/top-level interface for namespace locks. // dsync's distributed lock instance.
type lockInstance struct { type distLockInstance struct {
rwMutex *dsync.DRWMutex
volume, path, opsID string
}
// Lock - block until write lock is taken or timeout has occurred.
func (di *distLockInstance) GetLock(timeout *dynamicTimeout) (timedOutErr error) {
lockSource := getSource()
start := UTCNow()
if !di.rwMutex.GetLock(di.opsID, lockSource, timeout.Timeout()) {
timeout.LogFailure()
return OperationTimedOut{Path: di.path}
}
timeout.LogSuccess(UTCNow().Sub(start))
return nil
}
// Unlock - block until write lock is released.
func (di *distLockInstance) Unlock() {
di.rwMutex.Unlock()
}
// RLock - block until read lock is taken or timeout has occurred.
func (di *distLockInstance) GetRLock(timeout *dynamicTimeout) (timedOutErr error) {
lockSource := getSource()
start := UTCNow()
if !di.rwMutex.GetRLock(di.opsID, lockSource, timeout.Timeout()) {
timeout.LogFailure()
return OperationTimedOut{Path: di.path}
}
timeout.LogSuccess(UTCNow().Sub(start))
return nil
}
// RUnlock - block until read lock is released.
func (di *distLockInstance) RUnlock() {
di.rwMutex.RUnlock()
}
// localLockInstance - frontend/top-level interface for namespace locks.
type localLockInstance struct {
ns *nsLockMap ns *nsLockMap
volume, path, opsID string volume, path, opsID string
} }
@ -270,11 +301,14 @@ type lockInstance struct {
// volume, path and operation ID. // volume, path and operation ID.
func (n *nsLockMap) NewNSLock(volume, path string) RWLocker { func (n *nsLockMap) NewNSLock(volume, path string) RWLocker {
opsID := mustGetUUID() opsID := mustGetUUID()
return &lockInstance{n, volume, path, opsID} if n.isDistXL {
return &distLockInstance{dsync.NewDRWMutex(pathJoin(volume, path), globalDsync), volume, path, opsID}
}
return &localLockInstance{n, volume, path, opsID}
} }
// Lock - block until write lock is taken or timeout has occurred. // Lock - block until write lock is taken or timeout has occurred.
func (li *lockInstance) GetLock(timeout *dynamicTimeout) (timedOutErr error) { func (li *localLockInstance) GetLock(timeout *dynamicTimeout) (timedOutErr error) {
lockSource := getSource() lockSource := getSource()
start := UTCNow() start := UTCNow()
readLock := false readLock := false
@ -287,13 +321,13 @@ func (li *lockInstance) GetLock(timeout *dynamicTimeout) (timedOutErr error) {
} }
// Unlock - block until write lock is released. // Unlock - block until write lock is released.
func (li *lockInstance) Unlock() { func (li *localLockInstance) Unlock() {
readLock := false readLock := false
li.ns.unlock(li.volume, li.path, li.opsID, readLock) li.ns.unlock(li.volume, li.path, li.opsID, readLock)
} }
// RLock - block until read lock is taken or timeout has occurred. // RLock - block until read lock is taken or timeout has occurred.
func (li *lockInstance) GetRLock(timeout *dynamicTimeout) (timedOutErr error) { func (li *localLockInstance) GetRLock(timeout *dynamicTimeout) (timedOutErr error) {
lockSource := getSource() lockSource := getSource()
start := UTCNow() start := UTCNow()
readLock := true readLock := true
@ -306,7 +340,7 @@ func (li *lockInstance) GetRLock(timeout *dynamicTimeout) (timedOutErr error) {
} }
// RUnlock - block until read lock is released. // RUnlock - block until read lock is released.
func (li *lockInstance) RUnlock() { func (li *localLockInstance) RUnlock() {
readLock := true readLock := true
li.ns.unlock(li.volume, li.path, li.opsID, readLock) li.ns.unlock(li.volume, li.path, li.opsID, readLock)
} }

Loading…
Cancel
Save