mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 02:00:56 +00:00
fix(client): fix putAheadReadBlock Blocking issue
close:#1000412030
Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit ccb7de44bb)
This commit is contained in:
parent
a21a0b6b4c
commit
b47bc52042
@ -22,6 +22,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -37,6 +38,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
|
||||||
|
//"runtime/debug"
|
||||||
runtimepprof "runtime/pprof"
|
runtimepprof "runtime/pprof"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -92,7 +95,8 @@ const (
|
|||||||
|
|
||||||
ControlCommandSetRate = "/rate/set"
|
ControlCommandSetRate = "/rate/set"
|
||||||
ControlCommandGetRate = "/rate/get"
|
ControlCommandGetRate = "/rate/get"
|
||||||
ControlCommandFreeOSMemory = "/debug/freeosmemory"
|
ControlCommandFreeOSMemory = "/freeosmemory"
|
||||||
|
ControlCommandMemStats = "/memstats"
|
||||||
ControlCommandSuspend = "/suspend"
|
ControlCommandSuspend = "/suspend"
|
||||||
ControlCommandResume = "/resume"
|
ControlCommandResume = "/resume"
|
||||||
ControlCommandStopWarmMeta = "/stopWarmMeta"
|
ControlCommandStopWarmMeta = "/stopWarmMeta"
|
||||||
@ -767,6 +771,7 @@ func mount(opt *proto.MountOptions) (fsConn *fuse.Conn, super *cfs.Super, err er
|
|||||||
http.HandleFunc(ControlCommandGetRate, super.GetRate)
|
http.HandleFunc(ControlCommandGetRate, super.GetRate)
|
||||||
http.HandleFunc(log.SetLogLevelPath, log.SetLogLevel)
|
http.HandleFunc(log.SetLogLevelPath, log.SetLogLevel)
|
||||||
http.HandleFunc(ControlCommandFreeOSMemory, freeOSMemory)
|
http.HandleFunc(ControlCommandFreeOSMemory, freeOSMemory)
|
||||||
|
http.HandleFunc(ControlCommandMemStats, memStats)
|
||||||
http.HandleFunc(log.GetLogPath, log.GetLog)
|
http.HandleFunc(log.GetLogPath, log.GetLog)
|
||||||
http.HandleFunc(ControlCommandSuspend, super.SetSuspend)
|
http.HandleFunc(ControlCommandSuspend, super.SetSuspend)
|
||||||
http.HandleFunc(ControlCommandResume, super.SetResume)
|
http.HandleFunc(ControlCommandResume, super.SetResume)
|
||||||
@ -1136,6 +1141,19 @@ func changeRlimit(val uint64) {
|
|||||||
|
|
||||||
func freeOSMemory(w http.ResponseWriter, r *http.Request) {
|
func freeOSMemory(w http.ResponseWriter, r *http.Request) {
|
||||||
debug.FreeOSMemory()
|
debug.FreeOSMemory()
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte("freeOSMemory is called"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func memStats(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var m runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&m)
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
enc := json.NewEncoder(w)
|
||||||
|
enc.SetIndent("", " ")
|
||||||
|
enc.SetEscapeHTML(false)
|
||||||
|
_ = enc.Encode(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfFromMaster(opt *proto.MountOptions) (err error) {
|
func loadConfFromMaster(opt *proto.MountOptions) (err error) {
|
||||||
|
|||||||
@ -20,6 +20,8 @@ import (
|
|||||||
syslog "log"
|
syslog "log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@ -235,6 +237,13 @@ func (m *Server) checkConfig(cfg *config.Config) (err error) {
|
|||||||
m.bindIp = cfg.GetBool(proto.BindIpKey)
|
m.bindIp = cfg.GetBool(proto.BindIpKey)
|
||||||
m.port = cfg.GetString(proto.ListenPort)
|
m.port = cfg.GetString(proto.ListenPort)
|
||||||
m.logDir = cfg.GetString(LogDir)
|
m.logDir = cfg.GetString(LogDir)
|
||||||
|
// make logDir absolute to avoid dependency on process working directory
|
||||||
|
if m.logDir != "" && !filepath.IsAbs(m.logDir) {
|
||||||
|
if exe, e := os.Executable(); e == nil {
|
||||||
|
base := filepath.Dir(exe)
|
||||||
|
m.logDir = filepath.Join(base, m.logDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
m.walDir = cfg.GetString(WalDir)
|
m.walDir = cfg.GetString(WalDir)
|
||||||
m.bStoreAddr = cfg.GetString(BStoreAddrKey)
|
m.bStoreAddr = cfg.GetString(BStoreAddrKey)
|
||||||
if m.bStoreAddr == "" {
|
if m.bStoreAddr == "" {
|
||||||
|
|||||||
@ -147,9 +147,13 @@ func (arc *AheadReadCache) getAheadReadBlock() (block *AheadReadBlock, err error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (arc *AheadReadCache) putAheadReadBlock(key string, block *AheadReadBlock) {
|
func (arc *AheadReadCache) putAheadReadBlock(key string, block *AheadReadBlock) {
|
||||||
arc.availableBlockC <- struct{}{}
|
select {
|
||||||
|
case arc.availableBlockC <- struct{}{}:
|
||||||
|
atomic.AddInt64(&arc.availableBlockCnt, 1)
|
||||||
|
default:
|
||||||
|
// channel is full: duplicate return detected, drop token to avoid blocking
|
||||||
|
}
|
||||||
putAheadReadBlock(block)
|
putAheadReadBlock(block)
|
||||||
atomic.AddInt64(&arc.availableBlockCnt, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (arc *AheadReadCache) checkBlockTimeOut() {
|
func (arc *AheadReadCache) checkBlockTimeOut() {
|
||||||
@ -185,11 +189,13 @@ func (arc *AheadReadCache) doCheckBlockTimeOut() {
|
|||||||
if atomic.LoadUint32(&bv.readed) == AheadReadedInit {
|
if atomic.LoadUint32(&bv.readed) == AheadReadedInit {
|
||||||
log.LogInfof("doCheckBlockTimeOut delete unreaded block: key(%v) addr(%p)", key, bv)
|
log.LogInfof("doCheckBlockTimeOut delete unreaded block: key(%v) addr(%p)", key, bv)
|
||||||
}
|
}
|
||||||
arc.blockCache.Delete(key.(string))
|
// block is ready to recycle; ensure return-once semantics
|
||||||
// block is ready to recycle
|
keyStr := key.(string)
|
||||||
bv.key = ""
|
bv.key = ""
|
||||||
bv.lock.Unlock()
|
bv.lock.Unlock()
|
||||||
arc.putAheadReadBlock(key.(string), bv)
|
if actual, loaded := arc.blockCache.LoadAndDelete(keyStr); loaded {
|
||||||
|
arc.putAheadReadBlock(keyStr, actual.(*AheadReadBlock))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bv.lock.Unlock()
|
bv.lock.Unlock()
|
||||||
}
|
}
|
||||||
@ -747,12 +753,15 @@ func (arw *AheadReadWindow) evictAllBlocks() {
|
|||||||
bv.lock.Lock()
|
bv.lock.Lock()
|
||||||
bv.key = ""
|
bv.key = ""
|
||||||
if atomic.LoadUint32(&bv.state) == AheadReadBlockStateInit {
|
if atomic.LoadUint32(&bv.state) == AheadReadBlockStateInit {
|
||||||
arw.cache.blockCache.Delete(key)
|
// ensure only one goroutine returns the token once
|
||||||
arw.cache.putAheadReadBlock(key.(string), bv)
|
bv.lock.Unlock()
|
||||||
|
if actual, loaded := arw.cache.blockCache.LoadAndDelete(key.(string)); loaded {
|
||||||
|
arw.cache.putAheadReadBlock(key.(string), actual.(*AheadReadBlock))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
atomic.StoreUint32(&bv.state, AheadReadBlockStateClear)
|
atomic.StoreUint32(&bv.state, AheadReadBlockStateClear)
|
||||||
|
bv.lock.Unlock()
|
||||||
}
|
}
|
||||||
bv.lock.Unlock()
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
// wait for all blockCache is cleared
|
// wait for all blockCache is cleared
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sort"
|
"sort"
|
||||||
@ -98,6 +99,10 @@ var gSt *Statistic = nil
|
|||||||
|
|
||||||
func NewStatistic(dir, logModule string, logMaxSize int64, timeOutUs [MaxTimeoutLevel]uint32, useMutex bool) (*Statistic, error) {
|
func NewStatistic(dir, logModule string, logMaxSize int64, timeOutUs [MaxTimeoutLevel]uint32, useMutex bool) (*Statistic, error) {
|
||||||
dir = path.Join(dir, logModule)
|
dir = path.Join(dir, logModule)
|
||||||
|
// normalize to absolute path to avoid cwd-related issues
|
||||||
|
if absDir, err := filepath.Abs(dir); err == nil {
|
||||||
|
dir = absDir
|
||||||
|
}
|
||||||
fi, err := os.Stat(dir)
|
fi, err := os.Stat(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.MkdirAll(dir, 0o755)
|
os.MkdirAll(dir, 0o755)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user