1.add ump warn packet
  2.partition has recover,but the status don't change
  3.remove redundancy calling loadMetaData method
  4.reload meta data when change leader

metanode:
   1. add totalMem in configFile
   2.change not raft leader to tryOtherAddr error

 datanode:
   1.when datapartition not exsit,tell client with proto.OptryAgain resultcode
   2.change disk retrain default space to 20gb
   3.heartbeat report add volname

 raft:
   1.use raft.ErrNotLeader replace ErrNotLeader
   2.raft became leader must apply from oldapplyid to commitid

 client:
   1.  create a dummy node instance if inode does not exist
   2. add ump alarm for read/write/fsync errors

log:
   1.   auto create subdir to logdir

 error:
   1.delete juju error packet
This commit is contained in:
awzhgw 2019-04-30 09:07:03 +08:00
parent 88d2a1c87b
commit 36d97f1034
89 changed files with 998 additions and 2091 deletions

View File

@ -179,7 +179,9 @@ func (d *Dir) Lookup(ctx context.Context, req *fuse.LookupRequest, resp *fuse.Lo
inode, err := d.super.InodeGet(ino)
if err != nil {
log.LogErrorf("Lookup: parent(%v) name(%v) ino(%v) err(%v)", d.inode.ino, req.Name, ino, err)
return nil, ParseError(err)
dummyInode := &Inode{ino: ino}
dummyChild := NewFile(d.super, dummyInode)
return dummyChild, nil
}
mode := inode.mode

View File

@ -15,6 +15,7 @@
package fs
import (
"fmt"
"io"
"syscall"
"time"
@ -65,6 +66,10 @@ func (f *File) Attr(ctx context.Context, a *fuse.Attr) error {
inode, err := f.super.InodeGet(ino)
if err != nil {
log.LogErrorf("Attr: ino(%v) err(%v)", ino, err)
if err == fuse.ENOENT {
a.Inode = ino
return nil
}
return ParseError(err)
}
@ -140,16 +145,22 @@ func (f *File) Release(ctx context.Context, req *fuse.ReleaseRequest) (err error
// Read handles the read request.
func (f *File) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) (err error) {
log.LogDebugf("TRACE Read enter: ino(%v) offset(%v) reqsize(%v) req(%v)", f.inode.ino, req.Offset, req.Size, req)
start := time.Now()
size, err := f.super.ec.Read(f.inode.ino, resp.Data[fuse.OutHeaderSize:], int(req.Offset), req.Size)
if err != nil && err != io.EOF {
log.LogErrorf("Read: ino(%v) req(%v) err(%v) size(%v)", f.inode.ino, req, err, size)
msg := fmt.Sprintf("Read: ino(%v) req(%v) err(%v) size(%v)", f.inode.ino, req, err, size)
f.super.handleError("Read", msg)
return fuse.EIO
}
if size > req.Size {
log.LogErrorf("Read: ino(%v) req(%v) size(%v)", f.inode.ino, req, size)
msg := fmt.Sprintf("Read: read size larger than request size, ino(%v) req(%v) size(%v)", f.inode.ino, req, size)
f.super.handleError("Read", msg)
return fuse.ERANGE
}
if size > 0 {
resp.Data = resp.Data[:size+fuse.OutHeaderSize]
} else if size <= 0 {
@ -192,11 +203,14 @@ func (f *File) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.Wri
}
start := time.Now()
size, err := f.super.ec.Write(ino, int(req.Offset), req.Data, enSyncWrite)
if err != nil {
log.LogErrorf("Write: ino(%v) offset(%v) len(%v) err(%v)", ino, req.Offset, reqlen, err)
msg := fmt.Sprintf("Write: ino(%v) offset(%v) len(%v) err(%v)", ino, req.Offset, reqlen, err)
f.super.handleError("Write", msg)
return fuse.EIO
}
resp.Size = size
if size != reqlen {
log.LogErrorf("Write: ino(%v) offset(%v) len(%v) size(%v)", ino, req.Offset, reqlen, size)
@ -204,7 +218,8 @@ func (f *File) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.Wri
if waitForFlush {
if err = f.super.ec.Flush(ino); err != nil {
log.LogErrorf("Write: failed to wait for flush, ino(%v) offset(%v) len(%v) err(%v) req(%v)", ino, req.Offset, reqlen, err, req)
msg := fmt.Sprintf("Write: failed to wait for flush, ino(%v) offset(%v) len(%v) err(%v) req(%v)", ino, req.Offset, reqlen, err, req)
f.super.handleError("Wrtie", msg)
return fuse.EIO
}
}
@ -226,7 +241,8 @@ func (f *File) Fsync(ctx context.Context, req *fuse.FsyncRequest) (err error) {
start := time.Now()
err = f.super.ec.Flush(f.inode.ino)
if err != nil {
log.LogErrorf("Fsync: ino(%v) err(%v)", f.inode.ino, err)
msg := fmt.Sprintf("Fsync: ino(%v) err(%v)", f.inode.ino, err)
f.super.handleError("Fsync", msg)
return fuse.EIO
}
f.super.ic.Delete(f.inode.ino)

View File

@ -16,7 +16,7 @@ package fs
import (
"fmt"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"golang.org/x/net/context"
"sync"
"time"
@ -26,6 +26,7 @@ import (
"github.com/chubaofs/chubaofs/sdk/data/stream"
"github.com/chubaofs/chubaofs/sdk/meta"
"github.com/chubaofs/chubaofs/util/log"
"github.com/chubaofs/chubaofs/util/ump"
)
// Super defines the struct of a super block.
@ -54,12 +55,12 @@ func NewSuper(volname, owner, master string, icacheTimeout, lookupValid, attrVal
s = new(Super)
s.mw, err = meta.NewMetaWrapper(volname, owner, master)
if err != nil {
return nil, errors.Annotate(err, "NewMetaWrapper failed!")
return nil, errors.Trace(err, "NewMetaWrapper failed!")
}
s.ec, err = stream.NewExtentClient(volname, master, s.mw.AppendExtentKey, s.mw.GetExtents, s.mw.Truncate)
if err != nil {
return nil, errors.Annotate(err, "NewExtentClient failed!")
return nil, errors.Trace(err, "NewExtentClient failed!")
}
s.volname = volname
@ -107,11 +108,20 @@ func (s *Super) Statfs(ctx context.Context, req *fuse.StatfsRequest, resp *fuse.
return nil
}
func (s *Super) exporterKey(act string) string {
return fmt.Sprintf("%s_fuseclient_%s", s.cluster, act)
}
// ClusterName returns the cluster name.
func (s *Super) ClusterName() string {
return s.cluster
}
func (s *Super) exporterKey(act string) string {
return fmt.Sprintf("%v_fuseclient_%v", s.cluster, act)
}
func (s *Super) umpKey(act string) string {
return fmt.Sprintf("%v_fuseclient_%v", s.cluster, act)
}
func (s *Super) handleError(op, msg string) {
log.LogError(msg)
ump.Alarm(s.umpKey(op), msg)
}

View File

@ -23,11 +23,10 @@ package main
import (
"flag"
"fmt"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"net/http"
_ "net/http/pprof"
"os"
"path"
"runtime"
"strconv"
"strings"
@ -38,6 +37,7 @@ import (
"github.com/chubaofs/chubaofs/util/config"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/chubaofs/chubaofs/util/log"
"github.com/chubaofs/chubaofs/util/ump"
)
const (
@ -94,13 +94,14 @@ func Mount(cfg *config.Config) (err error) {
attrValid := ParseConfigString(cfg, "attrValid")
enSyncWrite := ParseConfigString(cfg, "enSyncWrite")
autoInvalData := ParseConfigString(cfg, "autoInvalData")
umpDatadir := cfg.GetString("warnLogDir")
if mnt == "" || volname == "" || owner == "" || master == "" {
return errors.New(fmt.Sprintf("invalid config file: lack of mandatory fields, mountPoint(%v), volName(%v), owner(%v), masterAddr(%v)", mnt, volname, owner, master))
}
level := ParseLogLevel(loglvl)
_, err = log.InitLog(path.Join(logpath, LoggerDir), LoggerPrefix, level, nil)
_, err = log.InitLog(logpath, LoggerPrefix, level, nil)
if err != nil {
return err
}
@ -108,7 +109,7 @@ func Mount(cfg *config.Config) (err error) {
super, err := cfs.NewSuper(volname, owner, master, icacheTimeout, lookupValid, attrValid, enSyncWrite)
if err != nil {
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
return err
}
@ -132,6 +133,7 @@ func Mount(cfg *config.Config) (err error) {
fmt.Println(http.ListenAndServe(":"+profport, nil))
}()
ump.InitUmp(fmt.Sprintf("%v_%v", super.ClusterName(), ModuleName), umpDatadir)
exporter.Init(super.ClusterName(), ModuleName, cfg)
if err = fs.Serve(c, super); err != nil {

View File

@ -25,6 +25,7 @@ import (
"flag"
"fmt"
"github.com/chubaofs/chubaofs/util/config"
"github.com/chubaofs/chubaofs/util/ump"
"net/http"
_ "net/http/pprof"
"os"
@ -38,11 +39,11 @@ var (
)
const (
ConfigKeyRole = "role"
ConfigKeyLogDir = "logDir"
ConfigKeyLogLevel = "logLevel"
ConfigKeyProfPort = "prof"
ConfigKeyExporterPort = "exporterPort"
ConfigKeyRole = "role"
ConfigKeyLogDir = "logDir"
ConfigKeyLogLevel = "logLevel"
ConfigKeyProfPort = "prof"
ConfigKeyWarnLogDir = "warnLogDir"
)
const (
@ -118,7 +119,8 @@ func main() {
err := modifyOpenFiles()
if err != nil {
panic(err.Error())
fmt.Println(fmt.Sprintf(err.Error()))
os.Exit(1)
}
log.LogInfof("Hello, ChubaoFS Storage, Current Version: %s", Version)
@ -127,10 +129,11 @@ func main() {
logDir := cfg.GetString(ConfigKeyLogDir)
logLevel := cfg.GetString(ConfigKeyLogLevel)
profPort := cfg.GetString(ConfigKeyProfPort)
umpDatadir := cfg.GetString(ConfigKeyWarnLogDir)
//for multi-cpu scheduling
runtime.GOMAXPROCS(runtime.NumCPU())
ump.InitUmp(role, umpDatadir)
// Init server instance with specified role configuration.
var (
server Server

View File

@ -24,8 +24,8 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/repl"
"github.com/chubaofs/chubaofs/storage"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"hash/crc32"
)
@ -89,7 +89,7 @@ func (dp *DataPartition) repair(extentType uint8) {
err := dp.buildDataPartitionRepairTask(repairTasks, extentType, tinyExtents)
if err != nil {
log.LogErrorf(errors.ErrorStack(err))
log.LogErrorf(errors.Stack(err))
log.LogErrorf("action[repair] partition(%v) err(%v).",
dp.partitionID, err)
dp.moveToBrokenTinyExtentC(extentType, tinyExtents)
@ -105,7 +105,7 @@ func (dp *DataPartition) repair(extentType uint8) {
dp.sendAllTinyExtentsToC(extentType, availableTinyExtents, brokenTinyExtents)
log.LogErrorf("action[repair] partition(%v) err(%v).",
dp.partitionID, err)
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
return
}
@ -113,7 +113,7 @@ func (dp *DataPartition) repair(extentType uint8) {
dp.DoRepair(repairTasks)
end := time.Now().UnixNano()
// every time we need to figure out which extents need to be repaired and which ones do not.
// every time we need to figureAnnotatef out which extents need to be repaired and which ones do not.
dp.sendAllTinyExtentsToC(extentType, availableTinyExtents, brokenTinyExtents)
// error check
@ -162,17 +162,17 @@ func (dp *DataPartition) getLocalExtentInfo(extentType uint8, tinyExtents []uint
localExtents, tinyDeleteRecordSize, err = dp.extentStore.GetAllWatermarks(storage.TinyExtentFilter(tinyExtents))
}
if err != nil {
err = errors.Annotatef(err, "getLocalExtentInfo extent DataPartition(%v) GetAllWaterMark", dp.partitionID)
err = errors.Trace(err, "getLocalExtentInfo extent DataPartition(%v) GetAllWaterMark", dp.partitionID)
return
}
data, err := json.Marshal(localExtents)
if err != nil {
err = errors.Annotatef(err, "getLocalExtentInfo extent DataPartition(%v) GetAllWaterMark", dp.partitionID)
err = errors.Trace(err, "getLocalExtentInfo extent DataPartition(%v) GetAllWaterMark", dp.partitionID)
return
}
if err = json.Unmarshal(data, &extents); err != nil {
err = errors.Annotatef(err, "getLocalExtentInfo extent DataPartition(%v) GetAllWaterMark", dp.partitionID)
err = errors.Trace(err, "getLocalExtentInfo extent DataPartition(%v) GetAllWaterMark", dp.partitionID)
}
return
@ -185,7 +185,7 @@ func (dp *DataPartition) getRemoteExtentInfo(extentType uint8, tinyExtents []uin
if extentType == proto.TinyExtentType {
p.Data, err = json.Marshal(tinyExtents)
if err != nil {
err = errors.Annotatef(err, "getRemoteExtentInfo DataPartition(%v) GetAllWatermarks", dp.partitionID)
err = errors.Trace(err, "getRemoteExtentInfo DataPartition(%v) GetAllWatermarks", dp.partitionID)
return
}
p.Size = uint32(len(p.Data))
@ -193,24 +193,24 @@ func (dp *DataPartition) getRemoteExtentInfo(extentType uint8, tinyExtents []uin
var conn *net.TCPConn
conn, err = gConnPool.GetConnect(target) // get remote connection
if err != nil {
err = errors.Annotatef(err, "getRemoteExtentInfo DataPartition(%v) get host(%v) connect", dp.partitionID, target)
err = errors.Trace(err, "getRemoteExtentInfo DataPartition(%v) get host(%v) connect", dp.partitionID, target)
return
}
defer gConnPool.PutConnect(conn, true)
err = p.WriteToConn(conn) // write command to the remote host
if err != nil {
err = errors.Annotatef(err, "getRemoteExtentInfo DataPartition(%v) write to host(%v)", dp.partitionID, target)
err = errors.Trace(err, "getRemoteExtentInfo DataPartition(%v) write to host(%v)", dp.partitionID, target)
return
}
reply := new(repl.Packet)
err = reply.ReadFromConn(conn, proto.GetAllWatermarksDeadLineTime) // read the response
if err != nil {
err = errors.Annotatef(err, "getRemoteExtentInfo DataPartition(%v) read from host(%v)", dp.partitionID, target)
err = errors.Trace(err, "getRemoteExtentInfo DataPartition(%v) read from host(%v)", dp.partitionID, target)
return
}
err = json.Unmarshal(reply.Data[:reply.Size], &extentFiles)
if err != nil {
err = errors.Annotatef(err, "getRemoteExtentInfo DataPartition(%v) unmarshal json(%v) from host(%v)",
err = errors.Trace(err, "getRemoteExtentInfo DataPartition(%v) unmarshal json(%v) from host(%v)",
dp.partitionID, string(reply.Data[:reply.Size]), target)
return
}
@ -227,12 +227,12 @@ func (dp *DataPartition) DoRepair(repairTasks []*DataPartitionRepairTask) {
for _, extentInfo := range repairTasks[0].ExtentsToBeRepaired {
err := dp.streamRepairExtent(extentInfo)
if err != nil {
err = errors.Annotatef(err, "doStreamExtentFixRepair %v", dp.applyRepairKey(int(extentInfo.FileID)))
err = errors.Trace(err, "doStreamExtentFixRepair %v", dp.applyRepairKey(int(extentInfo.FileID)))
localExtentInfo, opErr := dp.ExtentStore().Watermark(uint64(extentInfo.FileID))
if opErr != nil {
err = errors.Annotatef(err, opErr.Error())
err = errors.Trace(err, opErr.Error())
}
err = errors.Annotatef(err, "partition(%v) remote(%v) local(%v)",
err = errors.Trace(err, "partition(%v) remote(%v) local(%v)",
dp.partitionID, extentInfo, localExtentInfo)
log.LogWarnf("action[doStreamExtentFixRepair] err(%v).", err)
}
@ -404,12 +404,12 @@ func (dp *DataPartition) doStreamExtentFixRepair(wg *sync.WaitGroup, remoteExten
err := dp.streamRepairExtent(remoteExtentInfo)
if err != nil {
err = errors.Annotatef(err, "doStreamExtentFixRepair %v", dp.applyRepairKey(int(remoteExtentInfo.FileID)))
err = errors.Trace(err, "doStreamExtentFixRepair %v", dp.applyRepairKey(int(remoteExtentInfo.FileID)))
localExtentInfo, opErr := dp.ExtentStore().Watermark(uint64(remoteExtentInfo.FileID))
if opErr != nil {
err = errors.Annotatef(err, opErr.Error())
err = errors.Trace(err, opErr.Error())
}
err = errors.Annotatef(err, "partition(%v) remote(%v) local(%v)",
err = errors.Trace(err, "partition(%v) remote(%v) local(%v)",
dp.partitionID, remoteExtentInfo, localExtentInfo)
log.LogWarnf("action[doStreamExtentFixRepair] err(%v).", err)
}
@ -427,7 +427,7 @@ func (dp *DataPartition) streamRepairExtent(remoteExtentInfo *storage.ExtentInfo
}
localExtentInfo, err := store.Watermark(remoteExtentInfo.FileID)
if err != nil {
return errors.Annotatef(err, "streamRepairExtent Watermark error")
return errors.Trace(err, "streamRepairExtent Watermark error")
}
if localExtentInfo.Size >= remoteExtentInfo.Size {
@ -439,12 +439,12 @@ func (dp *DataPartition) streamRepairExtent(remoteExtentInfo *storage.ExtentInfo
var conn *net.TCPConn
conn, err = gConnPool.GetConnect(remoteExtentInfo.Source)
if err != nil {
return errors.Annotatef(err, "streamRepairExtent get conn from host[%v] error", remoteExtentInfo.Source)
return errors.Trace(err, "streamRepairExtent get conn from host[%v] error", remoteExtentInfo.Source)
}
defer gConnPool.PutConnect(conn, true)
if err = request.WriteToConn(conn); err != nil {
err = errors.Annotatef(err, "streamRepairExtent send streamRead to host[%v] error", remoteExtentInfo.Source)
err = errors.Trace(err, "streamRepairExtent send streamRead to host[%v] error", remoteExtentInfo.Source)
log.LogWarnf("action[streamRepairExtent] err[%v].", err)
return
}
@ -457,20 +457,20 @@ func (dp *DataPartition) streamRepairExtent(remoteExtentInfo *storage.ExtentInfo
// read 64k streaming repair packet
if err = reply.ReadFromConn(conn, proto.ReadDeadlineTime); err != nil {
err = errors.Annotatef(err, "streamRepairExtent receive data error")
err = errors.Trace(err, "streamRepairExtent receive data error")
log.LogErrorf("action[streamRepairExtent] err(%v).", err)
return
}
if reply.ResultCode != proto.OpOk {
err = errors.Annotatef(fmt.Errorf("unknow result code"),
err = errors.Trace(fmt.Errorf("unknow result code"),
"streamRepairExtent receive opcode error(%v) ", string(reply.Data[:reply.Size]))
return
}
if reply.ReqID != request.ReqID || reply.PartitionID != request.PartitionID ||
reply.ExtentID != request.ExtentID || reply.Size == 0 || reply.ExtentOffset != int64(currFixOffset) {
err = errors.Annotatef(fmt.Errorf("unavali reply"), "streamRepairExtent receive unavalid "+
err = errors.Trace(fmt.Errorf("unavali reply"), "streamRepairExtent receive unavalid "+
"request(%v) reply(%v)", request.GetUniqueLogId(), reply.GetUniqueLogId())
return
}
@ -483,13 +483,13 @@ func (dp *DataPartition) streamRepairExtent(remoteExtentInfo *storage.ExtentInfo
err = fmt.Errorf("streamRepairExtent crc mismatch expectCrc(%v) actualCrc(%v) extent(%v_%v) start fix from (%v)"+
" remoteSize(%v) localSize(%v) request(%v) reply(%v) ", reply.CRC, actualCrc, dp.partitionID, remoteExtentInfo.String(),
remoteExtentInfo.Source, remoteExtentInfo.Size, currFixOffset, request.GetUniqueLogId(), reply.GetUniqueLogId())
return errors.Annotatef(err, "streamRepairExtent receive data error")
return errors.Trace(err, "streamRepairExtent receive data error")
}
// write to the local extent file
err = store.Write(uint64(localExtentInfo.FileID), int64(currFixOffset), int64(reply.Size), reply.Data, reply.CRC, UpdateSize, BufferWrite)
if err != nil {
err = errors.Annotatef(err, "streamRepairExtent repair data error")
err = errors.Trace(err, "streamRepairExtent repair data error")
return
}
currFixOffset += uint64(reply.Size)

View File

@ -89,7 +89,6 @@ func (d *Disk) computeUsage() (err error) {
return
}
// TODO how about:
// total := math.Max(0, int64(fs.Blocks*uint64(fs.Bsize) - d.ReservedSpace))
total := int64(fs.Blocks*uint64(fs.Bsize) - d.ReservedSpace)
if total < 0 {
@ -97,7 +96,6 @@ func (d *Disk) computeUsage() (err error) {
}
d.Total = uint64(total)
// TODO how about:
// available := math.Max(0, int64(fs.Bavail*uint64(fs.Bsize) - d.ReservedSpace))
available := int64(fs.Bavail*uint64(fs.Bsize) - d.ReservedSpace)
if available < 0 {
@ -105,7 +103,6 @@ func (d *Disk) computeUsage() (err error) {
}
d.Available = uint64(available)
// TODO how about:
// used := math.Max(0, int64(total - available))
used := int64(total - available)
if used < 0 {

View File

@ -31,8 +31,8 @@ import (
"github.com/chubaofs/chubaofs/raftstore"
"github.com/chubaofs/chubaofs/repl"
"github.com/chubaofs/chubaofs/storage"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
raftProto "github.com/tiglabs/raft/proto"
"hash/crc32"
"net"

View File

@ -25,6 +25,7 @@ import (
"github.com/chubaofs/chubaofs/repl"
"github.com/chubaofs/chubaofs/storage"
"github.com/chubaofs/chubaofs/util/log"
"github.com/tiglabs/raft"
"strings"
"sync/atomic"
)
@ -159,9 +160,9 @@ func (dp *DataPartition) CheckLeader(request *repl.Packet, connect net.Conn) (er
// and use another getRaftLeaderAddr() to return the actual address
_, ok := dp.IsRaftLeader()
if !ok {
err = storage.NotALeaderError
err = raft.ErrNotLeader
logContent := fmt.Sprintf("action[ReadCheck] %v.", request.LogMessage(request.GetOpMsg(), connect.RemoteAddr().String(), request.StartT, err))
log.LogInfof(logContent)
log.LogWarnf(logContent)
return
}

View File

@ -29,8 +29,8 @@ import (
"github.com/chubaofs/chubaofs/raftstore"
"github.com/chubaofs/chubaofs/repl"
"github.com/chubaofs/chubaofs/util/config"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
raftproto "github.com/tiglabs/raft/proto"
)
@ -158,7 +158,7 @@ func (dp *DataPartition) StartRaftLoggingSchedule() {
case <-storeAppliedIDTimer.C:
if err := dp.storeAppliedID(dp.appliedID); err != nil {
err = errors.Errorf("[startSchedule]: dump partition=%d: %v", dp.config.PartitionID, err.Error())
err = errors.NewErrorf("[startSchedule]: dump partition=%d: %v", dp.config.PartitionID, err.Error())
log.LogErrorf(err.Error())
}
storeAppliedIDTimer.Reset(time.Second * 10)
@ -333,15 +333,15 @@ func (dp *DataPartition) LoadAppliedID() (err error) {
err = nil
return
}
err = errors.Errorf("[loadApplyIndex] OpenFile: %s", err.Error())
err = errors.NewErrorf("[loadApplyIndex] OpenFile: %s", err.Error())
return
}
if len(data) == 0 {
err = errors.Errorf("[loadApplyIndex]: ApplyIndex is empty")
err = errors.NewErrorf("[loadApplyIndex]: ApplyIndex is empty")
return
}
if _, err = fmt.Sscanf(string(data), "%d", &dp.appliedID); err != nil {
err = errors.Errorf("[loadApplyID] ReadApplyID: %s", err.Error())
err = errors.NewErrorf("[loadApplyID] ReadApplyID: %s", err.Error())
return
}
return
@ -375,7 +375,7 @@ func (s *DataNode) startRaftServer(cfg *config.Config) (err error) {
if _, err = os.Stat(s.raftDir); err != nil {
if err = os.MkdirAll(s.raftDir, 0755); err != nil {
err = errors.Errorf("create raft server dir: %s", err.Error())
err = errors.NewErrorf("create raft server dir: %s", err.Error())
log.LogErrorf("action[startRaftServer] cannot start raft server err[%v]", err)
return
}
@ -402,7 +402,7 @@ func (s *DataNode) startRaftServer(cfg *config.Config) (err error) {
}
s.raftStore, err = raftstore.NewRaftStore(raftConf)
if err != nil {
err = errors.Errorf("new raftStore: %s", err.Error())
err = errors.NewErrorf("new raftStore: %s", err.Error())
log.LogErrorf("action[startRaftServer] cannot start raft server err[%v]", err)
}
@ -481,18 +481,18 @@ func (dp *DataPartition) getPartitionSize() (size uint64, err error) {
target := dp.replicas[0]
conn, err = gConnPool.GetConnect(target) //get remote connect
if err != nil {
err = errors.Annotatef(err, " partition=%v get host[%v] connect", dp.partitionID, target)
err = errors.Trace(err, " partition=%v get host[%v] connect", dp.partitionID, target)
return
}
defer gConnPool.PutConnect(conn, true)
err = p.WriteToConn(conn) // write command to the remote host
if err != nil {
err = errors.Annotatef(err, "partition=%v write to host[%v]", dp.partitionID, target)
err = errors.Trace(err, "partition=%v write to host[%v]", dp.partitionID, target)
return
}
err = p.ReadFromConn(conn, 60)
if err != nil {
err = errors.Annotatef(err, "partition=%v read from host[%v]", dp.partitionID, target)
err = errors.Trace(err, "partition=%v read from host[%v]", dp.partitionID, target)
return
}

View File

@ -20,9 +20,9 @@ import (
"sync/atomic"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"github.com/tiglabs/raft"
raftproto "github.com/tiglabs/raft/proto"
)
@ -37,7 +37,7 @@ func (dp *DataPartition) Apply(command []byte, index uint64) (resp interface{},
if err != nil {
key := fmt.Sprintf("%s_datapartition_apply_err", dp.clusterID)
prefix := fmt.Sprintf("Datapartition(%v)_Extent(%v)", dp.partitionID, extentID)
err = errors.Annotatef(err, prefix)
err = errors.Trace(err, prefix)
exporter.NewAlarm(key)
resp = proto.OpExistErr
dp.stopRaftC <- extentID

View File

@ -50,11 +50,11 @@ var (
)
const (
DefaultRackName = "chubaofs_rack1"
DefaultRackName = "cfs_rack1"
DefaultRaftDir = "raft"
DefaultRaftLogsToRetain = 20000 // Count of raft logs per data partition
DefaultRaftLogsToRetain = 2000 // Count of raft logs per data partition
DefaultDiskMaxErr = 20
DefaultDiskRetain = 30 * util.GB // GB
DefaultDiskRetain = 20 * util.GB // GB
)
const (

View File

@ -148,6 +148,7 @@ func (s *DataNode) getPartitionAPI(w http.ResponseWriter, r *http.Request) {
return
}
result := &struct {
VolName string `json:volName`
ID uint64 `json:"id"`
Size int `json:"size"`
Used int `json:"used"`
@ -158,6 +159,7 @@ func (s *DataNode) getPartitionAPI(w http.ResponseWriter, r *http.Request) {
Replicas []string `json:"replicas"`
TinyDeleteRecordSize int64 `json:"tinyDeleteRecordSize"`
}{
VolName: partition.volumeID,
ID: partition.partitionID,
Size: partition.Size(),
Used: partition.Used(),

View File

@ -23,6 +23,7 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/raftstore"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/log"
)
@ -254,7 +255,7 @@ func (manager *SpaceManager) CreatePartition(request *proto.CreateDataPartitionR
)
for i := 0; i < len(manager.disks); i++ {
disk = manager.minPartitionCnt()
if disk.Available < uint64(dpCfg.PartitionSize) || disk.Status != proto.ReadWrite {
if disk.Available < 5*util.GB || disk.Status != proto.ReadWrite {
disk = nil
continue
}
@ -305,6 +306,7 @@ func (s *DataNode) buildHeartBeatResponse(response *proto.DataNodeHeartbeatRespo
space.RangePartitions(func(partition *DataPartition) bool {
leaderAddr, isLeader := partition.IsRaftLeader()
vr := &proto.PartitionReport{
VolName: partition.volumeID,
PartitionID: uint64(partition.partitionID),
PartitionStatus: partition.Status(),
Total: uint64(partition.Size()),

View File

@ -23,18 +23,17 @@ import (
"strconv"
"time"
"strings"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/repl"
"github.com/chubaofs/chubaofs/storage"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"github.com/tiglabs/raft"
raftProto "github.com/tiglabs/raft/proto"
"hash/crc32"
"strings"
)
func (s *DataNode) OperatePacket(p *repl.Packet, c *net.TCPConn) (err error) {
@ -56,7 +55,7 @@ func (s *DataNode) OperatePacket(p *repl.Packet, c *net.TCPConn) (err error) {
case proto.OpStreamRead, proto.OpRead, proto.OpExtentRepairRead:
case proto.OpReadTinyDelete:
log.LogRead(logContent)
case proto.OpWrite, proto.OpRandomWrite, proto.OpSyncRandomWrite, proto.OpSyncWrite:
case proto.OpWrite, proto.OpRandomWrite, proto.OpSyncRandomWrite, proto.OpSyncWrite, proto.OpMarkDelete:
log.LogWrite(logContent)
default:
log.LogInfo(logContent)
@ -73,9 +72,9 @@ func (s *DataNode) OperatePacket(p *repl.Packet, c *net.TCPConn) (err error) {
case proto.OpStreamRead:
s.handleStreamReadPacket(p, c, StreamRead)
case proto.OpExtentRepairRead:
s.handleStreamReadPacket(p, c, RepairRead)
s.handleExtentRepaiReadPacket(p, c, RepairRead)
case proto.OpMarkDelete:
s.handleMarkDeletePacket(p)
s.handleMarkDeletePacket(p, c)
case proto.OpRandomWrite, proto.OpSyncRandomWrite:
s.handleRandomWritePacket(p)
case proto.OpNotifyReplicasToRepair:
@ -209,7 +208,7 @@ func (s *DataNode) handleHeartbeatPacket(p *repl.Packet) {
}
_, err = MasterHelper.Request("POST", proto.GetDataNodeTaskResponse, nil, data)
if err != nil {
err = errors.Annotatef(err, "heartbeat to master(%v) failed.", request.MasterAddr)
err = errors.Trace(err, "heartbeat to master(%v) failed.", request.MasterAddr)
return
}
}
@ -252,7 +251,7 @@ func (s *DataNode) handlePacketToDeleteDataPartition(p *repl.Packet) {
data, _ := json.Marshal(task)
_, err = MasterHelper.Request("POST", proto.GetDataNodeTaskResponse, nil, data)
if err != nil {
err = errors.Annotatef(err, "delete DataPartition failed,partitionID(%v)", request.PartitionId)
err = errors.Trace(err, "delete DataPartition failed,partitionID(%v)", request.PartitionId)
log.LogErrorf("action[handlePacketToDeleteDataPartition] err(%v).", err)
}
log.LogInfof(fmt.Sprintf("action[handlePacketToDeleteDataPartition] %v error(%v)", request.PartitionId, string(data)))
@ -262,7 +261,9 @@ func (s *DataNode) handlePacketToDeleteDataPartition(p *repl.Packet) {
// Handle OpLoadDataPartition packet.
func (s *DataNode) handlePacketToLoadDataPartition(p *repl.Packet) {
task := &proto.AdminTask{}
err := json.Unmarshal(p.Data, task)
var (
err error
)
defer func() {
if err != nil {
p.PackErrorBody(ActionLoadDataPartition, err.Error())
@ -270,13 +271,18 @@ func (s *DataNode) handlePacketToLoadDataPartition(p *repl.Packet) {
p.PacketOkReply()
}
}()
if err != nil {
return
}
err = json.Unmarshal(p.Data, task)
p.PacketOkReply()
go s.asyncLoadDataPartition(task)
}
func (s *DataNode) asyncLoadDataPartition(task *proto.AdminTask) {
var (
err error
)
request := &proto.LoadDataPartitionRequest{}
response := &proto.LoadDataPartitionResponse{}
if task.OpCode == proto.OpLoadDataPartition {
// TODO unhandled errors
bytes, _ := json.Marshal(task.Request)
json.Unmarshal(bytes, request)
dp := s.space.Partition(request.PartitionId)
@ -306,13 +312,13 @@ func (s *DataNode) handlePacketToLoadDataPartition(p *repl.Packet) {
}
_, err = MasterHelper.Request("POST", proto.GetDataNodeTaskResponse, nil, data)
if err != nil {
err = errors.Annotatef(err, "load DataPartition failed,partitionID(%v)", request.PartitionId)
log.LogError(errors.ErrorStack(err))
err = errors.Trace(err, "load DataPartition failed,partitionID(%v)", request.PartitionId)
log.LogError(errors.Stack(err))
}
}
// Handle OpMarkDelete packet.
func (s *DataNode) handleMarkDeletePacket(p *repl.Packet) {
func (s *DataNode) handleMarkDeletePacket(p *repl.Packet, c net.Conn) {
var (
err error
)
@ -390,12 +396,12 @@ func (s *DataNode) handleRandomWritePacket(p *repl.Packet) {
partition := p.Object.(*DataPartition)
_, isLeader := partition.IsRaftLeader()
if !isLeader {
err = storage.NotALeaderError
err = raft.ErrNotLeader
return
}
err = partition.RandomWriteSubmit(p)
if err != nil && strings.Contains(err.Error(), raft.ErrNotLeader.Error()) {
err = storage.NotALeaderError
err = raft.ErrNotLeader
return
}
@ -409,37 +415,47 @@ func (s *DataNode) handleRandomWritePacket(p *repl.Packet) {
}
}
// Handle OpStreamRead packet.
func (s *DataNode) handleStreamReadPacket(p *repl.Packet, connect net.Conn, isRepairRead bool) {
var (
err error
)
defer func() {
if err != nil {
logContent := fmt.Sprintf("action[OperatePacket] %v.",
p.LogMessage(p.GetOpMsg(), connect.RemoteAddr().String(), p.StartT, err))
log.LogError(logContent)
p.PackErrorBody(ActionStreamRead, err.Error())
p.WriteToConn(connect)
}
}()
partition := p.Object.(*DataPartition)
if !isRepairRead {
err = partition.CheckLeader(p, connect)
if err = partition.CheckLeader(p, connect); err != nil {
return
}
s.handleExtentRepaiReadPacket(p, connect, isRepairRead)
return
}
func (s *DataNode) handleExtentRepaiReadPacket(p *repl.Packet, connect net.Conn, isRepairRead bool) {
var (
err error
)
defer func() {
if err != nil {
p.PackErrorBody(ActionStreamRead, err.Error())
p.WriteToConn(connect)
return
}
}
}()
partition := p.Object.(*DataPartition)
needReplySize := p.Size
offset := p.ExtentOffset
store := partition.ExtentStore()
reply := repl.NewStreamReadResponsePacket(p.ReqID, p.PartitionID, p.ExtentID)
reply.StartT = time.Now().UnixNano()
for {
if needReplySize <= 0 {
break
}
err = nil
reply := repl.NewStreamReadResponsePacket(p.ReqID, p.PartitionID, p.ExtentID)
reply.StartT = p.StartT
currReadSize := uint32(util.Min(int(needReplySize), util.ReadBlockSize))
if currReadSize == util.ReadBlockSize {
reply.Data, _ = proto.Buffers.Get(util.ReadBlockSize)
@ -454,21 +470,12 @@ func (s *DataNode) handleStreamReadPacket(p *repl.Packet, connect net.Conn, isRe
p.CRC = reply.CRC
tpObject.Set()
if err != nil {
reply.PackErrorBody(ActionStreamRead, err.Error())
p.PackErrorBody(ActionStreamRead, err.Error())
if err = reply.WriteToConn(connect); err != nil {
p.PackErrorBody(ActionStreamRead, err.Error())
}
return
}
reply.Size = uint32(currReadSize)
reply.ResultCode = proto.OpOk
p.ResultCode = proto.OpOk
logContent := fmt.Sprintf("action[OperatePacket] %v.",
p.LogMessage(p.GetOpMsg(), connect.RemoteAddr().String(), p.StartT, err))
log.LogRead(logContent)
if err = reply.WriteToConn(connect); err != nil {
p.PackErrorBody(ActionStreamRead, err.Error())
return
}
needReplySize -= currReadSize
@ -476,6 +483,9 @@ func (s *DataNode) handleStreamReadPacket(p *repl.Packet, connect net.Conn, isRe
if currReadSize == util.ReadBlockSize {
proto.Buffers.Put(reply.Data)
}
logContent := fmt.Sprintf("action[operatePacket] %v.",
reply.LogMessage(reply.GetOpMsg(), connect.RemoteAddr().String(), reply.StartT, err))
log.LogReadf(logContent)
}
p.PacketOkReply()
@ -652,7 +662,7 @@ func (s *DataNode) handlePacketToDecommissionDataPartition(p *repl.Packet) {
Status: proto.TaskFailed,
}
if req.AddPeer.ID == req.RemovePeer.ID {
err = errors.Errorf("[opOfflineDataPartition]: AddPeer[%v] same withRemovePeer[%v]", req.AddPeer, req.RemovePeer)
err = errors.NewErrorf("[opOfflineDataPartition]: AddPeer[%v] same withRemovePeer[%v]", req.AddPeer, req.RemovePeer)
resp.Result = err.Error()
goto end
}
@ -677,8 +687,8 @@ end:
data, _ := json.Marshal(adminTask)
_, err = MasterHelper.Request("POST", proto.GetDataNodeTaskResponse, nil, data)
if err != nil {
err = errors.Annotatef(err, "opOfflineDataPartition failed, partitionID(%v)", resp.PartitionId)
log.LogError(errors.ErrorStack(err))
err = errors.Trace(err, "opOfflineDataPartition failed, partitionID(%v)", resp.PartitionId)
log.LogError(errors.Stack(err))
return
}

View File

@ -23,14 +23,11 @@ import (
func (s *DataNode) Post(p *repl.Packet) error {
if p.IsMasterCommand() {
p.NeedReply = false
p.NeedReply = true
}
if isReadExtentOperation(p) {
p.NeedReply = false
}
if p.Opcode == proto.OpCreateDataPartition || p.Opcode == proto.OpDataNodeHeartbeat {
p.NeedReply = true
}
s.cleanupPkt(p)
s.addMetrics(p)
return nil

View File

@ -20,7 +20,6 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/repl"
"github.com/chubaofs/chubaofs/storage"
"github.com/juju/errors"
"hash/crc32"
)
@ -75,7 +74,7 @@ func (s *DataNode) checkCrc(p *repl.Packet) (err error) {
func (s *DataNode) checkPartition(p *repl.Packet) (err error) {
dp := s.space.Partition(p.PartitionID)
if dp == nil {
err = errors.Errorf("partition %v is not exist", p.PartitionID)
err = proto.ErrDataPartitionNotExists
return
}
p.Object = dp

View File

@ -48,10 +48,11 @@ Sample *master.json* is shown as follows,
"id":"1",
"peers": "1:192.168.31.173:80,2:192.168.31.141:80,3:192.168.30.200:80",
"retainLogs":"20000",
"logDir": "/export/Logs/cfs/master",
"logDir": "/export/Logs/master",
"logLevel":"info",
"walDir":"/export/Logs/cfs/raft",
"storeDir":"/export/cfs/rocksdbstore",
"walDir":"/export/Data/master/raft",
"storeDir":"/export/Data/master/rocksdbstore",
"warnLogDir":"/export/home/tomcat/UMP-Monitor/logs/",
"consulAddr": "http://consul.prometheus-cfs.local",
"exporterPort": 9510,
"clusterName":"cfs"
@ -76,11 +77,13 @@ Sample *meta.json is* shown as follows,
"listen": "9021",
"prof": "9092",
"logLevel": "debug",
"metaDir": "/export/cfs/metanode_meta",
"logDir": "/export/Logs/cfs/metanode",
"raftDir": "/export/cfs/metanode_raft",
"metaDir": "/export/Data/metanode",
"logDir": "/export/Logs/metanode",
"raftDir": "/export/Data/metanode/raft",
"raftHeartbeatPort": "9093",
"raftReplicatePort": "9094",
"totalMem": "17179869184",
"warnLogDir":"/export/home/tomcat/UMP-Monitor/logs/",
"consulAddr": "http://consul.prometheus-cfs.local",
"exporterPort": 9511,
"masterAddrs": [
@ -144,6 +147,7 @@ Start Datanode
"logLevel": "info",
"raftHeartbeat": "9095",
"raftReplica": "9096",
"warnLogDir":"/export/home/tomcat/UMP-Monitor/logs/",
"consulAddr": "http://consul.prometheus-cfs.local",
"exporterPort": 9512,
"masterAddr": [
@ -153,7 +157,8 @@ Start Datanode
],
"rack": "",
"disks": [
"/data0:107374182400"
"/data0:21474836480",
"/data1:21474836480",
]
}
@ -186,7 +191,8 @@ Mount Client
"volName": "test",
"owner": "cfs",
"masterAddr": "192.168.31.173:80,192.168.31.141:80,192.168.30.200:80",
"logDir": "/export/Logs/cfs",
"logDir": "/export/Logs/client",
"warnLogDir":"/export/home/tomcat/UMP-Monitor/logs/",
"profPort": "10094",
"logLevel": "info"
}

View File

@ -23,7 +23,8 @@ fuse.json
"volName": "test",
"owner": "cfs",
"masterAddr": "192.168.31.173:80,192.168.31.141:80,192.168.30.200:80",
"logDir": "/export/Logs/cfs",
"warnLogDir":"/export/home/tomcat/UMP-Monitor/logs/",
"logDir": "/export/Logs/client",
"logLevel": "info",
"profPort": "10094"
}
@ -45,6 +46,7 @@ fuse.json
"icacheTimeout", "string", "Inode cache valid duration in client", "No"
"enSyncWrite", "string", "Enable DirectIO sync write, i.e. make sure data is fsynced in data node", "No"
"autoInvalData", "string", "Use AutoInvalData FUSE mount option", "No"
"warnLogDir","string","Warn message directory","No"
Mount
-----

View File

@ -31,6 +31,8 @@ Configurations
"masterAddr", "string slice", "Addresses of master server", "Yes"
"rack", "string", "Identity of rack", "No"
"disks", "string slice", "PATH:MAX_ERRS:REST_SIZE", "Yes"
"warnLogDir","string","Warn message directory","No"
**Example:**
@ -43,8 +45,9 @@ Configurations
"logDir": "/export/Logs/datanode",
"logLevel": "debug",
"raftHeartbeat": "9095",
"warnLogDir":"/export/home/tomcat/UMP-Monitor/logs/",
"raftReplica": "9096",
"raftDir": "/export/Logs/datanode/raft",
"raftDir": "/export/Data/datanode/raft",
"consulAddr": "http://consul.prometheus-cfs.local",
"exporterPort": 9512,
"masterAddr": [
@ -54,8 +57,8 @@ Configurations
],
"rack": "main",
"disks": [
"/data0:107374182400",
"/data1:107374182400"
"/data0:21474836480",
"/data1:21474836480"
]
}

View File

@ -33,6 +33,8 @@ ChubaoFS use **JSON** as configuration file format.
"clusterName", "string", "The cluster identifier", "Yes"
"exporterPort", "int", "The prometheus exporter port", "No"
"consulAddr", "string", "The consul register addr for prometheus exporter", "No"
"warnLogDir","string","Warn message directory","No"
**Example:**
@ -45,11 +47,12 @@ ChubaoFS use **JSON** as configuration file format.
"prof":"10088",
"id":"1",
"peers": "1:127.0.0.1:8080,1:127.0.0.1:8081,1:127.0.0.1:8082",
"logDir": "/export/master",
"logLevel":"DEBUG",
"retainLogs":"2000",
"walDir":"/export/raft",
"storeDir":"/export/rocks",
"retainLogs":"20000",
"logDir": "/export/Logs/master",
"logLevel":"info",
"walDir":"/export/Data/master/raft",
"storeDir":"/export/Data/master/rocksdbstore",
"warnLogDir":"/export/home/tomcat/UMP-Monitor/logs/",
"exporterPort": 9510,
"consulAddr": "http://consul.prometheus-cfs.local",
"clusterName":"test"

View File

@ -18,6 +18,9 @@ Metanode is the manager of meta partitions and replicated by MultiRaft. Each met
"consulAddr", "string", "Addresses of monitor system", "No"
"exporterPort", "string", "Port for monitor system", "No"
"masterAddrs", "string", "Addresses of master server", "Yes"
"warnLogDir","string","Warn message directory","No"
"totalMem","string","max memory metadata used","No"
@ -30,13 +33,15 @@ Example:
"listen": "9021",
"prof": "9092",
"logLevel": "debug",
"metadataDir": "/export/cfs/metanode_meta",
"logDir": "/export/Logs/cfs/metanode",
"raftDir": "/export/cfs/metanode_raft",
"metaDir": "/export/Data/metanode",
"logDir": "/export/Logs/metanode",
"raftDir": "/export/Data/metanode/raft",
"warnLogDir":"/export/home/tomcat/UMP-Monitor/logs/",
"raftHeartbeatPort": "9093",
"raftReplicaPort": "9094",
"consulAddr": "http://consul.prometheus-cfs.local",
"exporterPort": 9511,
"exporterPort": 9511,
"totalMem": "17179869184",
"masterAddrs": [
"192.168.31.173:80",
"192.168.31.141:80",

View File

@ -12,7 +12,7 @@ ChubaoFS use prometheus as metrics collector. It simply config as follow in mast
* exporterPortprometheus exporter Port. when setcan export prometheus metrics from URL(http://$hostip:$exporterPort/metrics). If not set, prometheus exporter will unavailable
* consulAddr: consul register addressit can work with prometheus to auto discover deployed cfs nodes, if not set, consul register will not work.
* consulAddr: consul register addressit can work with prometheus to auto discover deployed chubaofs nodes, if not set, consul register will not work.
Using grafana as prometheus metrics web front

View File

@ -22,8 +22,8 @@ import (
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"net"
)
@ -117,14 +117,14 @@ func (sender *AdminTaskManager) sendTasks(tasks []*proto.AdminTask) {
for _, task := range tasks {
conn, err := sender.connPool.GetConnect(sender.targetAddr)
if err != nil {
msg := fmt.Sprintf("clusterID[%v] get connection to %v,err,%v", sender.clusterID, sender.targetAddr, errors.ErrorStack(err))
msg := fmt.Sprintf("clusterID[%v] get connection to %v,err,%v", sender.clusterID, sender.targetAddr, errors.Stack(err))
WarnBySpecialKey(fmt.Sprintf("%v_%v_sendTask", sender.clusterID, ModuleName), msg)
sender.connPool.PutConnect(conn, true)
sender.updateTaskInfo(task, false)
break
}
if err = sender.sendAdminTask(task, conn); err != nil {
log.LogError(fmt.Sprintf("send task %v to %v,err,%v", task.ToString(), sender.targetAddr, errors.ErrorStack(err)))
log.LogError(fmt.Sprintf("send task %v to %v,err,%v", task.ToString(), sender.targetAddr, errors.Stack(err)))
sender.connPool.PutConnect(conn, true)
sender.updateTaskInfo(task, true)
continue
@ -157,13 +157,13 @@ func (sender *AdminTaskManager) buildPacket(task *proto.AdminTask) (packet *prot
func (sender *AdminTaskManager) sendAdminTask(task *proto.AdminTask, conn net.Conn) (err error) {
packet, err := sender.buildPacket(task)
if err != nil {
return errors.Annotatef(err, "action[sendAdminTask build packet failed,task:%v]", task.ID)
return errors.Trace(err, "action[sendAdminTask build packet failed,task:%v]", task.ID)
}
if err = packet.WriteToConn(conn); err != nil {
return errors.Annotatef(err, "action[sendAdminTask],WriteToConn failed,task:%v", task.ID)
return errors.Trace(err, "action[sendAdminTask],WriteToConn failed,task:%v", task.ID)
}
if err = packet.ReadFromConn(conn, proto.ReadDeadlineTime); err != nil {
return errors.Annotatef(err, "action[sendAdminTask],ReadFromConn failed task:%v", task.ID)
return errors.Trace(err, "action[sendAdminTask],ReadFromConn failed task:%v", task.ID)
}
log.LogDebugf(fmt.Sprintf("action[sendAdminTask] sender task:%v success", task.ToString()))
sender.updateTaskInfo(task, true)
@ -175,13 +175,13 @@ func (sender *AdminTaskManager) syncSendAdminTask(task *proto.AdminTask, conn ne
log.LogInfof(fmt.Sprintf("action[syncSendAdminTask] sender task:%v begin", task.ToString()))
packet, err := sender.buildPacket(task)
if err != nil {
return nil, errors.Annotatef(err, "action[syncSendAdminTask build packet failed,task:%v]", task.ID)
return nil, errors.Trace(err, "action[syncSendAdminTask build packet failed,task:%v]", task.ID)
}
if err = packet.WriteToConn(conn); err != nil {
return nil, errors.Annotatef(err, "action[syncSendAdminTask],WriteToConn failed,task:%v", task.ID)
return nil, errors.Trace(err, "action[syncSendAdminTask],WriteToConn failed,task:%v", task.ID)
}
if err = packet.ReadFromConn(conn, proto.SyncSendTaskDeadlineTime); err != nil {
return nil, errors.Annotatef(err, "action[syncSendAdminTask],ReadFromConn failed task:%v", task.ID)
return nil, errors.Trace(err, "action[syncSendAdminTask],ReadFromConn failed task:%v", task.ID)
}
if packet.ResultCode != proto.OpOk {
err = fmt.Errorf(string(packet.Data))

View File

@ -23,8 +23,8 @@ import (
"bytes"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"io/ioutil"
"regexp"
"strings"
@ -519,7 +519,6 @@ func (m *Server) decommissionDisk(w http.ResponseWriter, r *http.Request) {
}
rstMsg = fmt.Sprintf("recive decommissionDisk node[%v] disk[%v], badPartitionIds[%v] has offline successfully",
node.Addr, diskPath, badPartitionIds)
m.cluster.BadDataPartitionIds.Store(fmt.Sprintf("%s:%s", offLineAddr, diskPath), badPartitionIds)
if err = m.cluster.decommissionDisk(node, diskPath, badPartitionIds); err != nil {
sendErrReply(w, r, newErrHTTPReply(err))
return

View File

@ -19,8 +19,8 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/raftstore"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"sync"
"time"
)
@ -290,7 +290,7 @@ func (c *Cluster) addMetaNode(nodeAddr string) (id uint64, err error) {
errHandler:
err = fmt.Errorf("action[addMetaNode],clusterID[%v] metaNodeAddr:%v err:%v ",
c.Name, nodeAddr, err.Error())
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
Warn(c.Name, err.Error())
return
}
@ -344,7 +344,7 @@ func (c *Cluster) addDataNode(nodeAddr string) (id uint64, err error) {
return
errHandler:
err = fmt.Errorf("action[addDataNode],clusterID[%v] dataNodeAddr:%v err:%v ", c.Name, nodeAddr, err.Error())
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
Warn(c.Name, err.Error())
return
}
@ -384,7 +384,7 @@ func (c *Cluster) getVol(volName string) (vol *Vol, err error) {
defer c.volMutex.RUnlock()
vol, ok := c.vols[volName]
if !ok {
err = errors.Annotatef(volNotFound(volName), "%v not found", volName)
err = errors.Trace(volNotFound(volName), "%v not found", volName)
}
return
}
@ -491,7 +491,7 @@ func (c *Cluster) createDataPartition(volName string) (dp *DataPartition, err er
return
errHandler:
err = fmt.Errorf("action[createDataPartition],clusterID[%v] vol[%v] Err:%v ", c.Name, volName, err.Error())
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
Warn(c.Name, err.Error())
return
}
@ -545,22 +545,22 @@ func (c *Cluster) chooseTargetDataNodes(replicaNum int) (hosts []string, peers [
peers = make([]proto.Peer, 0)
ns, err := c.t.allocNodeSetForDataNode(uint8(replicaNum))
if err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
if ns.isSingleRack() {
var newHosts []string
if rack, err = ns.getRack(ns.racks[0]); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
if newHosts, peers, err = rack.getAvailDataNodeHosts(hosts, replicaNum); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
hosts = newHosts
return
}
if racks, err = ns.allocRacks(replicaNum, nil); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
if len(racks) == 2 {
@ -569,12 +569,12 @@ func (c *Cluster) chooseTargetDataNodes(replicaNum int) (hosts []string, peers [
masterReplicaNum := replicaNum/2 + 1
slaveReplicaNum := replicaNum - masterReplicaNum
if masterAddr, masterPeers, err = masterRack.getAvailDataNodeHosts(hosts, masterReplicaNum); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
hosts = append(hosts, masterAddr...)
peers = append(peers, masterPeers...)
if addrs, slavePeers, err = slaveRack.getAvailDataNodeHosts(hosts, slaveReplicaNum); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
hosts = append(hosts, addrs...)
peers = append(peers, slavePeers...)
@ -583,7 +583,7 @@ func (c *Cluster) chooseTargetDataNodes(replicaNum int) (hosts []string, peers [
rack := racks[index]
var selectPeers []proto.Peer
if addrs, selectPeers, err = rack.getAvailDataNodeHosts(hosts, 1); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
hosts = append(hosts, addrs...)
peers = append(peers, selectPeers...)
@ -598,7 +598,7 @@ func (c *Cluster) chooseTargetDataNodes(replicaNum int) (hosts []string, peers [
func (c *Cluster) dataNode(addr string) (dataNode *DataNode, err error) {
value, ok := c.dataNodes.Load(addr)
if !ok {
err = errors.Annotatef(dataNodeNotFound(addr), "%v not found", addr)
err = errors.Trace(dataNodeNotFound(addr), "%v not found", addr)
return
}
dataNode = value.(*DataNode)
@ -608,7 +608,7 @@ func (c *Cluster) dataNode(addr string) (dataNode *DataNode, err error) {
func (c *Cluster) metaNode(addr string) (metaNode *MetaNode, err error) {
value, ok := c.metaNodes.Load(addr)
if !ok {
err = errors.Annotatef(metaNodeNotFound(addr), "%v not found", addr)
err = errors.Trace(metaNodeNotFound(addr), "%v not found", addr)
return
}
metaNode = value.(*MetaNode)
@ -669,8 +669,6 @@ func (c *Cluster) decommissionDataPartition(offlineAddr string, dp *DataPartitio
removePeer proto.Peer
replica *DataReplica
)
badPartitionIDs := make([]uint64, 0)
badPartitionIDs = append(badPartitionIDs, dp.PartitionID)
dp.Lock()
defer dp.Unlock()
if ok := dp.hasHost(offlineAddr); !ok {
@ -681,10 +679,6 @@ func (c *Cluster) decommissionDataPartition(offlineAddr string, dp *DataPartitio
goto errHandler
}
if replica, err = dp.getReplica(offlineAddr); err != nil {
goto errHandler
}
if err = dp.hasMissingOneReplica(int(vol.dpReplicaNum)); err != nil {
goto errHandler
}
@ -730,6 +724,7 @@ func (c *Cluster) decommissionDataPartition(offlineAddr string, dp *DataPartitio
if err = dp.updateForOffline(offlineAddr, newAddr, dp.VolName, newPeers, c); err != nil {
goto errHandler
}
replica, _ = dp.getReplica(offlineAddr)
dp.removeReplicaByAddr(offlineAddr)
dp.checkAndRemoveMissReplica(offlineAddr)
tasks = make([]*proto.AdminTask, 0)
@ -743,7 +738,7 @@ func (c *Cluster) decommissionDataPartition(offlineAddr string, dp *DataPartitio
}
dp.Status = proto.ReadOnly
dp.isRecover = true
c.BadDataPartitionIds.Store(fmt.Sprintf("%s:%s", offlineAddr, replica.DiskPath), badPartitionIDs)
c.putBadDataPartitionIDs(replica, offlineAddr, dp.PartitionID)
log.LogWarnf("clusterID[%v] partitionID:%v on Node:%v offline success,newHost[%v],PersistenceHosts:[%v]",
c.Name, dp.PartitionID, offlineAddr, newAddr, dp.Hosts)
return
@ -757,6 +752,22 @@ errHandler:
return
}
func (c *Cluster) putBadDataPartitionIDs(replica *DataReplica, offlineAddr string, partitionID uint64) {
var key string
newBadPartitionIDs := make([]uint64, 0)
if replica != nil {
key = fmt.Sprintf("%s:%s", offlineAddr, replica.DiskPath)
} else {
key = fmt.Sprintf("%s:%s", offlineAddr, "")
}
badPartitionIDs, ok := c.BadDataPartitionIds.Load(key)
if ok {
newBadPartitionIDs = badPartitionIDs.([]uint64)
}
newBadPartitionIDs = append(newBadPartitionIDs, partitionID)
c.BadDataPartitionIds.Store(key, newBadPartitionIDs)
}
func (c *Cluster) decommissionMetaNode(metaNode *MetaNode) {
msg := fmt.Sprintf("action[decommissionMetaNode],clusterID[%v] Node[%v] OffLine", c.Name, metaNode.Addr)
log.LogWarn(msg)
@ -812,7 +823,7 @@ func (c *Cluster) updateVol(name, authKey string, capacity int) (err error) {
return
errHandler:
err = fmt.Errorf("action[updateVol], clusterID[%v] name:%v, err:%v ", c.Name, name, err.Error())
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
Warn(c.Name, err.Error())
return
}
@ -863,7 +874,7 @@ func (c *Cluster) createVol(name, owner string, size, capacity int) (vol *Vol, e
errHandler:
err = fmt.Errorf("action[createVol], clusterID[%v] name:%v, err:%v ", c.Name, name, err)
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
Warn(c.Name, err.Error())
return
}
@ -881,7 +892,7 @@ func (c *Cluster) doCreateVol(name, owner string, dpSize, capacity uint64) (err
return
errHandler:
err = fmt.Errorf("action[doCreateVol], clusterID[%v] name:%v, err:%v ", c.Name, name, err.Error())
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
Warn(c.Name, err.Error())
return
}
@ -936,11 +947,11 @@ func (c *Cluster) createMetaPartition(volName string, start, end uint64) (err er
errChannel := make(chan error, vol.mpReplicaNum)
if hosts, peers, err = c.chooseTargetMetaHosts(int(vol.mpReplicaNum)); err != nil {
return errors.Trace(err)
return errors.NewError(err)
}
log.LogInfof("target meta hosts:%v,peers:%v", hosts, peers)
if partitionID, err = c.idAlloc.allocateMetaPartitionID(); err != nil {
return errors.Trace(err)
return errors.NewError(err)
}
mp = newMetaPartition(partitionID, start, end, vol.mpReplicaNum, volName, vol.ID)
mp.setHosts(hosts)
@ -981,12 +992,12 @@ func (c *Cluster) createMetaPartition(volName string, start, end uint64) (err er
c.addMetaNodeTasks(tasks)
}(host)
}
return errors.Trace(err)
return errors.NewError(err)
default:
mp.Status = proto.ReadWrite
}
if err = c.syncAddMetaPartition(mp); err != nil {
return errors.Trace(err)
return errors.NewError(err)
}
vol.addMetaPartition(mp)
log.LogInfof("action[createMetaPartition] success,volName[%v],partition[%v]", volName, partitionID)
@ -1018,12 +1029,12 @@ func (c *Cluster) chooseTargetMetaHosts(replicaNum int) (hosts []string, peers [
ns *nodeSet
)
if ns, err = c.t.allocNodeSetForMetaNode(uint8(replicaNum)); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
hosts = make([]string, 0)
if masterAddr, masterPeer, err = ns.getAvailMetaNodeHosts(hosts, 1); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
peers = append(peers, masterPeer...)
hosts = append(hosts, masterAddr[0])
@ -1032,7 +1043,7 @@ func (c *Cluster) chooseTargetMetaHosts(replicaNum int) (hosts []string, peers [
return
}
if slaveAddrs, slavePeers, err = ns.getAvailMetaNodeHosts(hosts, otherReplica); err != nil {
return nil, nil, errors.Trace(err)
return nil, nil, errors.NewError(err)
}
hosts = append(hosts, slaveAddrs...)
peers = append(peers, slavePeers...)
@ -1175,3 +1186,9 @@ func (c *Cluster) setDisableAutoAllocate(disableAutoAllocate bool) (err error) {
}
return
}
func (c *Cluster) clearVols() {
c.volMutex.Lock()
defer c.volMutex.Unlock()
c.vols = make(map[string]*Vol, 0)
}

View File

@ -18,8 +18,8 @@ import (
"encoding/json"
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"runtime"
"sync"
"time"
@ -157,7 +157,7 @@ func (c *Cluster) decommissionMetaPartition(nodeAddr string, mp *MetaPartition)
errHandler:
log.LogError(fmt.Sprintf("action[decommissionMetaPartition],volName: %v,partitionID: %v,err: %v",
mp.volName, mp.PartitionID, errors.ErrorStack(err)))
mp.volName, mp.PartitionID, errors.Stack(err)))
Warn(c.Name, fmt.Sprintf("clusterID[%v] meta partition[%v] offline addr[%v] failed,err:%v",
c.Name, mp.PartitionID, nodeAddr, err))
return
@ -401,7 +401,7 @@ func (c *Cluster) dealCreateMetaPartitionResp(nodeAddr string, resp *proto.Creat
log.LogInfof("action[dealCreateMetaPartitionResp] process resp from nodeAddr[%v] pid[%v] success", nodeAddr, resp.PartitionID)
return
errHandler:
log.LogErrorf(fmt.Sprintf("action[dealCreateMetaPartitionResp] %v", errors.ErrorStack(err)))
log.LogErrorf(fmt.Sprintf("action[dealCreateMetaPartitionResp] %v", errors.Stack(err)))
return
}
@ -435,7 +435,7 @@ func (c *Cluster) dealMetaNodeHeartbeatResp(nodeAddr string, resp *proto.MetaNod
log.LogInfof(logMsg)
return
errHandler:
logMsg = fmt.Sprintf("nodeAddr %v heartbeat error :%v", nodeAddr, errors.ErrorStack(err))
logMsg = fmt.Sprintf("nodeAddr %v heartbeat error :%v", nodeAddr, errors.Stack(err))
log.LogError(logMsg)
return
}

View File

@ -18,8 +18,8 @@ import (
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"math"
"strings"
"sync"
@ -235,7 +235,7 @@ func (partition *DataPartition) getReplica(addr string) (replica *DataReplica, e
}
log.LogErrorf("action[getReplica],partitionID:%v,locations:%v,err:%v",
partition.PartitionID, addr, dataReplicaNotFound(addr))
return nil, errors.Annotatef(dataReplicaNotFound(addr), "%v not found", addr)
return nil, errors.Trace(dataReplicaNotFound(addr), "%v not found", addr)
}
func (partition *DataPartition) convertToDataPartitionResponse() (dpr *proto.DataPartitionResponse) {
@ -455,7 +455,7 @@ func (partition *DataPartition) getReplicaIndex(addr string) (index int, err err
}
log.LogErrorf("action[getReplicaIndex],partitionID:%v,location:%v,err:%v",
partition.PartitionID, addr, dataReplicaNotFound(addr))
return -1, errors.Annotatef(dataReplicaNotFound(addr), "%v not found ", addr)
return -1, errors.Trace(dataReplicaNotFound(addr), "%v not found ", addr)
}
func (partition *DataPartition) updateForOffline(offlineAddr, newAddr, volName string, newPeers []proto.Peer, c *Cluster) (err error) {
@ -478,7 +478,7 @@ func (partition *DataPartition) updateForOffline(offlineAddr, newAddr, volName s
if err = c.syncUpdateDataPartition(partition); err != nil {
partition.Hosts = orgHosts
partition.Peers = oldPeers
return errors.Annotatef(err, "update partition[%v] failed", partition.PartitionID)
return errors.Trace(err, "update partition[%v] failed", partition.PartitionID)
}
msg := fmt.Sprintf("action[updateForOffline] partitionID:%v offlineAddr:%v newAddr:%v"+
"oldHosts:%v newHosts:%v,oldPees[%v],newPeers[%v]",

View File

@ -209,7 +209,6 @@ func (partition *DataPartition) missingReplicaAddress(dataPartitionSize uint64)
partition.PartitionID, addr))
err = proto.ErrMissingReplica
addr = addr
partition.isRecover = true
break
}
}

View File

@ -18,8 +18,8 @@ import (
"encoding/json"
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"runtime"
"sync"
"time"
@ -51,7 +51,7 @@ func (dpMap *DataPartitionMap) get(ID uint64) (*DataPartition, error) {
if v, ok := dpMap.partitionMap[ID]; ok {
return v, nil
}
return nil, errors.Annotatef(dataPartitionNotFound(ID), "[%v] not found in [%v]", ID, dpMap.volName)
return nil, errors.Trace(dataPartitionNotFound(ID), "[%v] not found in [%v]", ID, dpMap.volName)
}
func (dpMap *DataPartitionMap) put(dp *DataPartition) {

View File

@ -80,8 +80,14 @@ func (m *Server) handlerWithInterceptor() http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
if m.partition.IsRaftLeader() {
m.ServeHTTP(w, r)
return
if m.metaReady {
m.ServeHTTP(w, r)
return
} else {
log.LogWarnf("action[handlerWithInterceptor] leader meta has not ready")
http.Error(w, m.leaderInfo.addr, http.StatusBadRequest)
return
}
}
if m.leaderInfo.addr == "" {
log.LogErrorf("action[handlerWithInterceptor] no leader,request[%v]", r.URL)

View File

@ -35,12 +35,17 @@ func (m *Server) handleLeaderChange(leader uint64) {
log.LogWarnf("action[handleLeaderChange] change leader to [%v] ", m.leaderInfo.addr)
m.reverseProxy = m.newReverseProxy()
// once switching to the master, check the Heartbeat
if m.id == leader {
Warn(m.clusterName, fmt.Sprintf("clusterID[%v] leader is changed to %v",
m.clusterName, m.leaderInfo.addr))
m.cluster.checkMetaNodeHeartbeat()
m.loadMetadata()
m.metaReady = true
m.cluster.checkDataNodeHeartbeat()
m.cluster.checkMetaNodeHeartbeat()
} else {
Warn(m.clusterName, fmt.Sprintf("clusterID[%v] leader is changed to %v",
m.clusterName, m.leaderInfo.addr))
m.metaReady = false
}
}
@ -82,7 +87,9 @@ func (m *Server) restoreIDAlloc() {
// Load stored metadata into the memory
func (m *Server) loadMetadata() {
log.LogInfo("action[loadMetadata] begin")
m.clearMetadata()
m.restoreIDAlloc()
m.cluster.fsm.restore()
var err error
if err = m.cluster.loadClusterValue(); err != nil {
panic(err)
@ -112,3 +119,8 @@ func (m *Server) loadMetadata() {
log.LogInfo("action[loadMetadata] end")
}
func (m *Server) clearMetadata() {
m.cluster.clearVols()
m.cluster.t = newTopology()
}

View File

@ -19,8 +19,8 @@ import (
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"strings"
"time"
)
@ -458,7 +458,7 @@ func (mp *MetaPartition) buildNewMetaPartitionTasks(specifyAddrs []string, peers
func (mp *MetaPartition) createTaskToDecommissionReplica(volName string, removePeer proto.Peer, addPeer proto.Peer) (t *proto.AdminTask, err error) {
mr, err := mp.getMetaReplicaLeader()
if err != nil {
return nil, errors.Trace(err)
return nil, errors.NewError(err)
}
req := &proto.MetaPartitionDecommissionRequest{PartitionID: mp.PartitionID, VolName: volName, RemovePeer: removePeer, AddPeer: addPeer}
t = proto.NewAdminTask(proto.OpDecommissionMetaPartition, mr.Addr, req)

View File

@ -18,8 +18,8 @@ import (
"encoding/json"
"fmt"
bsProto "github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"github.com/tiglabs/raft/proto"
"strconv"
"strings"

View File

@ -20,9 +20,9 @@ import (
"encoding/json"
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/ump"
"math/rand"
"strings"
"time"
@ -153,19 +153,19 @@ func Warn(clusterID, msg string) {
// WarnBySpecialKey provides warnings when exits
func WarnBySpecialKey(key, msg string) {
log.LogWarn(msg)
exporter.NewAlarm(key)
ump.Alarm(key, msg)
}
func keyNotFound(name string) (err error) {
return errors.Errorf("parameter %v not found", name)
return errors.NewErrorf("parameter %v not found", name)
}
func unmatchedKey(name string) (err error) {
return errors.Errorf("parameter %v not match", name)
return errors.NewErrorf("parameter %v not match", name)
}
func notFoundMsg(name string) (err error) {
return errors.Errorf("%v not found", name)
return errors.NewErrorf("%v not found", name)
}
func metaPartitionNotFound(id uint64) (err error) {

View File

@ -19,9 +19,9 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/raftstore"
"github.com/chubaofs/chubaofs/util/config"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"net/http/httputil"
"strconv"
"sync"
@ -60,6 +60,7 @@ type Server struct {
partition raftstore.Partition
wg sync.WaitGroup
reverseProxy *httputil.ReverseProxy
metaReady bool
}
// NewServer creates a new server
@ -73,14 +74,14 @@ func (m *Server) Start(cfg *config.Config) (err error) {
m.leaderInfo = &LeaderInfo{}
m.reverseProxy = m.newReverseProxy()
if err = m.checkConfig(cfg); err != nil {
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
return
}
m.rocksDBStore = raftstore.NewRocksDBStore(m.storeDir, LRUCacheSize, WriteBufferSize)
m.initFsm()
m.initCluster()
if err = m.createRaftServer(); err != nil {
log.LogError(errors.ErrorStack(err))
log.LogError(errors.Stack(err))
return
}
m.cluster.partition = m.partition
@ -175,7 +176,7 @@ func (m *Server) checkConfig(cfg *config.Config) (err error) {
func (m *Server) createRaftServer() (err error) {
raftCfg := &raftstore.Config{NodeID: m.id, RaftPath: m.walDir, NumOfLogsToRetain: m.retainLogs}
if m.raftStore, err = raftstore.NewRaftStore(raftCfg); err != nil {
return errors.Annotatef(err, "NewRaftStore failed! id[%v] walPath[%v]", m.id, m.walDir)
return errors.Trace(err, "NewRaftStore failed! id[%v] walPath[%v]", m.id, m.walDir)
}
fmt.Println(m.config.peers)
partitionCfg := &raftstore.PartitionConfig{
@ -185,7 +186,7 @@ func (m *Server) createRaftServer() (err error) {
SM: m.fsm,
}
if m.partition, err = m.raftStore.CreatePartition(partitionCfg); err != nil {
return errors.Annotate(err, "CreatePartition failed")
return errors.Trace(err, "CreatePartition failed")
}
return
}

View File

@ -17,8 +17,8 @@ package master
import (
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"sort"
"sync"
)
@ -105,7 +105,7 @@ func (t *topology) deleteDataNode(dataNode *DataNode) {
func (t *topology) getRack(dataNode *DataNode) (rack *Rack, err error) {
topoNode, ok := t.dataNodes.Load(dataNode.Addr)
if !ok {
return nil, errors.Annotatef(dataNodeNotFound(dataNode.Addr), "%v not found", dataNode.Addr)
return nil, errors.Trace(dataNodeNotFound(dataNode.Addr), "%v not found", dataNode.Addr)
}
node := topoNode.(*topoDataNode)
ns, err := t.getNodeSet(node.setID)
@ -189,7 +189,7 @@ func (t *topology) getNodeSet(setID uint64) (ns *nodeSet, err error) {
defer t.nsLock.RUnlock()
ns, ok := t.nodeSetMap[setID]
if !ok {
return nil, errors.Errorf("set %v not found", setID)
return nil, errors.NewErrorf("set %v not found", setID)
}
return
}
@ -363,7 +363,7 @@ func (ns *nodeSet) getRack(name string) (rack *Rack, err error) {
defer ns.rackLock.RUnlock()
rack, ok := ns.rackMap[name]
if !ok {
return nil, errors.Annotatef(rackNotFound(name), "%v not found", name)
return nil, errors.Trace(rackNotFound(name), "%v not found", name)
}
return
}
@ -494,7 +494,7 @@ func (rack *Rack) putDataNode(dataNode *DataNode) {
func (rack *Rack) getDataNode(addr string) (dataNode *DataNode, err error) {
value, ok := rack.dataNodes.Load(addr)
if !ok {
return nil, errors.Annotatef(dataNodeNotFound(addr), "%v not found", addr)
return nil, errors.Trace(dataNodeNotFound(addr), "%v not found", addr)
}
dataNode = value.(*DataNode)
return

View File

@ -16,7 +16,7 @@ package metanode
import (
"github.com/chubaofs/chubaofs/proto"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"time"
)
@ -129,6 +129,7 @@ const (
cfgMasterAddrs = "masterAddrs"
cfgRaftHeartbeatPort = "raftHeartbeatPort"
cfgRaftReplicaPort = "raftReplicaPort"
cfgTotalMem = "totalMem"
)
const (

View File

@ -30,9 +30,9 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/raftstore"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
)
const partitionPrefix = "partition_"
@ -116,13 +116,12 @@ func (m *metadataManager) HandleMetadataOperation(conn net.Conn, p *Packet,
err = m.opDecommissionMetaPartition(conn, p, remoteAddr)
case proto.OpMetaBatchInodeGet:
err = m.opMetaBatchInodeGet(conn, p, remoteAddr)
case proto.OpPing:
default:
err = fmt.Errorf("%s unknown Opcode: %d, reqId: %d", remoteAddr,
p.Opcode, p.GetReqID())
}
if err != nil {
err = errors.Errorf("%s [%s] req: %d - %s", remoteAddr, p.GetOpMsg(),
err = errors.NewErrorf("%s [%s] req: %d - %s", remoteAddr, p.GetOpMsg(),
p.GetReqID(), err.Error())
}
return
@ -246,7 +245,7 @@ func (m *metadataManager) loadPartitions() (err error) {
backupDir := path.Join(partitionConfig.RootDir, snapshotBackup)
if _, err = os.Stat(backupDir); err == nil {
if err = os.Rename(backupDir, snapshotDir); err != nil {
err = errors.Annotate(err,
err = errors.Trace(err,
fmt.Sprintf(": fail recover backup snapshot %s",
snapshotDir))
return
@ -293,7 +292,7 @@ func (m *metadataManager) createPartition(id uint64, volName string, start,
end uint64, peers []proto.Peer) (err error) {
// check partitions
if _, err = m.getPartition(id); err == nil {
err = errors.Errorf("create partition id=%d is exsited!", id)
err = errors.NewErrorf("create partition id=%d is exsited!", id)
return
}
err = nil
@ -317,13 +316,13 @@ func (m *metadataManager) createPartition(id uint64, volName string, start,
}
partition := NewMetaPartition(mpc)
if err = partition.PersistMetadata(); err != nil {
err = errors.Errorf("[createPartition]->%s", err.Error())
err = errors.NewErrorf("[createPartition]->%s", err.Error())
return
}
if err = m.attachPartition(id, partition); err != nil {
// TODO Unhandled errors
os.RemoveAll(mpc.RootDir)
err = errors.Errorf("[createPartition]->%s", err.Error())
err = errors.NewErrorf("[createPartition]->%s", err.Error())
return
}
return

View File

@ -22,8 +22,8 @@ import (
"bytes"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
raftProto "github.com/tiglabs/raft/proto"
)
@ -47,7 +47,8 @@ func (m *metadataManager) opMasterHeartbeat(conn net.Conn, p *Packet,
}
// collect memory info
resp.Total, resp.Used, err = util.GetMemInfo()
resp.Total = configTotalMem
resp.Used, err = util.GetProcessMemory(os.Getpid())
if err != nil {
adminTask.Status = proto.TaskFailed
goto end
@ -101,7 +102,7 @@ func (m *metadataManager) opCreateMetaPartition(conn net.Conn, p *Packet,
decode := json.NewDecoder(bytes.NewBuffer(p.Data))
decode.UseNumber()
if err = decode.Decode(adminTask); err != nil {
err = errors.Errorf("[opCreateMetaPartition]: Unmarshal AdminTask"+
err = errors.NewErrorf("[opCreateMetaPartition]: Unmarshal AdminTask"+
" struct: %s", err.Error())
return
}
@ -110,7 +111,7 @@ func (m *metadataManager) opCreateMetaPartition(conn net.Conn, p *Packet,
// create a new meta partition.
if err = m.createPartition(req.PartitionID, req.VolName,
req.Start, req.End, req.Members); err != nil {
err = errors.Errorf("[opCreateMetaPartition]->%s; request message: %v",
err = errors.NewErrorf("[opCreateMetaPartition]->%s; request message: %v",
err.Error(), adminTask.Request)
return
}
@ -314,14 +315,14 @@ func (m *metadataManager) opMetaInodeGet(conn net.Conn, p *Packet,
if err = json.Unmarshal(p.Data, req); err != nil {
p.PacketErrorWithBody(proto.OpErr, nil)
m.respondToClient(conn, p)
err = errors.Errorf("[opMetaInodeGet]: %s", err.Error())
err = errors.NewErrorf("[opMetaInodeGet]: %s", err.Error())
return
}
mp, err := m.getPartition(req.PartitionID)
if err != nil {
p.PacketErrorWithBody(proto.OpNotExistErr, nil)
m.respondToClient(conn, p)
err = errors.Errorf("[opMetaInodeGet] %s, req: %s", err.Error(),
err = errors.NewErrorf("[opMetaInodeGet] %s, req: %s", err.Error(),
string(p.Data))
return
}
@ -329,7 +330,7 @@ func (m *metadataManager) opMetaInodeGet(conn net.Conn, p *Packet,
return
}
if err = mp.InodeGet(req, p); err != nil {
err = errors.Errorf("[opMetaInodeGet] %s, req: %s", err.Error(),
err = errors.NewErrorf("[opMetaInodeGet] %s, req: %s", err.Error(),
string(p.Data))
}
m.respondToClient(conn, p)
@ -344,14 +345,14 @@ func (m *metadataManager) opMetaEvictInode(conn net.Conn, p *Packet,
if err = json.Unmarshal(p.Data, req); err != nil {
p.PacketErrorWithBody(proto.OpErr, []byte(err.Error()))
m.respondToClient(conn, p)
err = errors.Errorf("[opMetaEvictInode] request unmarshal: %v", err.Error())
err = errors.NewErrorf("[opMetaEvictInode] request unmarshal: %v", err.Error())
return
}
mp, err := m.getPartition(req.PartitionID)
if err != nil {
p.PacketErrorWithBody(proto.OpNotExistErr, nil)
m.respondToClient(conn, p)
err = errors.Errorf("[opMetaEvictInode] req: %s, resp: %v", req, err.Error())
err = errors.NewErrorf("[opMetaEvictInode] req: %s, resp: %v", req, err.Error())
return
}
if !m.serveProxy(conn, mp, p) {
@ -359,7 +360,7 @@ func (m *metadataManager) opMetaEvictInode(conn net.Conn, p *Packet,
}
if err = mp.EvictInode(req, p); err != nil {
err = errors.Errorf("[opMetaEvictInode] req: %s, resp: %v", req, err.Error())
err = errors.NewErrorf("[opMetaEvictInode] req: %s, resp: %v", req, err.Error())
}
m.respondToClient(conn, p)
log.LogInfof("%s [opMetaEvictInode] req: %d - %v, resp: %v, body: %s",
@ -373,7 +374,7 @@ func (m *metadataManager) opSetAttr(conn net.Conn, p *Packet,
if err = json.Unmarshal(p.Data, req); err != nil {
p.PacketErrorWithBody(proto.OpErr, []byte(err.Error()))
m.respondToClient(conn, p)
err = errors.Errorf("[opSetAttr] req: %v, error: %v", req, err.Error())
err = errors.NewErrorf("[opSetAttr] req: %v, error: %v", req, err.Error())
return
}
@ -381,7 +382,7 @@ func (m *metadataManager) opSetAttr(conn net.Conn, p *Packet,
if err != nil {
p.PacketErrorWithBody(proto.OpErr, []byte(err.Error()))
m.respondToClient(conn, p)
err = errors.Errorf("[opSetAttr] req: %v, error: %v", req, err.Error())
err = errors.NewErrorf("[opSetAttr] req: %v, error: %v", req, err.Error())
return
}
@ -389,7 +390,7 @@ func (m *metadataManager) opSetAttr(conn net.Conn, p *Packet,
return
}
if err = mp.SetAttr(p.Data, p); err != nil {
err = errors.Errorf("[opSetAttr] req: %v, error: %s", req, err.Error())
err = errors.NewErrorf("[opSetAttr] req: %v, error: %s", req, err.Error())
}
m.respondToClient(conn, p)
log.LogDebugf("%s [opSetAttr] req: %d - %v, resp: %v, body: %s", remoteAddr,
@ -434,7 +435,7 @@ func (m *metadataManager) opMetaExtentsAdd(conn net.Conn, p *Packet,
if err != nil {
p.PacketErrorWithBody(proto.OpNotExistErr, nil)
m.respondToClient(conn, p)
err = errors.Errorf("%s, response to client: %s", err.Error(),
err = errors.NewErrorf("%s, response to client: %s", err.Error(),
p.GetResultMsg())
return
}
@ -645,13 +646,13 @@ func (m *metadataManager) opDecommissionMetaPartition(conn net.Conn,
Status: proto.TaskFailed,
}
if req.AddPeer.ID == req.RemovePeer.ID {
err = errors.Errorf("[opDecommissionMetaPartition]: AddPeer[%v] same withRemovePeer[%v]", req.AddPeer, req.RemovePeer)
err = errors.NewErrorf("[opDecommissionMetaPartition]: AddPeer[%v] same withRemovePeer[%v]", req.AddPeer, req.RemovePeer)
resp.Result = err.Error()
goto end
}
reqData, err = json.Marshal(req)
if err != nil {
err = errors.Errorf("[opDecommissionMetaPartition]: partitionID= %d, "+
err = errors.NewErrorf("[opDecommissionMetaPartition]: partitionID= %d, "+
"Marshal %s", req.PartitionID, err)
resp.Result = err.Error()
goto end

View File

@ -18,8 +18,8 @@ import (
"encoding/json"
"net"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
)
const (
@ -48,7 +48,7 @@ func (m *metadataManager) respondToMaster(data interface{}) (err error) {
}
_, err = masterHelper.Request("POST", masterResponsePath, nil, jsonBytes)
if err != nil {
err = errors.Annotate(err, "try respondToMaster failed")
err = errors.Trace(err, "try respondToMaster failed")
}
return
}

View File

@ -26,15 +26,16 @@ import (
"github.com/chubaofs/chubaofs/raftstore"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/config"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"strconv"
)
var (
clusterInfo *proto.ClusterInfo
masterHelper util.MasterHelper
clusterInfo *proto.ClusterInfo
masterHelper util.MasterHelper
configTotalMem uint64
)
// The MetaNode manages the dentry and inode information of the meta partitions on a meta node.
@ -135,6 +136,19 @@ func (m *MetaNode) parseConfig(cfg *config.Config) (err error) {
m.raftDir = cfg.GetString(cfgRaftDir)
m.raftHeartbeatPort = cfg.GetString(cfgRaftHeartbeatPort)
m.raftReplicatePort = cfg.GetString(cfgRaftReplicaPort)
configTotalMem, _ = strconv.ParseUint(cfg.GetString(cfgTotalMem), 10, 64)
if configTotalMem != 0 && configTotalMem <= util.GB {
configTotalMem = util.GB
}
total, _, err := util.GetMemInfo()
if err == nil && configTotalMem == 0 {
configTotalMem = total
}
if configTotalMem > total {
configTotalMem = total
}
log.LogInfof("[parseConfig] load localAddr[%v].", m.localAddr)
log.LogInfof("[parseConfig] load listen[%v].", m.listen)

View File

@ -25,8 +25,8 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/raftstore"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
raftproto "github.com/tiglabs/raft/proto"
"io/ioutil"
"os"
@ -77,21 +77,21 @@ type MetaPartitionConfig struct {
func (c *MetaPartitionConfig) checkMeta() (err error) {
if c.PartitionId <= 0 {
err = errors.Errorf("[checkMeta]: partition id at least 1, "+
err = errors.NewErrorf("[checkMeta]: partition id at least 1, "+
"now partition id is: %d", c.PartitionId)
return
}
if c.Start < 0 {
err = errors.Errorf("[checkMeta]: start at least 0")
err = errors.NewErrorf("[checkMeta]: start at least 0")
return
}
if c.End <= c.Start {
err = errors.Errorf("[checkMeta]: end=%v, "+
err = errors.NewErrorf("[checkMeta]: end=%v, "+
"start=%v; end <= start", c.End, c.Start)
return
}
if len(c.Peers) <= 0 {
err = errors.Errorf("[checkMeta]: must have peers, now peers is 0")
err = errors.NewErrorf("[checkMeta]: must have peers, now peers is 0")
return
}
return
@ -198,7 +198,7 @@ func (mp *metaPartition) Start() (err error) {
mp.config.BeforeStart()
}
if err = mp.onStart(); err != nil {
err = errors.Errorf("[Start]->%s", err.Error())
err = errors.NewErrorf("[Start]->%s", err.Error())
return
}
if mp.config.AfterStart != nil {
@ -232,18 +232,18 @@ func (mp *metaPartition) onStart() (err error) {
mp.onStop()
}()
if err = mp.load(); err != nil {
err = errors.Errorf("[onStart]:load partition id=%d: %s",
err = errors.NewErrorf("[onStart]:load partition id=%d: %s",
mp.config.PartitionId, err.Error())
return
}
mp.startSchedule(mp.applyID)
if err = mp.startFreeList(); err != nil {
err = errors.Errorf("[onStart] start free list id=%d: %s",
err = errors.NewErrorf("[onStart] start free list id=%d: %s",
mp.config.PartitionId, err.Error())
return
}
if err = mp.startRaft(); err != nil {
err = errors.Errorf("[onStart]start raft id=%d: %s",
err = errors.NewErrorf("[onStart]start raft id=%d: %s",
mp.config.PartitionId, err.Error())
return
}
@ -520,7 +520,7 @@ func (mp *metaPartition) UpdatePartition(req *UpdatePartitionReq,
resp.Status = proto.TaskFailed
p := &Packet{}
p.ResultCode = status
err = errors.Errorf("[UpdatePartition]: %s", p.GetResultMsg())
err = errors.NewErrorf("[UpdatePartition]: %s", p.GetResultMsg())
resp.Result = p.GetResultMsg()
}
resp.Status = proto.TaskSucceeds
@ -542,7 +542,7 @@ func (mp *metaPartition) LoadSnapshotSign(p *Packet) (err error) {
snapshotDir)
if err != nil {
if !os.IsNotExist(err) {
err = errors.Annotate(err, "[LoadSnapshotSign] 1st check snapshot")
err = errors.Trace(err, "[LoadSnapshotSign] 1st check snapshot")
p.PacketErrorWithBody(proto.OpErr, []byte(err.Error()))
return err
}
@ -551,7 +551,7 @@ func (mp *metaPartition) LoadSnapshotSign(p *Packet) (err error) {
}
if err != nil {
if !os.IsNotExist(err) {
err = errors.Annotate(err,
err = errors.Trace(err,
"[LoadSnapshotSign] 2st check snapshot")
p.PacketErrorWithBody(proto.OpErr, []byte(err.Error()))
return
@ -561,7 +561,7 @@ func (mp *metaPartition) LoadSnapshotSign(p *Packet) (err error) {
}
data, err := json.Marshal(resp)
if err != nil {
err = errors.Annotate(err, "[LoadSnapshotSign] marshal")
err = errors.Trace(err, "[LoadSnapshotSign] marshal")
return
}
p.PacketOkWithBody(data)

View File

@ -18,8 +18,8 @@ import (
"encoding/json"
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"net"
"os"
"path"
@ -73,7 +73,6 @@ func (mp *metaPartition) updateVolWorker() {
break
}
mp.vol.UpdatePartitions(dataView)
log.LogDebugf("[updateVol] %v", dataView)
}
}
}
@ -210,7 +209,7 @@ func (mp *metaPartition) deleteMarkedInodes(inoSlice []*Inode) {
for _, ino := range shouldCommit {
mp.freeList.Push(ino)
}
log.LogWarnf("[deleteInodeTreeOnRaftPeers] syncToRaftFollowersFreeInode inode list: %v, "+
log.LogWarnf("[deleteInodeTreeOnRaftPeers] raft commit inode list: %v, "+
"response %s", shouldCommit, err.Error())
}
log.LogDebugf("[deleteInodeTree] inode list: %v", shouldCommit)
@ -218,6 +217,10 @@ func (mp *metaPartition) deleteMarkedInodes(inoSlice []*Inode) {
}
func (mp *metaPartition) freeInodesOnRaftFollower(inodes []byte) {
}
func (mp *metaPartition) syncToRaftFollowersFreeInode(hasDeleteInodes []byte) (err error) {
raftPeers := mp.GetPeers()
raftPeersError := make([]error, len(raftPeers))
@ -272,7 +275,7 @@ func (mp *metaPartition) doDeleteMarkedInodes(ext *proto.ExtentKey) (err error)
// get the data node view
dp := mp.vol.GetPartition(ext.PartitionId)
if dp == nil {
err = errors.Errorf("unknown dataPartitionID=%d in vol",
err = errors.NewErrorf("unknown dataPartitionID=%d in vol",
ext.PartitionId)
return
}
@ -288,24 +291,24 @@ func (mp *metaPartition) doDeleteMarkedInodes(ext *proto.ExtentKey) (err error)
}()
if err != nil {
err = errors.Errorf("get conn from pool %s, "+
err = errors.NewErrorf("get conn from pool %s, "+
"extents partitionId=%d, extentId=%d",
err.Error(), ext.PartitionId, ext.ExtentId)
return
}
p := NewPacketToDeleteExtent(dp, ext)
if err = p.WriteToConn(conn); err != nil {
err = errors.Errorf("write to dataNode %s, %s", p.GetUniqueLogId(),
err = errors.NewErrorf("write to dataNode %s, %s", p.GetUniqueLogId(),
err.Error())
return
}
if err = p.ReadFromConn(conn, proto.ReadDeadlineTime); err != nil {
err = errors.Errorf("read response from dataNode %s, %s",
err = errors.NewErrorf("read response from dataNode %s, %s",
p.GetUniqueLogId(), err.Error())
return
}
if p.ResultCode != proto.OpOk {
err = errors.Errorf("[deleteMarkedInodes] %s response: %s", p.GetUniqueLogId(),
err = errors.NewErrorf("[deleteMarkedInodes] %s response: %s", p.GetUniqueLogId(),
p.GetResultMsg())
}
log.LogDebugf("[deleteMarkedInodes] %v", p.GetUniqueLogId())

View File

@ -20,7 +20,7 @@ import (
"encoding/json"
"fmt"
"github.com/chubaofs/chubaofs/proto"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"hash/crc32"
"io"
"io/ioutil"
@ -44,19 +44,19 @@ func (mp *metaPartition) loadMetadata() (err error) {
metaFile := path.Join(mp.config.RootDir, metadataFile)
fp, err := os.OpenFile(metaFile, os.O_RDONLY, 0644)
if err != nil {
err = errors.Errorf("[loadMetadata]: OpenFile %s", err.Error())
err = errors.NewErrorf("[loadMetadata]: OpenFile %s", err.Error())
return
}
defer fp.Close()
data, err := ioutil.ReadAll(fp)
if err != nil || len(data) == 0 {
err = errors.Errorf("[loadMetadata]: ReadFile %s, data: %s", err.Error(),
err = errors.NewErrorf("[loadMetadata]: ReadFile %s, data: %s", err.Error(),
string(data))
return
}
mConf := &MetaPartitionConfig{}
if err = json.Unmarshal(data, mConf); err != nil {
err = errors.Errorf("[loadMetadata]: Unmarshal MetaPartitionConfig %s",
err = errors.NewErrorf("[loadMetadata]: Unmarshal MetaPartitionConfig %s",
err.Error())
return
}
@ -81,7 +81,7 @@ func (mp *metaPartition) loadInode(rootDir string) (err error) {
}
fp, err := os.OpenFile(filename, os.O_RDONLY, 0644)
if err != nil {
err = errors.Errorf("[loadInode] OpenFile: %s", err.Error())
err = errors.NewErrorf("[loadInode] OpenFile: %s", err.Error())
return
}
defer fp.Close()
@ -96,7 +96,7 @@ func (mp *metaPartition) loadInode(rootDir string) (err error) {
err = nil
return
}
err = errors.Errorf("[loadInode] ReadHeader: %s", err.Error())
err = errors.NewErrorf("[loadInode] ReadHeader: %s", err.Error())
return
}
length := binary.BigEndian.Uint32(inoBuf)
@ -109,12 +109,12 @@ func (mp *metaPartition) loadInode(rootDir string) (err error) {
}
_, err = io.ReadFull(reader, inoBuf)
if err != nil {
err = errors.Errorf("[loadInode] ReadBody: %s", err.Error())
err = errors.NewErrorf("[loadInode] ReadBody: %s", err.Error())
return
}
ino := NewInode(0, 0)
if err = ino.Unmarshal(inoBuf); err != nil {
err = errors.Errorf("[loadInode] Unmarshal: %s", err.Error())
err = errors.NewErrorf("[loadInode] Unmarshal: %s", err.Error())
return
}
mp.fsmCreateInode(ino)
@ -138,7 +138,7 @@ func (mp *metaPartition) loadDentry(rootDir string) (err error) {
err = nil
return
}
err = errors.Errorf("[loadDentry] OpenFile: %s", err.Error())
err = errors.NewErrorf("[loadDentry] OpenFile: %s", err.Error())
return
}
@ -154,7 +154,7 @@ func (mp *metaPartition) loadDentry(rootDir string) (err error) {
err = nil
return
}
err = errors.Errorf("[loadDentry] ReadHeader: %s", err.Error())
err = errors.NewErrorf("[loadDentry] ReadHeader: %s", err.Error())
return
}
@ -168,16 +168,16 @@ func (mp *metaPartition) loadDentry(rootDir string) (err error) {
}
_, err = io.ReadFull(reader, dentryBuf)
if err != nil {
err = errors.Errorf("[loadDentry]: ReadBody: %s", err.Error())
err = errors.NewErrorf("[loadDentry]: ReadBody: %s", err.Error())
return
}
dentry := &Dentry{}
if err = dentry.Unmarshal(dentryBuf); err != nil {
err = errors.Errorf("[loadDentry] Unmarshal: %s", err.Error())
err = errors.NewErrorf("[loadDentry] Unmarshal: %s", err.Error())
return
}
if status := mp.fsmCreateDentry(dentry, true); status != proto.OpOk {
err = errors.Errorf("[loadDentry] createDentry dentry: %v, "+
err = errors.NewErrorf("[loadDentry] createDentry dentry: %v, "+
"resp code: %d", status)
return
}
@ -196,15 +196,15 @@ func (mp *metaPartition) loadApplyID(rootDir string) (err error) {
err = nil
return
}
err = errors.Errorf("[loadApplyID] OpenFile: %s", err.Error())
err = errors.NewErrorf("[loadApplyID] OpenFile: %s", err.Error())
return
}
if len(data) == 0 {
err = errors.Errorf("[loadApplyID]: ApplyID is empty")
err = errors.NewErrorf("[loadApplyID]: ApplyID is empty")
return
}
if _, err = fmt.Sscanf(string(data), "%d", &mp.applyID); err != nil {
err = errors.Errorf("[loadApplyID] ReadApplyID: %s", err.Error())
err = errors.NewErrorf("[loadApplyID] ReadApplyID: %s", err.Error())
return
}
return
@ -212,7 +212,7 @@ func (mp *metaPartition) loadApplyID(rootDir string) (err error) {
func (mp *metaPartition) persistMetadata() (err error) {
if err = mp.config.checkMeta(); err != nil {
err = errors.Errorf("[persistMetadata]->%s", err.Error())
err = errors.NewErrorf("[persistMetadata]->%s", err.Error())
return
}

View File

@ -17,9 +17,9 @@ package metanode
import (
"time"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
)
type storeMsg struct {
@ -50,7 +50,7 @@ func (mp *metaPartition) startSchedule(curIndex uint64) {
} else {
// retry again
mp.storeChan <- msg
err = errors.Errorf("[startSchedule]: dump partition id=%d: %v",
err = errors.NewErrorf("[startSchedule]: dump partition id=%d: %v",
mp.config.PartitionId, err.Error())
log.LogErrorf(err.Error())
exporter.NewAlarm(exporterKey)

View File

@ -19,14 +19,14 @@ import (
"strconv"
"github.com/chubaofs/chubaofs/raftstore"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
)
// StartRaftServer initializes the address resolver and the raftStore server instance.
func (m *MetaNode) startRaftServer() (err error) {
if _, err = os.Stat(m.raftDir); err != nil {
if err = os.MkdirAll(m.raftDir, 0755); err != nil {
err = errors.Errorf("create raft server dir: %s", err.Error())
err = errors.NewErrorf("create raft server dir: %s", err.Error())
return
}
}
@ -44,7 +44,7 @@ func (m *MetaNode) startRaftServer() (err error) {
}
m.raftStore, err = raftstore.NewRaftStore(raftConf)
if err != nil {
err = errors.Errorf("new raftStore: %s", err.Error())
err = errors.NewErrorf("new raftStore: %s", err.Error())
}
return
}

View File

@ -169,6 +169,7 @@ type HeartBeatRequest struct {
// PartitionReport defines the partition report.
type PartitionReport struct {
VolName string
PartitionID uint64
PartitionStatus int
Total uint64

View File

@ -15,7 +15,7 @@
package proto
import (
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
)
//err
@ -30,8 +30,8 @@ var (
ErrVolNotExists = errors.New("vol not exists")
ErrMetaPartitionNotExists = errors.New("meta partition not exists")
ErrDataPartitionNotExists = errors.New("data partition not exists")
ErrDataNodeNotExists = errors.New("data partition not exists")
ErrMetaNodeNotExists = errors.New("data partition not exists")
ErrDataNodeNotExists = errors.New("data node not exists")
ErrMetaNodeNotExists = errors.New("meta node not exists")
ErrDuplicateVol = errors.New("duplicate vol")
ErrActiveDataNodesTooLess = errors.New("no enough active data node")
ErrActiveMetaNodesTooLess = errors.New("no enough active meta node")

View File

@ -113,7 +113,7 @@ const (
OpAgain uint8 = 0xF9
OpExistErr uint8 = 0xFA
OpInodeFullErr uint8 = 0xFB
OpNotLeaderErr uint8 = 0xFC
OpTryOtherAddr uint8 = 0xFC
OpNotPerm uint8 = 0xFD
OpNotEmtpy uint8 = 0xFE
OpOk uint8 = 0xF0
@ -153,6 +153,7 @@ type Packet struct {
Arg []byte // for create or append ops, the data contains the address
Data []byte
StartT int64
mesg string
}
// NewPacket returns a new packet.
@ -317,8 +318,8 @@ func (p *Packet) GetResultMsg() (m string) {
m = "ArgUnmatchErr"
case OpNotExistErr:
m = "NotExistErr"
case OpNotLeaderErr:
m = "NotLeaderErr"
case OpTryOtherAddr:
m = "TryOtherAddr"
case OpNotPerm:
m = "NotPerm"
case OpNotEmtpy:
@ -503,26 +504,35 @@ func (p *Packet) PacketErrorWithBody(code uint8, reply []byte) {
// GetUniqueLogId returns the unique log ID.
func (p *Packet) GetUniqueLogId() (m string) {
defer func() {
if p.mesg == "" {
p.mesg = m
}
m = p.mesg + fmt.Sprintf("_ResultMesg(%v)", p.GetResultMsg())
}()
if p.mesg != "" {
return
}
m = fmt.Sprintf("Req(%v)_Partition(%v)_", p.ReqID, p.PartitionID)
if p.ExtentType == TinyExtentType && p.Opcode == OpMarkDelete && len(p.Data) > 0 {
ext := new(TinyExtentDeleteRecord)
err := json.Unmarshal(p.Data, ext)
if err == nil {
m += fmt.Sprintf("Extent(%v)_ExtentOffset(%v)_TinyDeleteFileOffset(%v)_Size(%v)_Opcode(%v)_ResultCode(%v)",
ext.ExtentId, ext.ExtentOffset, ext.TinyDeleteFileOffset, ext.Size, p.Opcode, p.ResultCode)
m += fmt.Sprintf("Extent(%v)_ExtentOffset(%v)_TinyDeleteFileOffset(%v)_Size(%v)_Opcode(%v)",
ext.ExtentId, ext.ExtentOffset, ext.TinyDeleteFileOffset, ext.Size, p.Opcode)
return m
}
} else if p.Opcode == OpReadTinyDelete {
m += fmt.Sprintf("Opcode(%v)_ResultCode(%v)", p.GetOpMsg(), p.GetResultMsg())
m += fmt.Sprintf("Opcode(%v)", p.GetOpMsg())
return m
} else if p.Opcode == OpNotifyReplicasToRepair {
m += fmt.Sprintf("Opcode(%v)_ResultCode(%v)", p.GetOpMsg(), p.GetResultMsg())
m += fmt.Sprintf("Opcode(%v)", p.GetOpMsg())
return m
}
m = fmt.Sprintf("Req(%v)_Partition(%v)_Extent(%v)_ExtentOffset(%v)_KernelOffset(%v)_"+
"Size(%v)_Opcode(%v)_ResultCode(%v)_CRC(%v)",
"Size(%v)_Opcode(%v)_CRC(%v)",
p.ReqID, p.PartitionID, p.ExtentID, p.ExtentOffset,
p.KernelOffset, p.Size, p.GetOpMsg(), p.GetResultMsg(), p.CRC)
p.KernelOffset, p.Size, p.GetOpMsg(), p.CRC)
return
}

View File

@ -15,17 +15,11 @@
package raftstore
import (
"github.com/juju/errors"
"github.com/tiglabs/raft"
"github.com/tiglabs/raft/proto"
"os"
)
// Error definitions for raft store partition.
var (
ErrNotLeader = errors.New("not a raft leader")
)
// PartitionStatus is a type alias of raft.Status
type PartitionStatus = raft.Status
@ -85,7 +79,7 @@ type partition struct {
func (p *partition) ChangeMember(changeType proto.ConfChangeType, peer proto.Peer, context []byte) (
resp interface{}, err error) {
if !p.IsRaftLeader() {
err = ErrNotLeader
err = raft.ErrNotLeader
return
}
future := p.raft.ChangeMember(p.id, changeType, peer, context)
@ -141,7 +135,7 @@ func (p *partition) CommittedIndex() (applied uint64) {
// Submit submits command data to raft log.
func (p *partition) Submit(cmd []byte) (resp interface{}, err error) {
if !p.IsRaftLeader() {
err = ErrNotLeader
err = raft.ErrNotLeader
return
}
future := p.raft.Submit(p.id, cmd)

View File

@ -16,8 +16,8 @@ package raftstore
import (
"fmt"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"github.com/tiglabs/raft"
"strings"
"sync"

View File

@ -26,7 +26,6 @@ const (
ActionSendToFollowers = "ActionSendToFollowers"
ActionReceiveFromFollower = "ActionReceiveFromFollower"
ActionWriteToClient = "ActionWriteToClient"
ActionCheckAndAddInfos = "ActionCheckAndAddInfos"
ActionCheckReply = "ActionCheckReply"
ActionPreparePkt = "ActionPreparePkt"

View File

@ -24,8 +24,9 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/storage"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/exporter"
"github.com/juju/errors"
"github.com/tiglabs/raft"
)
var (
@ -230,14 +231,13 @@ var (
func (p *Packet) identificationErrorResultCode(errLog string, errMsg string) {
if strings.Contains(errLog, ActionReceiveFromFollower) || strings.Contains(errLog, ActionSendToFollowers) ||
strings.Contains(errLog, ConnIsNullErr) || strings.Contains(errLog, ActionCheckAndAddInfos) {
strings.Contains(errLog, ConnIsNullErr) {
p.ResultCode = proto.OpIntraGroupNetErr
return
}
if strings.Contains(errMsg, storage.ParameterMismatchError.Error()) ||
} else if strings.Contains(errMsg, storage.ParameterMismatchError.Error()) ||
strings.Contains(errMsg, ErrorUnknownOp.Error()) {
p.ResultCode = proto.OpArgMismatchErr
} else if strings.Contains(errMsg, proto.ErrDataPartitionNotExists.Error()) {
p.ResultCode = proto.OpTryOtherAddr
} else if strings.Contains(errMsg, storage.ExtentNotFoundError.Error()) ||
strings.Contains(errMsg, storage.ExtentHasBeenDeletedError.Error()) {
p.ResultCode = proto.OpNotExistErr
@ -245,14 +245,8 @@ func (p *Packet) identificationErrorResultCode(errLog string, errMsg string) {
p.ResultCode = proto.OpDiskNoSpaceErr
} else if strings.Contains(errMsg, storage.TryAgainError.Error()) {
p.ResultCode = proto.OpAgain
} else if strings.Contains(errMsg, storage.NotALeaderError.Error()) {
p.ResultCode = proto.OpNotLeaderErr
} else if strings.Contains(errMsg, storage.ExtentNotFoundError.Error()) {
if p.Opcode != proto.OpWrite {
p.ResultCode = proto.OpNotExistErr
} else {
p.ResultCode = proto.OpIntraGroupNetErr
}
} else if strings.Contains(errMsg, raft.ErrNotLeader.Error()) {
p.ResultCode = proto.OpTryOtherAddr
} else {
p.ResultCode = proto.OpIntraGroupNetErr
}
@ -260,9 +254,6 @@ func (p *Packet) identificationErrorResultCode(errLog string, errMsg string) {
func (p *Packet) PackErrorBody(action, msg string) {
p.identificationErrorResultCode(action, msg)
if p.ResultCode == proto.OpDiskNoSpaceErr || p.ResultCode == proto.OpDiskErr {
p.ResultCode = proto.OpIntraGroupNetErr
}
p.Size = uint32(len([]byte(action + "_" + msg)))
p.Data = make([]byte, p.Size)
copy(p.Data[:int(p.Size)], []byte(action+"_"+msg))

View File

@ -22,8 +22,8 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"sync/atomic"
)
@ -286,7 +286,7 @@ func (rp *ReplProtocol) checkLocalResultAndReceiveFromFollower(request *Packet,
reply.clean()
}()
if err = reply.ReadFromConn(request.followerConns[index], proto.ReadDeadlineTime); err != nil {
err = errors.Annotatef(err, "local(%v) follower(%v)", request.followerConns[index].LocalAddr().String(),
err = errors.Trace(err, "local(%v) follower(%v)", request.followerConns[index].LocalAddr().String(),
request.followerConns[index].RemoteAddr().String())
return
}

View File

@ -19,7 +19,7 @@ import (
"runtime"
"sync"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/sdk/data/wrapper"
@ -56,7 +56,7 @@ func NewExtentClient(volname, master string, appendExtentKey AppendExtentKeyFunc
client = new(ExtentClient)
gDataWrapper, err = wrapper.NewDataPartitionWrapper(volname, master)
if err != nil {
return nil, errors.Annotatef(err, "Init dp wrapper failed!")
return nil, errors.Trace(err, "Init dp wrapper failed!")
}
client.streamers = make(map[uint64]*Streamer)
client.appendExtentKey = appendExtentKey
@ -165,8 +165,8 @@ func (client *ExtentClient) Write(inode uint64, offset int, data []byte, direct
write, err = s.IssueWriteRequest(offset, data, direct)
if err != nil {
err = errors.Annotatef(err, prefix)
log.LogError(errors.ErrorStack(err))
err = errors.Trace(err, prefix)
log.LogError(errors.Stack(err))
exporter.NewAlarm(gDataWrapper.WarningMsg())
}
return
@ -181,8 +181,8 @@ func (client *ExtentClient) Truncate(inode uint64, size int) error {
err := s.IssueTruncRequest(size)
if err != nil {
err = errors.Annotatef(err, prefix)
log.LogError(errors.ErrorStack(err))
err = errors.Trace(err, prefix)
log.LogError(errors.Stack(err))
}
return err
}

View File

@ -20,7 +20,7 @@ import (
"sync/atomic"
"time"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/sdk/data/wrapper"
@ -516,7 +516,7 @@ func (eh *ExtentHandler) allocateExtent() (err error) {
errmsg := fmt.Sprintf("allocateExtent failed: hit max retry limit")
if err != nil {
err = errors.Annotate(err, errmsg)
err = errors.Trace(err, errmsg)
} else {
err = errors.New(errmsg)
}
@ -539,7 +539,7 @@ func (eh *ExtentHandler) createExtent(dp *wrapper.DataPartition) (extID int, err
conn, err := StreamConnPool.GetConnect(dp.Hosts[0])
if err != nil {
// TODO unhandled error
errors.Annotatef(err, "createExtent: failed to create connection, eh(%v) datapartionHosts(%v)", eh, dp.Hosts[0])
errors.Trace(err, "createExtent: failed to create connection, eh(%v) datapartionHosts(%v)", eh, dp.Hosts[0])
return
}
// TODO unhandled error
@ -554,12 +554,12 @@ func (eh *ExtentHandler) createExtent(dp *wrapper.DataPartition) (extID int, err
p := NewCreateExtentPacket(dp, eh.inode)
if err = p.WriteToConn(conn); err != nil {
// TODO unhandled error
errors.Annotatef(err, "createExtent: failed to WriteToConn, packet(%v) datapartionHosts(%v)", p, dp.Hosts[0])
errors.Trace(err, "createExtent: failed to WriteToConn, packet(%v) datapartionHosts(%v)", p, dp.Hosts[0])
return
}
if err = p.ReadFromConn(conn, proto.ReadDeadlineTime*2); err != nil {
err = errors.Annotatef(err, "createExtent: failed to ReadFromConn, packet(%v) datapartionHosts(%v)", p, dp.Hosts[0])
err = errors.Trace(err, "createExtent: failed to ReadFromConn, packet(%v) datapartionHosts(%v)", p, dp.Hosts[0])
return
}

View File

@ -19,8 +19,8 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/sdk/data/wrapper"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
"hash/crc32"
"net"
)
@ -66,8 +66,8 @@ func (reader *ExtentReader) Read(req *ExtentRequest) (readBytes int, err error)
e := replyPacket.readFromConn(conn, proto.ReadDeadlineTime)
if e != nil {
log.LogErrorf("Extent Reader Read: failed to read from connect, readBytes(%v) err(%v)", readBytes, e)
// Upon receiving NotALeaderError, other hosts will be retried.
return NotALeaderError, false
// Upon receiving TryOtherAddrError, other hosts will be retried.
return TryOtherAddrError, false
}
//log.LogDebugf("ExtentReader Read: ResultCode(%v) req(%v) reply(%v) readBytes(%v)", replyPacket.GetResultMsg(), reqPacket, replyPacket, readBytes)
@ -97,8 +97,8 @@ func (reader *ExtentReader) Read(req *ExtentRequest) (readBytes int, err error)
}
func (reader *ExtentReader) checkStreamReply(request *Packet, reply *Packet) (err error) {
if reply.ResultCode == proto.OpNotLeaderErr {
return NotALeaderError
if reply.ResultCode == proto.OpTryOtherAddr {
return TryOtherAddrError
}
if reply.ResultCode != proto.OpOk {

View File

@ -21,12 +21,12 @@ import (
"github.com/chubaofs/chubaofs/sdk/data/wrapper"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
)
var (
NotALeaderError = errors.New("NotALeaderError")
TryOtherAddrError = errors.New("TryOtherAddrError")
)
const (
@ -83,7 +83,7 @@ func (sc *StreamConn) sendToPartition(req *Packet, getReply GetReplyFunc) (err e
}
log.LogWarnf("sendToPartition: curr addr failed, addr(%v) reqPacket(%v) err(%v)", sc.currAddr, req, err)
StreamConnPool.PutConnect(conn, true)
if err != NotALeaderError {
if err != TryOtherAddrError {
return
}
}
@ -103,7 +103,7 @@ func (sc *StreamConn) sendToPartition(req *Packet, getReply GetReplyFunc) (err e
return
}
StreamConnPool.PutConnect(conn, true)
if err != NotALeaderError {
if err != TryOtherAddrError {
return
}
}

View File

@ -25,8 +25,8 @@ import (
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/sdk/data/wrapper"
"github.com/chubaofs/chubaofs/util"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/util/log"
"github.com/juju/errors"
)
const (
@ -312,7 +312,7 @@ func (s *Streamer) doOverwrite(req *ExtentRequest, direct bool) (total int, err
if dp, err = gDataWrapper.GetDataPartition(req.ExtentKey.PartitionId); err != nil {
// TODO unhandled error
errors.Annotatef(err, "doOverwrite: ino(%v) failed to get datapartition, ek(%v)", s.inode, req.ExtentKey)
errors.Trace(err, "doOverwrite: ino(%v) failed to get datapartition, ek(%v)", s.inode, req.ExtentKey)
return
}
@ -333,16 +333,16 @@ func (s *Streamer) doOverwrite(req *ExtentRequest, direct bool) (total int, err
e := replyPacket.ReadFromConn(conn, proto.ReadDeadlineTime)
if e != nil {
log.LogErrorf("Stream Writer doOverwrite: ino(%v) failed to read from connect, err(%v)", s.inode, e)
// Upon receiving NotALeaderError, other hosts will be retried.
return NotALeaderError, false
// Upon receiving TryOtherAddrError, other hosts will be retried.
return TryOtherAddrError, false
}
if replyPacket.ResultCode == proto.OpAgain {
return nil, true
}
if replyPacket.ResultCode == proto.OpNotLeaderErr {
e = NotALeaderError
if replyPacket.ResultCode == proto.OpTryOtherAddr {
e = TryOtherAddrError
}
return e, false
})

View File

@ -23,7 +23,7 @@ import (
"sync"
"time"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util"
@ -65,11 +65,11 @@ func NewDataPartitionWrapper(volName, masterHosts string) (w *Wrapper, err error
w.rwPartition = make([]*DataPartition, 0)
w.partitions = make(map[uint64]*DataPartition)
if err = w.updateClusterInfo(); err != nil {
err = errors.Annotate(err, "NewDataPartitionWrapper:")
err = errors.Trace(err, "NewDataPartitionWrapper:")
return
}
if err = w.updateDataPartition(); err != nil {
err = errors.Annotate(err, "NewDataPartitionWrapper:")
err = errors.Trace(err, "NewDataPartitionWrapper:")
return
}
go w.update()
@ -117,14 +117,14 @@ func (w *Wrapper) updateDataPartition() error {
paras["name"] = w.volName
msg, err := MasterHelper.Request(http.MethodGet, proto.ClientDataPartitions, paras, nil)
if err != nil {
return errors.Annotate(err, "updateDataPartition: request to master failed!")
return errors.Trace(err, "updateDataPartition: request to master failed!")
}
log.LogInfof("updateDataPartition: start!")
view := &DataPartitionView{}
if err = json.Unmarshal(msg, view); err != nil {
return errors.Annotatef(err, "updateDataPartition: unmarshal failed, msg(%v)", msg)
return errors.Trace(err, "updateDataPartition: unmarshal failed, msg(%v)", msg)
}
rwPartitionGroups := make([]*DataPartition, 0)

View File

@ -281,6 +281,8 @@ func (mw *MetaWrapper) Rename_ll(srcParentID uint64, srcName string, dstParentID
return statusToErrno(status)
}
mw.iunlink(srcMP, inode)
if oldInode != 0 {
inodeMP := mw.getPartitionByInode(oldInode)
if inodeMP != nil {

View File

@ -19,7 +19,7 @@ import (
"net"
"time"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/log"
@ -120,12 +120,12 @@ out:
func (mc *MetaConn) send(req *proto.Packet) (resp *proto.Packet, err error) {
err = req.WriteToConn(mc.conn)
if err != nil {
return nil, errors.Annotatef(err, "Failed to write to conn, req(%v)", req)
return nil, errors.Trace(err, "Failed to write to conn, req(%v)", req)
}
resp = proto.NewPacket()
err = resp.ReadFromConn(mc.conn, proto.ReadDeadlineTime)
if err != nil {
return nil, errors.Annotatef(err, "Failed to read from conn, req(%v)", req)
return nil, errors.Trace(err, "Failed to read from conn, req(%v)", req)
}
return resp, nil
}

View File

@ -18,7 +18,7 @@ import (
"fmt"
"sync"
"github.com/juju/errors"
"github.com/chubaofs/chubaofs/util/errors"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/exporter"

View File

@ -15,28 +15,21 @@
package meta
import (
"encoding/json"
"net/http"
"sync/atomic"
"time"
"github.com/juju/errors"
"crypto/md5"
"encoding/hex"
"encoding/json"
"github.com/chubaofs/chubaofs/proto"
"github.com/chubaofs/chubaofs/util/log"
"net/http"
"strings"
"sync/atomic"
"time"
)
const (
MaxSendToMaster = 3
)
var (
NotLeader = errors.New("NotLeader")
)
type VolumeView struct {
VolName string
MetaPartitions []*MetaPartition

View File

@ -27,7 +27,6 @@ var (
NoSpaceError = errors.New("no space left on the device")
TryAgainError = errors.New("try again")
CrcMismatchError = errors.New("packet Crc is incorrect")
NotALeaderError = errors.New("not a raft leader")
NoLeaderError = errors.New("no raft leader")
ExtentNotFoundError = errors.New("extent does not exist")
ExtentExistsError = errors.New("extent already exists")

88
util/errors/errors.go Normal file
View File

@ -0,0 +1,88 @@
// Copyright 2018 The Chubao Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package errors
import (
"fmt"
"path"
"runtime"
"strings"
)
type ErrorTrace struct {
msg string
}
func New(msg string) error {
return &ErrorTrace{msg: msg}
}
func NewError(err error) error {
if err == nil {
return nil
}
_, file, line, _ := runtime.Caller(1)
_, fileName := path.Split(file)
return &ErrorTrace{
msg: fmt.Sprintf("[%v %v] %v", fileName, line, err.Error()),
}
}
func NewErrorf(format string, a ...interface{}) error {
msg := fmt.Sprintf(format, a...)
_, file, line, _ := runtime.Caller(1)
_, fileName := path.Split(file)
return &ErrorTrace{
msg: fmt.Sprintf("[%v %v] %v", fileName, line, msg),
}
}
func (e *ErrorTrace) Error() string {
return e.msg
}
func Trace(err error, format string, a ...interface{}) error {
msg := fmt.Sprintf(format, a...)
_, file, line, _ := runtime.Caller(1)
_, fileName := path.Split(file)
if err == nil {
return &ErrorTrace{
msg: fmt.Sprintf("[%v %v] %v", fileName, line, msg),
}
}
return &ErrorTrace{
msg: fmt.Sprintf("[%v %v] %v :: %v", fileName, line, msg, err),
}
}
func Stack(err error) string {
e, ok := err.(*ErrorTrace)
if !ok {
return err.Error()
}
var msg string
stack := strings.Split(e.msg, "::")
for _, s := range stack {
msg = fmt.Sprintf("%v\n%v", msg, strings.TrimPrefix(s, " "))
}
return msg
}

View File

@ -0,0 +1,35 @@
package errors
import (
"testing"
)
func init() {
}
func TestError01(t *testing.T) {
err := New("first")
err = NewError(err)
err = Trace(err, "second(%v %v)", 2, 3)
err = Trace(err, "third(%v %v)", 4, 5)
t.Log(err)
t.Log(Stack(err))
}
func TestError02(t *testing.T) {
var err error
err = Trace(nil, "first(%v %v)", 2, 3)
err = Trace(err, "second(%v %v)", 4, 5)
t.Log(err)
t.Log(Stack(err))
}
func TestError03(t *testing.T) {
var err error
err = Trace(nil, "first")
err = Trace(err, "second(%v %v)", 4, 5)
t.Log(err)
t.Log(Stack(err))
}

View File

@ -140,21 +140,20 @@ func (writer *asyncWriter) flushToFile() {
writer.mu.Lock()
writer.buffer, writer.flushTmp = writer.flushTmp, writer.buffer
writer.mu.Unlock()
isRotateDay := false // TODO rename?
isRotateDay := false
select {
case <-writer.rotateDay:
isRotateDay = true
default:
}
flushLength := writer.flushTmp.Len()
if (writer.logSize+int64(flushLength))/(1024*1024) >= writer.
if (writer.logSize+int64(flushLength)) >= writer.
rollingSize || isRotateDay {
oldFile := writer.fileName + "." + time.Now().Format(
FileNameDateFormat) + RolledExtension
if _, err := os.Lstat(oldFile); err != nil {
if err := writer.rename(oldFile); err == nil {
if fp, err := os.OpenFile(writer.fileName, FileOpt, 0666); err == nil {
// TODO Unhandled errors
writer.file.Close()
writer.file = fp
writer.logSize = 0
@ -225,7 +224,6 @@ func newLogObject(writer *asyncWriter, prefix string, flag int) *LogObject {
// Log defines the log struct.
type Log struct {
dir string
module string
errorLogger *LogObject
warnLogger *LogObject
debugLogger *LogObject
@ -252,12 +250,10 @@ var gLog *Log = nil
// InitLog initializes the log.
func InitLog(dir, module string, level Level, rotate *LogRotate) (*Log, error) {
l := new(Log)
dir = path.Join(dir, module)
l.dir = dir
l.module = module
fi, err := os.Stat(dir)
if err != nil {
// TODO unhandled errors
// TODO there are many unhandled errors in this file.
os.MkdirAll(dir, 0755)
} else {
if !fi.IsDir() {

View File

@ -17,7 +17,7 @@ package log
const (
// DefaultRollingSize Specifies at what size to roll the output log at
// Units: MB
DefaultRollingSize = 10 * 1024
DefaultRollingSize = 20 * 1024 * 1024 * 1024
// DefaultHeadRoom The tolerance for the log space limit (in megabytes)
DefaultHeadRoom = 50 * 1024
// DefaultHeadRatio The disk reserve space ratio

View File

@ -16,12 +16,16 @@ package util
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const MEMINFO = "/proc/meminfo"
const (
MEMINFO = "/proc/meminfo"
PRO_MEM = "/proc/%d/status"
)
// GetMemInfo returns the memory information.
func GetMemInfo() (total, used uint64, err error) {
@ -65,3 +69,30 @@ func GetMemInfo() (total, used uint64, err error) {
used = total - free - buffer - cached
return
}
func GetProcessMemory(pid int) (used uint64, err error) {
proFileName := fmt.Sprintf(PRO_MEM, pid)
fp, err := os.Open(proFileName)
if err != nil {
return
}
defer fp.Close()
scan := bufio.NewScanner(fp)
for scan.Scan() {
line := scan.Text()
fields := strings.Split(line, ":")
key := fields[0]
if key != "VmRSS" {
continue
}
value := strings.TrimSpace(fields[1])
value = strings.Replace(value, " kB", "", -1)
used, err = strconv.ParseUint(value, 10, 64)
if err != nil {
return
}
used = used * KB
break
}
return
}

127
util/ump/ump.go Normal file
View File

@ -0,0 +1,127 @@
// Copyright 2018 The ChubaoFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package ump
import (
"runtime"
"strconv"
"sync"
"time"
)
type TpObject struct {
StartTime time.Time
EndTime time.Time
UmpType interface{}
}
func NewTpObject() (o *TpObject) {
o = new(TpObject)
o.StartTime = time.Now()
return
}
const (
TpMethod = "TP"
HeartbeatMethod = "Heartbeat"
FunctionError = "FunctionError"
)
var (
HostName string
LogTimeForMat = "20060102150405000"
AlarmPool = &sync.Pool{New: func() interface{} {
return new(BusinessAlarm)
}}
TpObjectPool = &sync.Pool{New: func() interface{} {
return new(TpObject)
}}
SystemAlivePool = &sync.Pool{New: func() interface{} {
return new(SystemAlive)
}}
FunctionTpPool = &sync.Pool{New: func() interface{} {
return new(FunctionTp)
}}
)
func InitUmp(module, dataDir string) {
runtime.GOMAXPROCS(runtime.NumCPU())
if err := initLogName(module, dataDir); err != nil {
panic("init UMP Monitor failed " + err.Error())
}
backGroudWrite()
}
func BeforeTP(key string) (o *TpObject) {
o = TpObjectPool.Get().(*TpObject)
o.StartTime = time.Now()
tp := FunctionTpPool.Get().(*FunctionTp)
tp.HostName = HostName
tp.Time = time.Now().Format(LogTimeForMat)
tp.Key = key
tp.ProcessState = "0"
o.UmpType = tp
return
}
func AfterTP(o *TpObject, err error) {
tp := o.UmpType.(*FunctionTp)
tp.ElapsedTime = strconv.FormatInt((int64)(time.Since(o.StartTime)/1e6), 10)
TpObjectPool.Put(o)
tp.ProcessState = "0"
if err != nil {
tp.ProcessState = "1"
}
select {
case FunctionTpLogWrite.logCh <- tp:
default:
}
return
}
func Alive(key string) {
alive := SystemAlivePool.Get().(*SystemAlive)
alive.HostName = HostName
alive.Key = key
alive.Time = time.Now().Format(LogTimeForMat)
select {
case SystemAliveLogWrite.logCh <- alive:
default:
}
return
}
func Alarm(key, detail string) {
alarm := AlarmPool.Get().(*BusinessAlarm)
alarm.Time = time.Now().Format(LogTimeForMat)
alarm.Key = key
alarm.HostName = HostName
alarm.BusinessType = "0"
alarm.Value = "0"
alarm.Detail = detail
if len(alarm.Detail) > 512 {
rs := []rune(detail)
alarm.Detail = string(rs[0:510])
}
select {
case BusinessAlarmLogWrite.logCh <- alarm:
default:
}
return
}

205
util/ump/ump_async_log.go Normal file
View File

@ -0,0 +1,205 @@
// Copyright 2018 The ChubaoFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package ump
import (
"encoding/json"
"fmt"
"net"
"os"
"strings"
)
type FunctionTp struct {
Time string `json:"time"`
Key string `json:"key"`
HostName string `json:"hostname"`
ProcessState string `json:"processState"`
ElapsedTime string `json:"elapsedTime"`
}
type SystemAlive struct {
Key string `json:"key"`
HostName string `json:"hostname"`
Time string `json:"time"`
}
type BusinessAlarm struct {
Time string `json:"time"`
Key string `json:"key"`
HostName string `json:"hostname"`
BusinessType string `json:"type"`
Value string `json:"value"`
Detail string `json:"detail"`
}
const (
FunctionTpSufixx = "tp.log"
SystemAliveSufixx = "alive.log"
BusinessAlarmSufixx = "business.log"
LogFileOpt = os.O_RDWR | os.O_CREATE | os.O_APPEND
ChSize = 102400
BusinessAlarmType = "BusinessAlarm"
SystemAliveType = "SystemAlive"
FunctionTpType = "FunctionTp"
HostNameFile = "/proc/sys/kernel/hostname"
MaxLogSize = 1024 * 1024 * 10
)
var (
FunctionTpLogWrite = &LogWrite{logCh: make(chan interface{}, ChSize)}
SystemAliveLogWrite = &LogWrite{logCh: make(chan interface{}, ChSize)}
BusinessAlarmLogWrite = &LogWrite{logCh: make(chan interface{}, ChSize)}
UmpDataDir = "/export/home/tomcat/UMP-Monitor/logs/"
)
type LogWrite struct {
logCh chan interface{}
logName string
logSize int64
seq int
logSufixx string
logFp *os.File
sigCh chan bool
}
func (lw *LogWrite) initLogFp(sufixx string) (err error) {
var fi os.FileInfo
lw.seq = 0
lw.sigCh = make(chan bool, 1)
lw.logSufixx = sufixx
lw.logName = fmt.Sprintf("%s%s%s", UmpDataDir, "ump_", lw.logSufixx)
if lw.logFp, err = os.OpenFile(lw.logName, LogFileOpt, 0666); err != nil {
return
}
if fi, err = lw.logFp.Stat(); err != nil {
return
}
lw.logSize = fi.Size()
return
}
func (lw *LogWrite) backGroundCheckFile() (err error) {
if lw.logSize <= MaxLogSize {
return
}
lw.logFp.Close()
lw.seq++
if lw.seq > 3 {
lw.seq = 1
}
name := fmt.Sprintf("%s%s%s.%d", UmpDataDir, "ump_", lw.logSufixx, lw.seq)
if _, err = os.Stat(name); err == nil {
os.Remove(name)
}
os.Rename(lw.logName, name)
if lw.logFp, err = os.OpenFile(lw.logName, LogFileOpt, 0666); err != nil {
lw.seq--
return
}
if err = os.Truncate(lw.logName, 0); err != nil {
lw.seq--
return
}
lw.logSize = 0
return
}
func (lw *LogWrite) backGroundWrite(umpType string) {
var (
body []byte
)
for {
obj := <-lw.logCh
switch umpType {
case FunctionTpType:
tp := obj.(*FunctionTp)
body, _ = json.Marshal(tp)
FunctionTpPool.Put(tp)
case SystemAliveType:
alive := obj.(*SystemAlive)
body, _ = json.Marshal(alive)
SystemAlivePool.Put(alive)
case BusinessAlarmType:
alarm := obj.(*BusinessAlarm)
body, _ = json.Marshal(alarm)
AlarmPool.Put(alarm)
}
if lw.backGroundCheckFile() != nil {
continue
}
body = append(body, []byte("\n")...)
lw.logFp.Write(body)
lw.logSize += (int64)(len(body))
}
}
func initLogName(module, dataDir string) (err error) {
if dataDir != "" {
UmpDataDir = dataDir
if !strings.HasSuffix(UmpDataDir, "/") {
UmpDataDir += "/"
}
}
if err = os.MkdirAll(UmpDataDir, 0666); err != nil {
return
}
if HostName, err = GetLocalIpAddr(); err != nil {
return
}
if err = FunctionTpLogWrite.initLogFp(module + "_" + FunctionTpSufixx); err != nil {
return
}
if err = SystemAliveLogWrite.initLogFp(module + "_" + SystemAliveSufixx); err != nil {
return
}
if err = BusinessAlarmLogWrite.initLogFp(module + "_" + BusinessAlarmSufixx); err != nil {
return
}
return
}
func GetLocalIpAddr() (localAddr string, err error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return
}
for _, addr := range addrs {
if ipNet, isIpNet := addr.(*net.IPNet); isIpNet && !ipNet.IP.IsLoopback() {
if ipv4 := ipNet.IP.To4(); ipv4 != nil {
localAddr = ipv4.String()
return
}
}
}
err = fmt.Errorf("cannot get local ip")
return
}
func backGroudWrite() {
go FunctionTpLogWrite.backGroundWrite(FunctionTpType)
go SystemAliveLogWrite.backGroundWrite(SystemAliveType)
go BusinessAlarmLogWrite.backGroundWrite(BusinessAlarmType)
}

View File

@ -1,23 +0,0 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test

191
vendor/github.com/juju/errors/LICENSE generated vendored
View File

@ -1,191 +0,0 @@
All files in this repository are licensed as follows. If you contribute
to this repository, it is assumed that you license your contribution
under the same license unless you state otherwise.
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
This software is licensed under the LGPLv3, included below.
As a special exception to the GNU Lesser General Public License version 3
("LGPL3"), the copyright holders of this Library give you permission to
convey to a third party a Combined Work that links statically or dynamically
to this Library without providing any Minimal Corresponding Source or
Minimal Application Code as set out in 4d or providing the installation
information set out in section 4e, provided that you comply with the other
provisions of LGPL3 and provided that you meet, for the Application the
terms and conditions of the license(s) which apply to the Application.
Except as stated in this special exception, the provisions of LGPL3 will
continue to comply in full to this Library. If you modify this Library, you
may apply this exception to your version of this Library, but you are not
obliged to do so. If you do not wish to do so, delete this exception
statement from your version. This exception does not (and cannot) modify any
license terms which apply to the Application, with which you must still
comply.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -1,11 +0,0 @@
default: check
check:
go test && go test -compiler gccgo
docs:
godoc2md github.com/juju/errors > README.md
sed -i 's|\[godoc-link-here\]|[![GoDoc](https://godoc.org/github.com/juju/errors?status.svg)](https://godoc.org/github.com/juju/errors)|' README.md
.PHONY: default check docs

View File

@ -1,543 +0,0 @@
# errors
import "github.com/juju/errors"
[![GoDoc](https://godoc.org/github.com/juju/errors?status.svg)](https://godoc.org/github.com/juju/errors)
The juju/errors provides an easy way to annotate errors without losing the
orginal error context.
The exported `New` and `Errorf` functions are designed to replace the
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
error is there, but the package also records the location at which the error
was created.
A primary use case for this library is to add extra context any time an
error is returned from a function.
if err := SomeFunc(); err != nil {
return err
}
This instead becomes:
if err := SomeFunc(); err != nil {
return errors.Trace(err)
}
which just records the file and line number of the Trace call, or
if err := SomeFunc(); err != nil {
return errors.Annotate(err, "more context")
}
which also adds an annotation to the error.
When you want to check to see if an error is of a particular type, a helper
function is normally exported by the package that returned the error, like the
`os` package does. The underlying cause of the error is available using the
`Cause` function.
os.IsNotExist(errors.Cause(err))
The result of the `Error()` call on an annotated error is the annotations joined
with colons, then the result of the `Error()` method for the underlying error
that was the cause.
err := errors.Errorf("original")
err = errors.Annotatef(err, "context")
err = errors.Annotatef(err, "more context")
err.Error() -> "more context: context: original"
Obviously recording the file, line and functions is not very useful if you
cannot get them back out again.
errors.ErrorStack(err)
will return something like:
first error
github.com/juju/errors/annotation_test.go:193:
github.com/juju/errors/annotation_test.go:194: annotation
github.com/juju/errors/annotation_test.go:195:
github.com/juju/errors/annotation_test.go:196: more context
github.com/juju/errors/annotation_test.go:197:
The first error was generated by an external system, so there was no location
associated. The second, fourth, and last lines were generated with Trace calls,
and the other two through Annotate.
Sometimes when responding to an error you want to return a more specific error
for the situation.
if err := FindField(field); err != nil {
return errors.Wrap(err, errors.NotFoundf(field))
}
This returns an error where the complete error stack is still available, and
`errors.Cause()` will return the `NotFound` error.
## func AlreadyExistsf
``` go
func AlreadyExistsf(format string, args ...interface{}) error
```
AlreadyExistsf returns an error which satisfies IsAlreadyExists().
## func Annotate
``` go
func Annotate(other error, message string) error
```
Annotate is used to add extra context to an existing error. The location of
the Annotate call is recorded with the annotations. The file, line and
function are also recorded.
For example:
if err := SomeFunc(); err != nil {
return errors.Annotate(err, "failed to frombulate")
}
## func Annotatef
``` go
func Annotatef(other error, format string, args ...interface{}) error
```
Annotatef is used to add extra context to an existing error. The location of
the Annotate call is recorded with the annotations. The file, line and
function are also recorded.
For example:
if err := SomeFunc(); err != nil {
return errors.Annotatef(err, "failed to frombulate the %s", arg)
}
## func Cause
``` go
func Cause(err error) error
```
Cause returns the cause of the given error. This will be either the
original error, or the result of a Wrap or Mask call.
Cause is the usual way to diagnose errors that may have been wrapped by
the other errors functions.
## func DeferredAnnotatef
``` go
func DeferredAnnotatef(err *error, format string, args ...interface{})
```
DeferredAnnotatef annotates the given error (when it is not nil) with the given
format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
does nothing. This method is used in a defer statement in order to annotate any
resulting error with the same message.
For example:
defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
## func Details
``` go
func Details(err error) string
```
Details returns information about the stack of errors wrapped by err, in
the format:
[{filename:99: error one} {otherfile:55: cause of error one}]
This is a terse alternative to ErrorStack as it returns a single line.
## func ErrorStack
``` go
func ErrorStack(err error) string
```
ErrorStack returns a string representation of the annotated error. If the
error passed as the parameter is not an annotated error, the result is
simply the result of the Error() method on that error.
If the error is an annotated error, a multi-line string is returned where
each line represents one entry in the annotation stack. The full filename
from the call stack is used in the output.
first error
github.com/juju/errors/annotation_test.go:193:
github.com/juju/errors/annotation_test.go:194: annotation
github.com/juju/errors/annotation_test.go:195:
github.com/juju/errors/annotation_test.go:196: more context
github.com/juju/errors/annotation_test.go:197:
## func Errorf
``` go
func Errorf(format string, args ...interface{}) error
```
Errorf creates a new annotated error and records the location that the
error is created. This should be a drop in replacement for fmt.Errorf.
For example:
return errors.Errorf("validation failed: %s", message)
## func IsAlreadyExists
``` go
func IsAlreadyExists(err error) bool
```
IsAlreadyExists reports whether the error was created with
AlreadyExistsf() or NewAlreadyExists().
## func IsNotFound
``` go
func IsNotFound(err error) bool
```
IsNotFound reports whether err was created with NotFoundf() or
NewNotFound().
## func IsNotImplemented
``` go
func IsNotImplemented(err error) bool
```
IsNotImplemented reports whether err was created with
NotImplementedf() or NewNotImplemented().
## func IsNotSupported
``` go
func IsNotSupported(err error) bool
```
IsNotSupported reports whether the error was created with
NotSupportedf() or NewNotSupported().
## func IsNotValid
``` go
func IsNotValid(err error) bool
```
IsNotValid reports whether the error was created with NotValidf() or
NewNotValid().
## func IsUnauthorized
``` go
func IsUnauthorized(err error) bool
```
IsUnauthorized reports whether err was created with Unauthorizedf() or
NewUnauthorized().
## func Mask
``` go
func Mask(other error) error
```
Mask hides the underlying error type, and records the location of the masking.
## func Maskf
``` go
func Maskf(other error, format string, args ...interface{}) error
```
Mask masks the given error with the given format string and arguments (like
fmt.Sprintf), returning a new error that maintains the error stack, but
hides the underlying error type. The error string still contains the full
annotations. If you want to hide the annotations, call Wrap.
## func New
``` go
func New(message string) error
```
New is a drop in replacement for the standard libary errors module that records
the location that the error is created.
For example:
return errors.New("validation failed")
## func NewAlreadyExists
``` go
func NewAlreadyExists(err error, msg string) error
```
NewAlreadyExists returns an error which wraps err and satisfies
IsAlreadyExists().
## func NewNotFound
``` go
func NewNotFound(err error, msg string) error
```
NewNotFound returns an error which wraps err that satisfies
IsNotFound().
## func NewNotImplemented
``` go
func NewNotImplemented(err error, msg string) error
```
NewNotImplemented returns an error which wraps err and satisfies
IsNotImplemented().
## func NewNotSupported
``` go
func NewNotSupported(err error, msg string) error
```
NewNotSupported returns an error which wraps err and satisfies
IsNotSupported().
## func NewNotValid
``` go
func NewNotValid(err error, msg string) error
```
NewNotValid returns an error which wraps err and satisfies IsNotValid().
## func NewUnauthorized
``` go
func NewUnauthorized(err error, msg string) error
```
NewUnauthorized returns an error which wraps err and satisfies
IsUnauthorized().
## func NotFoundf
``` go
func NotFoundf(format string, args ...interface{}) error
```
NotFoundf returns an error which satisfies IsNotFound().
## func NotImplementedf
``` go
func NotImplementedf(format string, args ...interface{}) error
```
NotImplementedf returns an error which satisfies IsNotImplemented().
## func NotSupportedf
``` go
func NotSupportedf(format string, args ...interface{}) error
```
NotSupportedf returns an error which satisfies IsNotSupported().
## func NotValidf
``` go
func NotValidf(format string, args ...interface{}) error
```
NotValidf returns an error which satisfies IsNotValid().
## func Trace
``` go
func Trace(other error) error
```
Trace adds the location of the Trace call to the stack. The Cause of the
resulting error is the same as the error parameter. If the other error is
nil, the result will be nil.
For example:
if err := SomeFunc(); err != nil {
return errors.Trace(err)
}
## func Unauthorizedf
``` go
func Unauthorizedf(format string, args ...interface{}) error
```
Unauthorizedf returns an error which satisfies IsUnauthorized().
## func Forbiddenf
``` go
func Forbiddenf(format string, args ...interface{}) error
```
Forbiddenf returns an error which satisfies IsForbidden().
## func Wrap
``` go
func Wrap(other, newDescriptive error) error
```
Wrap changes the Cause of the error. The location of the Wrap call is also
stored in the error stack.
For example:
if err := SomeFunc(); err != nil {
newErr := &packageError{"more context", private_value}
return errors.Wrap(err, newErr)
}
## func Wrapf
``` go
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error
```
Wrapf changes the Cause of the error, and adds an annotation. The location
of the Wrap call is also stored in the error stack.
For example:
if err := SomeFunc(); err != nil {
return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
}
## type Err
``` go
type Err struct {
// contains filtered or unexported fields
}
```
Err holds a description of an error along with information about
where the error was created.
It may be embedded in custom error types to add extra information that
this errors package can understand.
### func NewErr
``` go
func NewErr(format string, args ...interface{}) Err
```
NewErr is used to return an Err for the purpose of embedding in other
structures. The location is not specified, and needs to be set with a call
to SetLocation.
For example:
type FooError struct {
errors.Err
code int
}
func NewFooError(code int) error {
err := &FooError{errors.NewErr("foo"), code}
err.SetLocation(1)
return err
}
### func (\*Err) Cause
``` go
func (e *Err) Cause() error
```
The Cause of an error is the most recent error in the error stack that
meets one of these criteria: the original error that was raised; the new
error that was passed into the Wrap function; the most recently masked
error; or nil if the error itself is considered the Cause. Normally this
method is not invoked directly, but instead through the Cause stand alone
function.
### func (\*Err) Error
``` go
func (e *Err) Error() string
```
Error implements error.Error.
### func (\*Err) Location
``` go
func (e *Err) Location() (filename string, line int)
```
Location is the file and line of where the error was most recently
created or annotated.
### func (\*Err) Message
``` go
func (e *Err) Message() string
```
Message returns the message stored with the most recent location. This is
the empty string if the most recent call was Trace, or the message stored
with Annotate or Mask.
### func (\*Err) SetLocation
``` go
func (e *Err) SetLocation(callDepth int)
```
SetLocation records the source location of the error at callDepth stack
frames above the call.
### func (\*Err) StackTrace
``` go
func (e *Err) StackTrace() []string
```
StackTrace returns one string for each location recorded in the stack of
errors. The first value is the originating error, with a line for each
other annotation or tracing of the error.
### func (\*Err) Underlying
``` go
func (e *Err) Underlying() error
```
Underlying returns the previous error in the error stack, if any. A client
should not ever really call this method. It is used to build the error
stack and should not be introspected by client calls. Or more
specifically, clients should not depend on anything but the `Cause` of an
error.
- - -
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)

81
vendor/github.com/juju/errors/doc.go generated vendored
View File

@ -1,81 +0,0 @@
// Copyright 2013, 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
/*
[godoc-link-here]
The juju/errors provides an easy way to annotate errors without losing the
orginal error context.
The exported `New` and `Errorf` functions are designed to replace the
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
error is there, but the package also records the location at which the error
was created.
A primary use case for this library is to add extra context any time an
error is returned from a function.
if err := SomeFunc(); err != nil {
return err
}
This instead becomes:
if err := SomeFunc(); err != nil {
return errors.Trace(err)
}
which just records the file and line number of the Trace call, or
if err := SomeFunc(); err != nil {
return errors.Annotate(err, "more context")
}
which also adds an annotation to the error.
When you want to check to see if an error is of a particular type, a helper
function is normally exported by the package that returned the error, like the
`os` package does. The underlying cause of the error is available using the
`Cause` function.
os.IsNotExist(errors.Cause(err))
The result of the `Error()` call on an annotated error is the annotations joined
with colons, then the result of the `Error()` method for the underlying error
that was the cause.
err := errors.Errorf("original")
err = errors.Annotatef(err, "context")
err = errors.Annotatef(err, "more context")
err.Error() -> "more context: context: original"
Obviously recording the file, line and functions is not very useful if you
cannot get them back out again.
errors.ErrorStack(err)
will return something like:
first error
github.com/juju/errors/annotation_test.go:193:
github.com/juju/errors/annotation_test.go:194: annotation
github.com/juju/errors/annotation_test.go:195:
github.com/juju/errors/annotation_test.go:196: more context
github.com/juju/errors/annotation_test.go:197:
The first error was generated by an external system, so there was no location
associated. The second, fourth, and last lines were generated with Trace calls,
and the other two through Annotate.
Sometimes when responding to an error you want to return a more specific error
for the situation.
if err := FindField(field); err != nil {
return errors.Wrap(err, errors.NotFoundf(field))
}
This returns an error where the complete error stack is still available, and
`errors.Cause()` will return the `NotFound` error.
*/
package errors

View File

@ -1,172 +0,0 @@
// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors
import (
"fmt"
"reflect"
"runtime"
)
// Err holds a description of an error along with information about
// where the error was created.
//
// It may be embedded in custom error types to add extra information that
// this errors package can understand.
type Err struct {
// message holds an annotation of the error.
message string
// cause holds the cause of the error as returned
// by the Cause method.
cause error
// previous holds the previous error in the error stack, if any.
previous error
// file and line hold the source code location where the error was
// created.
file string
line int
}
// NewErr is used to return an Err for the purpose of embedding in other
// structures. The location is not specified, and needs to be set with a call
// to SetLocation.
//
// For example:
// type FooError struct {
// errors.Err
// code int
// }
//
// func NewFooError(code int) error {
// err := &FooError{errors.NewErr("foo"), code}
// err.SetLocation(1)
// return err
// }
func NewErr(format string, args ...interface{}) Err {
return Err{
message: fmt.Sprintf(format, args...),
}
}
// NewErrWithCause is used to return an Err with case by other error for the purpose of embedding in other
// structures. The location is not specified, and needs to be set with a call
// to SetLocation.
//
// For example:
// type FooError struct {
// errors.Err
// code int
// }
//
// func (e *FooError) Annotate(format string, args ...interface{}) error {
// err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
// err.SetLocation(1)
// return err
// })
func NewErrWithCause(other error, format string, args ...interface{}) Err {
return Err{
message: fmt.Sprintf(format, args...),
cause: Cause(other),
previous: other,
}
}
// Location is the file and line of where the error was most recently
// created or annotated.
func (e *Err) Location() (filename string, line int) {
return e.file, e.line
}
// Underlying returns the previous error in the error stack, if any. A client
// should not ever really call this method. It is used to build the error
// stack and should not be introspected by client calls. Or more
// specifically, clients should not depend on anything but the `Cause` of an
// error.
func (e *Err) Underlying() error {
return e.previous
}
// The Cause of an error is the most recent error in the error stack that
// meets one of these criteria: the original error that was raised; the new
// error that was passed into the Wrap function; the most recently masked
// error; or nil if the error itself is considered the Cause. Normally this
// method is not invoked directly, but instead through the Cause stand alone
// function.
func (e *Err) Cause() error {
return e.cause
}
// Message returns the message stored with the most recent location. This is
// the empty string if the most recent call was Trace, or the message stored
// with Annotate or Mask.
func (e *Err) Message() string {
return e.message
}
// Error implements error.Error.
func (e *Err) Error() string {
// We want to walk up the stack of errors showing the annotations
// as long as the cause is the same.
err := e.previous
if !sameError(Cause(err), e.cause) && e.cause != nil {
err = e.cause
}
switch {
case err == nil:
return e.message
case e.message == "":
return err.Error()
}
return fmt.Sprintf("%s: %v", e.message, err)
}
// Format implements fmt.Formatter
// When printing errors with %+v it also prints the stack trace.
// %#v unsurprisingly will print the real underlying type.
func (e *Err) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case s.Flag('+'):
fmt.Fprintf(s, "%s", ErrorStack(e))
return
case s.Flag('#'):
// avoid infinite recursion by wrapping e into a type
// that doesn't implement Formatter.
fmt.Fprintf(s, "%#v", (*unformatter)(e))
return
}
fallthrough
case 's':
fmt.Fprintf(s, "%s", e.Error())
}
}
// helper for Format
type unformatter Err
func (unformatter) Format() { /* break the fmt.Formatter interface */ }
// SetLocation records the source location of the error at callDepth stack
// frames above the call.
func (e *Err) SetLocation(callDepth int) {
_, file, line, _ := runtime.Caller(callDepth + 1)
e.file = trimGoPath(file)
e.line = line
}
// StackTrace returns one string for each location recorded in the stack of
// errors. The first value is the originating error, with a line for each
// other annotation or tracing of the error.
func (e *Err) StackTrace() []string {
return errorStack(e)
}
// Ideally we'd have a way to check identity, but deep equals will do.
func sameError(e1, e2 error) bool {
return reflect.DeepEqual(e1, e2)
}

View File

@ -1,309 +0,0 @@
// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors
import (
"fmt"
)
// wrap is a helper to construct an *wrapper.
func wrap(err error, format, suffix string, args ...interface{}) Err {
newErr := Err{
message: fmt.Sprintf(format+suffix, args...),
previous: err,
}
newErr.SetLocation(2)
return newErr
}
// notFound represents an error when something has not been found.
type notFound struct {
Err
}
// NotFoundf returns an error which satisfies IsNotFound().
func NotFoundf(format string, args ...interface{}) error {
return &notFound{wrap(nil, format, " not found", args...)}
}
// NewNotFound returns an error which wraps err that satisfies
// IsNotFound().
func NewNotFound(err error, msg string) error {
return &notFound{wrap(err, msg, "")}
}
// IsNotFound reports whether err was created with NotFoundf() or
// NewNotFound().
func IsNotFound(err error) bool {
err = Cause(err)
_, ok := err.(*notFound)
return ok
}
// userNotFound represents an error when an inexistent user is looked up.
type userNotFound struct {
Err
}
// UserNotFoundf returns an error which satisfies IsUserNotFound().
func UserNotFoundf(format string, args ...interface{}) error {
return &userNotFound{wrap(nil, format, " user not found", args...)}
}
// NewUserNotFound returns an error which wraps err and satisfies
// IsUserNotFound().
func NewUserNotFound(err error, msg string) error {
return &userNotFound{wrap(err, msg, "")}
}
// IsUserNotFound reports whether err was created with UserNotFoundf() or
// NewUserNotFound().
func IsUserNotFound(err error) bool {
err = Cause(err)
_, ok := err.(*userNotFound)
return ok
}
// unauthorized represents an error when an operation is unauthorized.
type unauthorized struct {
Err
}
// Unauthorizedf returns an error which satisfies IsUnauthorized().
func Unauthorizedf(format string, args ...interface{}) error {
return &unauthorized{wrap(nil, format, "", args...)}
}
// NewUnauthorized returns an error which wraps err and satisfies
// IsUnauthorized().
func NewUnauthorized(err error, msg string) error {
return &unauthorized{wrap(err, msg, "")}
}
// IsUnauthorized reports whether err was created with Unauthorizedf() or
// NewUnauthorized().
func IsUnauthorized(err error) bool {
err = Cause(err)
_, ok := err.(*unauthorized)
return ok
}
// notImplemented represents an error when something is not
// implemented.
type notImplemented struct {
Err
}
// NotImplementedf returns an error which satisfies IsNotImplemented().
func NotImplementedf(format string, args ...interface{}) error {
return &notImplemented{wrap(nil, format, " not implemented", args...)}
}
// NewNotImplemented returns an error which wraps err and satisfies
// IsNotImplemented().
func NewNotImplemented(err error, msg string) error {
return &notImplemented{wrap(err, msg, "")}
}
// IsNotImplemented reports whether err was created with
// NotImplementedf() or NewNotImplemented().
func IsNotImplemented(err error) bool {
err = Cause(err)
_, ok := err.(*notImplemented)
return ok
}
// alreadyExists represents and error when something already exists.
type alreadyExists struct {
Err
}
// AlreadyExistsf returns an error which satisfies IsAlreadyExists().
func AlreadyExistsf(format string, args ...interface{}) error {
return &alreadyExists{wrap(nil, format, " already exists", args...)}
}
// NewAlreadyExists returns an error which wraps err and satisfies
// IsAlreadyExists().
func NewAlreadyExists(err error, msg string) error {
return &alreadyExists{wrap(err, msg, "")}
}
// IsAlreadyExists reports whether the error was created with
// AlreadyExistsf() or NewAlreadyExists().
func IsAlreadyExists(err error) bool {
err = Cause(err)
_, ok := err.(*alreadyExists)
return ok
}
// notSupported represents an error when something is not supported.
type notSupported struct {
Err
}
// NotSupportedf returns an error which satisfies IsNotSupported().
func NotSupportedf(format string, args ...interface{}) error {
return &notSupported{wrap(nil, format, " not supported", args...)}
}
// NewNotSupported returns an error which wraps err and satisfies
// IsNotSupported().
func NewNotSupported(err error, msg string) error {
return &notSupported{wrap(err, msg, "")}
}
// IsNotSupported reports whether the error was created with
// NotSupportedf() or NewNotSupported().
func IsNotSupported(err error) bool {
err = Cause(err)
_, ok := err.(*notSupported)
return ok
}
// notValid represents an error when something is not valid.
type notValid struct {
Err
}
// NotValidf returns an error which satisfies IsNotValid().
func NotValidf(format string, args ...interface{}) error {
return &notValid{wrap(nil, format, " not valid", args...)}
}
// NewNotValid returns an error which wraps err and satisfies IsNotValid().
func NewNotValid(err error, msg string) error {
return &notValid{wrap(err, msg, "")}
}
// IsNotValid reports whether the error was created with NotValidf() or
// NewNotValid().
func IsNotValid(err error) bool {
err = Cause(err)
_, ok := err.(*notValid)
return ok
}
// notProvisioned represents an error when something is not yet provisioned.
type notProvisioned struct {
Err
}
// NotProvisionedf returns an error which satisfies IsNotProvisioned().
func NotProvisionedf(format string, args ...interface{}) error {
return &notProvisioned{wrap(nil, format, " not provisioned", args...)}
}
// NewNotProvisioned returns an error which wraps err that satisfies
// IsNotProvisioned().
func NewNotProvisioned(err error, msg string) error {
return &notProvisioned{wrap(err, msg, "")}
}
// IsNotProvisioned reports whether err was created with NotProvisionedf() or
// NewNotProvisioned().
func IsNotProvisioned(err error) bool {
err = Cause(err)
_, ok := err.(*notProvisioned)
return ok
}
// notAssigned represents an error when something is not yet assigned to
// something else.
type notAssigned struct {
Err
}
// NotAssignedf returns an error which satisfies IsNotAssigned().
func NotAssignedf(format string, args ...interface{}) error {
return &notAssigned{wrap(nil, format, " not assigned", args...)}
}
// NewNotAssigned returns an error which wraps err that satisfies
// IsNotAssigned().
func NewNotAssigned(err error, msg string) error {
return &notAssigned{wrap(err, msg, "")}
}
// IsNotAssigned reports whether err was created with NotAssignedf() or
// NewNotAssigned().
func IsNotAssigned(err error) bool {
err = Cause(err)
_, ok := err.(*notAssigned)
return ok
}
// badRequest represents an error when a request has bad parameters.
type badRequest struct {
Err
}
// BadRequestf returns an error which satisfies IsBadRequest().
func BadRequestf(format string, args ...interface{}) error {
return &badRequest{wrap(nil, format, "", args...)}
}
// NewBadRequest returns an error which wraps err that satisfies
// IsBadRequest().
func NewBadRequest(err error, msg string) error {
return &badRequest{wrap(err, msg, "")}
}
// IsBadRequest reports whether err was created with BadRequestf() or
// NewBadRequest().
func IsBadRequest(err error) bool {
err = Cause(err)
_, ok := err.(*badRequest)
return ok
}
// methodNotAllowed represents an error when an HTTP request
// is made with an inappropriate method.
type methodNotAllowed struct {
Err
}
// MethodNotAllowedf returns an error which satisfies IsMethodNotAllowed().
func MethodNotAllowedf(format string, args ...interface{}) error {
return &methodNotAllowed{wrap(nil, format, "", args...)}
}
// NewMethodNotAllowed returns an error which wraps err that satisfies
// IsMethodNotAllowed().
func NewMethodNotAllowed(err error, msg string) error {
return &methodNotAllowed{wrap(err, msg, "")}
}
// IsMethodNotAllowed reports whether err was created with MethodNotAllowedf() or
// NewMethodNotAllowed().
func IsMethodNotAllowed(err error) bool {
err = Cause(err)
_, ok := err.(*methodNotAllowed)
return ok
}
// forbidden represents an error when a request cannot be completed because of
// missing privileges
type forbidden struct {
Err
}
// Forbiddenf returns an error which satistifes IsForbidden()
func Forbiddenf(format string, args ...interface{}) error {
return &forbidden{wrap(nil, format, "", args...)}
}
// NewForbidden returns an error which wraps err that satisfies
// IsForbidden().
func NewForbidden(err error, msg string) error {
return &forbidden{wrap(err, msg, "")}
}
// IsForbidden reports whether err was created with Forbiddenf() or
// NewForbidden().
func IsForbidden(err error) bool {
err = Cause(err)
_, ok := err.(*forbidden)
return ok
}

View File

@ -1,330 +0,0 @@
// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors
import (
"fmt"
"strings"
)
// New is a drop in replacement for the standard library errors module that records
// the location that the error is created.
//
// For example:
// return errors.New("validation failed")
//
func New(message string) error {
err := &Err{message: message}
err.SetLocation(1)
return err
}
// Errorf creates a new annotated error and records the location that the
// error is created. This should be a drop in replacement for fmt.Errorf.
//
// For example:
// return errors.Errorf("validation failed: %s", message)
//
func Errorf(format string, args ...interface{}) error {
err := &Err{message: fmt.Sprintf(format, args...)}
err.SetLocation(1)
return err
}
// Trace adds the location of the Trace call to the stack. The Cause of the
// resulting error is the same as the error parameter. If the other error is
// nil, the result will be nil.
//
// For example:
// if err := SomeFunc(); err != nil {
// return errors.Trace(err)
// }
//
func Trace(other error) error {
if other == nil {
return nil
}
err := &Err{previous: other, cause: Cause(other)}
err.SetLocation(1)
return err
}
// Annotate is used to add extra context to an existing error. The location of
// the Annotate call is recorded with the annotations. The file, line and
// function are also recorded.
//
// For example:
// if err := SomeFunc(); err != nil {
// return errors.Annotate(err, "failed to frombulate")
// }
//
func Annotate(other error, message string) error {
if other == nil {
return nil
}
err := &Err{
previous: other,
cause: Cause(other),
message: message,
}
err.SetLocation(1)
return err
}
// Annotatef is used to add extra context to an existing error. The location of
// the Annotate call is recorded with the annotations. The file, line and
// function are also recorded.
//
// For example:
// if err := SomeFunc(); err != nil {
// return errors.Annotatef(err, "failed to frombulate the %s", arg)
// }
//
func Annotatef(other error, format string, args ...interface{}) error {
if other == nil {
return nil
}
err := &Err{
previous: other,
cause: Cause(other),
message: fmt.Sprintf(format, args...),
}
err.SetLocation(1)
return err
}
// DeferredAnnotatef annotates the given error (when it is not nil) with the given
// format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
// does nothing. This method is used in a defer statement in order to annotate any
// resulting error with the same message.
//
// For example:
//
// defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
//
func DeferredAnnotatef(err *error, format string, args ...interface{}) {
if *err == nil {
return
}
newErr := &Err{
message: fmt.Sprintf(format, args...),
cause: Cause(*err),
previous: *err,
}
newErr.SetLocation(1)
*err = newErr
}
// Wrap changes the Cause of the error. The location of the Wrap call is also
// stored in the error stack.
//
// For example:
// if err := SomeFunc(); err != nil {
// newErr := &packageError{"more context", private_value}
// return errors.Wrap(err, newErr)
// }
//
func Wrap(other, newDescriptive error) error {
err := &Err{
previous: other,
cause: newDescriptive,
}
err.SetLocation(1)
return err
}
// Wrapf changes the Cause of the error, and adds an annotation. The location
// of the Wrap call is also stored in the error stack.
//
// For example:
// if err := SomeFunc(); err != nil {
// return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
// }
//
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error {
err := &Err{
message: fmt.Sprintf(format, args...),
previous: other,
cause: newDescriptive,
}
err.SetLocation(1)
return err
}
// Mask masks the given error with the given format string and arguments (like
// fmt.Sprintf), returning a new error that maintains the error stack, but
// hides the underlying error type. The error string still contains the full
// annotations. If you want to hide the annotations, call Wrap.
func Maskf(other error, format string, args ...interface{}) error {
if other == nil {
return nil
}
err := &Err{
message: fmt.Sprintf(format, args...),
previous: other,
}
err.SetLocation(1)
return err
}
// Mask hides the underlying error type, and records the location of the masking.
func Mask(other error) error {
if other == nil {
return nil
}
err := &Err{
previous: other,
}
err.SetLocation(1)
return err
}
// Cause returns the cause of the given error. This will be either the
// original error, or the result of a Wrap or Mask call.
//
// Cause is the usual way to diagnose errors that may have been wrapped by
// the other errors functions.
func Cause(err error) error {
var diag error
if err, ok := err.(causer); ok {
diag = err.Cause()
}
if diag != nil {
return diag
}
return err
}
type causer interface {
Cause() error
}
type wrapper interface {
// Message returns the top level error message,
// not including the message from the Previous
// error.
Message() string
// Underlying returns the Previous error, or nil
// if there is none.
Underlying() error
}
type locationer interface {
Location() (string, int)
}
var (
_ wrapper = (*Err)(nil)
_ locationer = (*Err)(nil)
_ causer = (*Err)(nil)
)
// Details returns information about the stack of errors wrapped by err, in
// the format:
//
// [{filename:99: error one} {otherfile:55: cause of error one}]
//
// This is a terse alternative to ErrorStack as it returns a single line.
func Details(err error) string {
if err == nil {
return "[]"
}
var s []byte
s = append(s, '[')
for {
s = append(s, '{')
if err, ok := err.(locationer); ok {
file, line := err.Location()
if file != "" {
s = append(s, fmt.Sprintf("%s:%d", file, line)...)
s = append(s, ": "...)
}
}
if cerr, ok := err.(wrapper); ok {
s = append(s, cerr.Message()...)
err = cerr.Underlying()
} else {
s = append(s, err.Error()...)
err = nil
}
s = append(s, '}')
if err == nil {
break
}
s = append(s, ' ')
}
s = append(s, ']')
return string(s)
}
// ErrorStack returns a string representation of the annotated error. If the
// error passed as the parameter is not an annotated error, the result is
// simply the result of the Error() method on that error.
//
// If the error is an annotated error, a multi-line string is returned where
// each line represents one entry in the annotation stack. The full filename
// from the call stack is used in the output.
//
// first error
// github.com/juju/errors/annotation_test.go:193:
// github.com/juju/errors/annotation_test.go:194: annotation
// github.com/juju/errors/annotation_test.go:195:
// github.com/juju/errors/annotation_test.go:196: more context
// github.com/juju/errors/annotation_test.go:197:
func ErrorStack(err error) string {
return strings.Join(errorStack(err), "\n")
}
func errorStack(err error) []string {
if err == nil {
return nil
}
// We want the first error first
var lines []string
for {
var buff []byte
if err, ok := err.(locationer); ok {
file, line := err.Location()
// Strip off the leading GOPATH/src path elements.
file = trimGoPath(file)
if file != "" {
buff = append(buff, fmt.Sprintf("%s:%d", file, line)...)
buff = append(buff, ": "...)
}
}
if cerr, ok := err.(wrapper); ok {
message := cerr.Message()
buff = append(buff, message...)
// If there is a cause for this error, and it is different to the cause
// of the underlying error, then output the error string in the stack trace.
var cause error
if err1, ok := err.(causer); ok {
cause = err1.Cause()
}
err = cerr.Underlying()
if cause != nil && !sameError(Cause(err), cause) {
if message != "" {
buff = append(buff, ": "...)
}
buff = append(buff, cause.Error()...)
}
} else {
buff = append(buff, err.Error()...)
err = nil
}
lines = append(lines, string(buff))
if err == nil {
break
}
}
// reverse the lines to get the original error, which was at the end of
// the list, back to the start.
var result []string
for i := len(lines); i > 0; i-- {
result = append(result, lines[i-1])
}
return result
}

View File

@ -1,38 +0,0 @@
// Copyright 2013, 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors
import (
"runtime"
"strings"
)
// prefixSize is used internally to trim the user specific path from the
// front of the returned filenames from the runtime call stack.
var prefixSize int
// goPath is the deduced path based on the location of this file as compiled.
var goPath string
func init() {
_, file, _, ok := runtime.Caller(0)
if file == "?" {
return
}
if ok {
// We know that the end of the file should be:
// github.com/juju/errors/path.go
size := len(file)
suffix := len("github.com/juju/errors/path.go")
goPath = file[:size-suffix]
prefixSize = len(goPath)
}
}
func trimGoPath(filename string) string {
if strings.HasPrefix(filename, goPath) {
return filename[prefixSize:]
}
return filename
}

View File

@ -115,6 +115,12 @@ type Message struct {
Snapshot Snapshot // No need for codec
}
func (m *Message) ToString() (mesg string) {
return fmt.Sprintf("Mesg:[%v] type(%v) ForceVote(%v) Reject(%v) RejectIndex(%v) "+
"From(%v) To(%v) Term(%v) LogTrem(%v) Index(%v) Commit(%v)", m.ID, m.Type.String(), m.ForceVote,
m.Reject, m.RejectIndex, m.From, m.To, m.Term, m.LogTerm, m.Index, m.Commit)
}
type ConfChange struct {
Type ConfChangeType
Peer Peer

View File

@ -447,6 +447,7 @@ func (s *raft) reciveMessage(m *proto.Message) {
case <-s.stopc:
case s.recvc <- m:
default:
logger.Warn(fmt.Sprintf("raft[%v] discard message(%v)", s.raftConfig.ID, m.ToString()))
return
}
}
@ -538,12 +539,6 @@ func (s *raft) sendMessage(m *proto.Message) {
func (s *raft) maybeChange(respErr bool) {
updated := false
if s.prevSoftSt.term != s.raftFsm.term && s.raftFsm.leader == s.config.NodeID &&
s.curApplied.Get() < s.raftFsm.raftLog.committed {
logger.Warn("raft:[%v] changed leader wait applied. curApplied %v committed %v at term %d.",
s.raftFsm.id, s.curApplied.Get(), s.raftFsm.raftLog.committed, s.raftFsm.term)
return
}
if s.prevSoftSt.term != s.raftFsm.term {
updated = true
s.prevSoftSt.term = s.raftFsm.term

View File

@ -22,6 +22,7 @@ import (
"github.com/tiglabs/raft/logger"
"github.com/tiglabs/raft/proto"
"time"
)
// NoLeader is a placeholder nodeID used when there is no leader.
@ -131,9 +132,20 @@ func newRaftFsm(config *Config, raftConfig *RaftConfig) (*raftFsm, error) {
logger.Debug("newRaft[%v] [peers: [%s], term: %d, commit: %d, applied: %d, lastindex: %d, lastterm: %d]",
r.id, strings.Join(peerStrs, ","), r.term, r.raftLog.committed, r.raftLog.applied, r.raftLog.lastIndex(), r.raftLog.lastTerm())
}
go r.doRandomSeed()
return r, nil
}
func (r *raftFsm) doRandomSeed() {
ticker := time.Tick(time.Duration(rand.Intn(10)) * time.Second)
for {
select {
case <-ticker:
r.rand.Seed(time.Now().UnixNano())
}
}
}
// raft main method
func (r *raftFsm) Step(m *proto.Message) {
if m.Type == proto.LocalMsgHup {
@ -338,7 +350,10 @@ func (r *raftFsm) reset(term, lasti uint64, isLeader bool) {
}
func (r *raftFsm) resetRandomizedElectionTimeout() {
r.randElectionTick = r.config.ElectionTick + r.rand.Intn(r.config.ElectionTick)
randTick := r.rand.Intn(r.config.ElectionTick)
r.randElectionTick = r.config.ElectionTick + randTick
logger.Debug("raft[%v] random election timeout randElectionTick=%v, config.ElectionTick=%v, randTick=%v", r.id,
r.randElectionTick, r.config.ElectionTick, randTick)
}
func (r *raftFsm) pastElectionTimeout() bool {

View File

@ -29,7 +29,7 @@ func (r *raftFsm) becomeLeader() {
if r.state == stateFollower {
panic(AppPanicError(fmt.Sprintf("[raft->becomeLeader][%v] invalid transition [follower -> leader].", r.id)))
}
r.recoverCommit()
lasti := r.raftLog.lastIndex()
r.step = stepLeader
r.reset(r.term, lasti, true)

View File

@ -18,6 +18,8 @@ import (
"net"
"sync"
//"fmt"
//"github.com/tiglabs/raft/logger"
"github.com/tiglabs/raft/proto"
"github.com/tiglabs/raft/util"
)
@ -96,6 +98,7 @@ func (t *heartbeatTransport) handleConn(conn *util.ConnTimeout) {
if msg, err := reciveMessage(bufRd); err != nil {
return
} else {
//logger.Debug(fmt.Sprintf("Recive %v from (%v)", msg.ToString(), conn.RemoteAddr()))
t.raftServer.reciveMessage(msg)
}
}

View File

@ -219,6 +219,7 @@ func (t *replicateTransport) handleConn(conn *util.ConnTimeout) {
if msg, err := reciveMessage(bufRd); err != nil {
return
} else {
//logger.Debug(fmt.Sprintf("Recive %v from (%v)", msg.ToString(), conn.RemoteAddr()))
if msg.Type == proto.ReqMsgSnapShot {
if err := t.handleSnapshot(msg, conn, bufRd); err != nil {
return

View File

@ -19,6 +19,7 @@ import (
"sync"
"time"
//"fmt"
"github.com/tiglabs/raft/logger"
"github.com/tiglabs/raft/proto"
"github.com/tiglabs/raft/util"
@ -138,6 +139,7 @@ func (s *transportSender) loopSend(recvc chan *proto.Message) {
select {
case msg := <-recvc:
err = msg.Encode(bufWr)
//logger.Debug(fmt.Sprintf("SendMesg %v to (%v) ", msg.ToString(), conn.RemoteAddr()))
proto.ReturnMessage(msg)
if err != nil {
goto flush