[refactor] 重构naza整个项目的命名规则,见 https://github.com/q191201771/lal/issues/87

pull/2/head v0.19.0
q191201771 4 years ago
parent 8b839e3e4f
commit d6ea811e9d

1
.gitignore vendored

@ -5,6 +5,7 @@
/playground
/playground/cc
/demo/camel/camel
/demo/samefile
/demo/time
/demo/temp

@ -0,0 +1,260 @@
// Copyright 2021, Chef. All rights reserved.
// https://github.com/q191201771/naza
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package main
import (
"bytes"
"flag"
"io/ioutil"
"os"
"strings"
"github.com/q191201771/naza/pkg/filebatch"
"github.com/q191201771/naza/pkg/nazalog"
)
// 帮助找出源码中多个大写字母连接在一起的地方
func main() {
_ = nazalog.Init(func(option *nazalog.Option) {
option.Level = nazalog.LevelInfo
//option.LevelFlag = false
option.TimestampWithMsFlag = false
option.TimestampFlag = false
//option.ShortFileFlag = false
})
dir := parseFlag()
// 遍历所有go文件
err := filebatch.Walk(dir, true, ".go", func(path string, info os.FileInfo, content []byte, err error) []byte {
if err != nil {
nazalog.Warnf("read file failed. file=%s, err=%+v", path, err)
return nil
}
nazalog.Tracef("path:%s", path)
//checkModFile(path, content)
//return nil
//免检的文件:
if strings.Contains(path, "/pkg/alpha/stun/") {
return nil
}
// 免检文件:测试文件
if strings.HasSuffix(path, "_test.go") {
return nil
}
lines := bytes.Split(content, []byte{'\n'})
// 免检的行:
ignContainsKeyList := []string{
// 字符串
"\"",
// 16进制的数字
"0x",
// 接口
"IBufWriter",
"IClientSession",
"IServerSession",
"IClientSessionLifecycle",
"IServerSessionLifecycle",
"ISessionStat",
"ISessionUrlContext",
"IObject",
"IPathStrategy",
"IPathRequestStrategy",
"IPathWriteStrategy",
"IQueueObserver",
"IHandshakeClient",
"IRtpUnpacker",
"IRtpUnpackContainer",
"IRtpUnpackerProtocol",
"IInterleavedPacketWriter",
"filesystemlayer.IFileSystemLayer",
"filesystemlayer.IFile",
"IFile",
"IFileSystemLayer",
// RTSP相关
"HeaderCSeq",
"ARtpMap",
"AFmtPBase",
"AControl",
// 标准库
".URL",
".TLS",
".SIGUSR",
"ServeHTTP(",
".URI",
".RequestURI",
"io.EOF",
"net.UDPAddr",
"net.UDPConn",
"net.ResolveUDPAddr",
"net.ListenUDP",
"WriteToUDP",
"ReadFromUDP",
"time.RFC1123",
"runtime.GOOS",
"crc32.ChecksumIEEE",
"cipher.NewCBCEncrypter",
"cipher.NewCBCDecrypter",
"os.O_CREATE",
//
"LAddr",
"RAddr",
}
// 注释
ignPrefixKeyList := []string{
"//",
"/*",
}
// 逐行分析
for j, line := range lines {
// 免检的行:
if j == 3 && strings.Contains(string(line), "MIT-style license") {
continue
}
ignFlag := false
for _, k := range ignContainsKeyList {
if strings.Contains(string(line), k) {
nazalog.Debugf("ign contains line:%s %s", string(line), k)
ignFlag = true
}
}
if ignFlag {
continue
}
for _, k := range ignPrefixKeyList {
if strings.HasPrefix(strings.TrimSpace(string(line)), k) {
nazalog.Debugf("ign prefix line:%s %s", string(line), k)
ignFlag = true
}
}
if ignFlag {
continue
}
for i := range line {
// 连续两个字符是大写字母
if i == 0 {
continue
}
if isCap(line[i]) && isCap(line[i-1]) {
nazalog.Infof("%s:%d %s", path, j+1, string(highlightSerialCap(line)))
break
}
}
}
return nil
})
nazalog.Assert(nil, err)
}
// 是否大写字母
func isCap(c byte) bool {
return c >= 'A' && c <= 'Z'
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
// 有连续大写的地方高亮显示
func highlightSerialCap(line []byte) []byte {
var ret []byte
var cache []byte
for i := range line {
if isCap(line[i]) {
cache = append(cache, line[i])
} else {
if cache != nil {
if len(cache) > 1 {
ret = append(ret, []byte("\033[22;31m")...)
}
ret = append(ret, cache...)
if len(cache) > 1 {
ret = append(ret, []byte("\033[0m")...)
}
cache = nil
}
ret = append(ret, line[i])
}
}
if cache != nil {
if len(cache) > 1 {
ret = append(ret, []byte("\033[22;31m")...)
}
ret = append(ret, cache...)
if len(cache) > 1 {
ret = append(ret, []byte("\033[0m")...)
}
}
return ret
}
// 一段检查文件修改后和修改前的逻辑,修改是否符合预期
func checkModFile(path string, content []byte) {
beforeModPath := "x"
afterModPath := "x"
ignFileList := []string{
"pkg/rtmp/server_session.go",
"pkg/base/websocket.go",
"pkg/rtsp/client_command_session.go",
}
for _, f := range ignFileList {
if strings.HasSuffix(path, f) {
return
}
}
beforeModFilename := strings.ReplaceAll(path, afterModPath, beforeModPath)
beforeModContent, err := ioutil.ReadFile(beforeModFilename)
nazalog.Assert(nil, err)
// 理论上,大部分修改,不影响文件大小
if len(content) != len(beforeModContent) {
nazalog.Errorf("file size not match. path=%s, len(b=%d, a=%d)", path, len(content), len(beforeModContent))
}
notEqualFlag := false
// 不管大小是否相等,取最小值,逐个字节比较内容
// 理论上,大部分修改,要么是相等,要么是将新内容从小写转换回大写就相等
for i := 0; i < min(len(content), len(beforeModContent)); i++ {
if content[i] != beforeModContent[i] && content[i]-32 != beforeModContent[i] {
nazalog.Errorf("-----a-----\n%s\n-----b-----\n%s", string(content[i:i+128]), string(beforeModContent[i:i+128]))
notEqualFlag = true
break
}
}
if notEqualFlag {
nazalog.Errorf("%s", path)
}
}
func parseFlag() string {
dir := flag.String("d", "", "dir of source")
flag.Parse()
if *dir == "" {
flag.Usage()
os.Exit(1)
}
return *dir
}

@ -32,7 +32,7 @@ var tmpSliceByte []byte
var gorutineNum = 1000
var loopNum = 1000
var sleepMSec = time.Duration(10) * time.Millisecond
var sleepMs = time.Duration(10) * time.Millisecond
func size() int {
return random(1, 128*1024)
@ -60,14 +60,14 @@ func originFunc() {
buf := make([]byte, size)
tmpSliceByte = buf
atomic.AddUint32(&doneCount, 1)
time.Sleep(sleepMSec)
time.Sleep(sleepMs)
}
func bufferPoolFunc() {
size := size()
buf := bp.Get(size)
tmpSliceByte = buf
time.Sleep(sleepMSec)
time.Sleep(sleepMs)
bp.Put(buf)
atomic.AddUint32(&doneCount, 1)
}

@ -23,28 +23,28 @@ import (
// ----- 反序列化 -----
func BEUint16(p []byte) uint16 {
func BeUint16(p []byte) uint16 {
return binary.BigEndian.Uint16(p)
}
func BEUint24(p []byte) uint32 {
func BeUint24(p []byte) uint32 {
return uint32(p[2]) | uint32(p[1])<<8 | uint32(p[0])<<16
}
func BEUint32(p []byte) (ret uint32) {
func BeUint32(p []byte) (ret uint32) {
return binary.BigEndian.Uint32(p)
}
func BEUint64(p []byte) (ret uint64) {
func BeUint64(p []byte) (ret uint64) {
return binary.BigEndian.Uint64(p)
}
func BEFloat64(p []byte) (ret float64) {
func BeFloat64(p []byte) (ret float64) {
a := binary.BigEndian.Uint64(p)
return math.Float64frombits(a)
}
func LEUint32(p []byte) (ret uint32) {
func LeUint32(p []byte) (ret uint32) {
return binary.LittleEndian.Uint32(p)
}
@ -76,79 +76,79 @@ func ReadUint8(r io.Reader) (uint8, error) {
return b[0], nil
}
func ReadBEUint16(r io.Reader) (uint16, error) {
func ReadBeUint16(r io.Reader) (uint16, error) {
b, err := ReadBytes(r, 2)
if err != nil {
return 0, err
}
return BEUint16(b), nil
return BeUint16(b), nil
}
func ReadBEUint24(r io.Reader) (uint32, error) {
func ReadBeUint24(r io.Reader) (uint32, error) {
b, err := ReadBytes(r, 3)
if err != nil {
return 0, err
}
return BEUint24(b), nil
return BeUint24(b), nil
}
func ReadBEUint32(r io.Reader) (uint32, error) {
func ReadBeUint32(r io.Reader) (uint32, error) {
b, err := ReadBytes(r, 4)
if err != nil {
return 0, err
}
return BEUint32(b), nil
return BeUint32(b), nil
}
func ReadBEUint64(r io.Reader) (uint64, error) {
func ReadBeUint64(r io.Reader) (uint64, error) {
b, err := ReadBytes(r, 8)
if err != nil {
return 0, err
}
return BEUint64(b), nil
return BeUint64(b), nil
}
func ReadLEUint32(r io.Reader) (uint32, error) {
func ReadLeUint32(r io.Reader) (uint32, error) {
b, err := ReadBytes(r, 4)
if err != nil {
return 0, err
}
return LEUint32(b), nil
return LeUint32(b), nil
}
// ----- 序列化 -----
func BEPutUint16(out []byte, in uint16) {
func BePutUint16(out []byte, in uint16) {
binary.BigEndian.PutUint16(out, in)
}
func BEPutUint24(out []byte, in uint32) {
func BePutUint24(out []byte, in uint32) {
out[0] = byte(in >> 16)
out[1] = byte(in >> 8)
out[2] = byte(in)
}
func BEPutUint32(out []byte, in uint32) {
func BePutUint32(out []byte, in uint32) {
binary.BigEndian.PutUint32(out, in)
}
func BEPutUint64(out []byte, in uint64) {
func BePutUint64(out []byte, in uint64) {
binary.BigEndian.PutUint64(out, in)
}
func LEPutUint32(out []byte, in uint32) {
func LePutUint32(out []byte, in uint32) {
binary.LittleEndian.PutUint32(out, in)
}
func WriteBEUint24(writer io.Writer, in uint32) error {
func WriteBeUint24(writer io.Writer, in uint32) error {
_, err := writer.Write([]byte{uint8(in >> 16), uint8(in >> 8), uint8(in & 0xFF)})
return err
}
func WriteBE(writer io.Writer, in interface{}) error {
func WriteBe(writer io.Writer, in interface{}) error {
return binary.Write(writer, binary.BigEndian, in)
}
func WriteLE(writer io.Writer, in interface{}) error {
func WriteLe(writer io.Writer, in interface{}) error {
return binary.Write(writer, binary.LittleEndian, in)
}

@ -16,7 +16,7 @@ import (
"github.com/q191201771/naza/pkg/assert"
)
func TestBEUint16(t *testing.T) {
func TestBeUint16(t *testing.T) {
vector := []struct {
input []byte
output uint16
@ -30,11 +30,11 @@ func TestBEUint16(t *testing.T) {
}
for i := 0; i < len(vector); i++ {
assert.Equal(t, vector[i].output, BEUint16(vector[i].input))
assert.Equal(t, vector[i].output, BeUint16(vector[i].input))
}
}
func TestBEUint24(t *testing.T) {
func TestBeUint24(t *testing.T) {
vector := []struct {
input []byte
output uint32
@ -47,11 +47,11 @@ func TestBEUint24(t *testing.T) {
}
for i := 0; i < len(vector); i++ {
assert.Equal(t, vector[i].output, BEUint24(vector[i].input))
assert.Equal(t, vector[i].output, BeUint24(vector[i].input))
}
}
func TestBEUint32(t *testing.T) {
func TestBeUint32(t *testing.T) {
vector := []struct {
input []byte
output uint32
@ -64,11 +64,11 @@ func TestBEUint32(t *testing.T) {
}
for i := 0; i < len(vector); i++ {
assert.Equal(t, vector[i].output, BEUint32(vector[i].input))
assert.Equal(t, vector[i].output, BeUint32(vector[i].input))
}
}
func TestBEUint64(t *testing.T) {
func TestBeUint64(t *testing.T) {
vector := []struct {
input []byte
output uint64
@ -80,11 +80,11 @@ func TestBEUint64(t *testing.T) {
}
for i := 0; i < len(vector); i++ {
assert.Equal(t, vector[i].output, BEUint64(vector[i].input))
assert.Equal(t, vector[i].output, BeUint64(vector[i].input))
}
}
func TestBEFloat64(t *testing.T) {
func TestBeFloat64(t *testing.T) {
vector := []int{
1,
0xFF,
@ -95,11 +95,11 @@ func TestBEFloat64(t *testing.T) {
b := &bytes.Buffer{}
err := binary.Write(b, binary.BigEndian, float64(vector[i]))
assert.Equal(t, nil, err)
assert.Equal(t, vector[i], int(BEFloat64(b.Bytes())))
assert.Equal(t, vector[i], int(BeFloat64(b.Bytes())))
}
}
func TestLEUint32(t *testing.T) {
func TestLeUint32(t *testing.T) {
vector := []struct {
input []byte
output uint32
@ -112,23 +112,23 @@ func TestLEUint32(t *testing.T) {
}
for i := 0; i < len(vector); i++ {
assert.Equal(t, vector[i].output, LEUint32(vector[i].input))
assert.Equal(t, vector[i].output, LeUint32(vector[i].input))
}
}
func TestBEPutUint16(t *testing.T) {
func TestBePutUint16(t *testing.T) {
b := make([]byte, 2)
BEPutUint16(b, 1)
BePutUint16(b, 1)
assert.Equal(t, []byte{0, 1}, b)
}
func TestBEPutUint64(t *testing.T) {
func TestBePutUint64(t *testing.T) {
b := make([]byte, 8)
BEPutUint64(b, 1)
BePutUint64(b, 1)
assert.Equal(t, []byte{0, 0, 0, 0, 0, 0, 0, 1}, b)
}
func TestBEPutUint24(t *testing.T) {
func TestBePutUint24(t *testing.T) {
vector := []struct {
input uint32
output []byte
@ -142,12 +142,12 @@ func TestBEPutUint24(t *testing.T) {
out := make([]byte, 3)
for i := 0; i < len(vector); i++ {
BEPutUint24(out, vector[i].input)
BePutUint24(out, vector[i].input)
assert.Equal(t, vector[i].output, out)
}
}
func TestBEPutUint32(t *testing.T) {
func TestBePutUint32(t *testing.T) {
vector := []struct {
input uint32
output []byte
@ -161,12 +161,12 @@ func TestBEPutUint32(t *testing.T) {
out := make([]byte, 4)
for i := 0; i < len(vector); i++ {
BEPutUint32(out, vector[i].input)
BePutUint32(out, vector[i].input)
assert.Equal(t, vector[i].output, out)
}
}
func TestLEPutUint32(t *testing.T) {
func TestLePutUint32(t *testing.T) {
vector := []struct {
input uint32
output []byte
@ -180,12 +180,12 @@ func TestLEPutUint32(t *testing.T) {
out := make([]byte, 4)
for i := 0; i < len(vector); i++ {
LEPutUint32(out, vector[i].input)
LePutUint32(out, vector[i].input)
assert.Equal(t, vector[i].output, out)
}
}
func TestWriteBEUint24(t *testing.T) {
func TestWriteBeUint24(t *testing.T) {
vector := []struct {
input uint32
output []byte
@ -199,13 +199,13 @@ func TestWriteBEUint24(t *testing.T) {
for i := 0; i < len(vector); i++ {
out := &bytes.Buffer{}
err := WriteBEUint24(out, vector[i].input)
err := WriteBeUint24(out, vector[i].input)
assert.Equal(t, nil, err)
assert.Equal(t, vector[i].output, out.Bytes())
}
}
func TestWriteBE(t *testing.T) {
func TestWriteBe(t *testing.T) {
vector := []struct {
input interface{}
output []byte
@ -215,13 +215,13 @@ func TestWriteBE(t *testing.T) {
}
for i := 0; i < len(vector); i++ {
out := &bytes.Buffer{}
err := WriteBE(out, vector[i].input)
err := WriteBe(out, vector[i].input)
assert.Equal(t, nil, err)
assert.Equal(t, vector[i].output, out.Bytes())
}
}
func TestWriteLE(t *testing.T) {
func TestWriteLe(t *testing.T) {
vector := []struct {
input interface{}
output []byte
@ -231,7 +231,7 @@ func TestWriteLE(t *testing.T) {
}
for i := 0; i < len(vector); i++ {
out := &bytes.Buffer{}
err := WriteLE(out, vector[i].input)
err := WriteLe(out, vector[i].input)
assert.Equal(t, nil, err)
assert.Equal(t, vector[i].output, out.Bytes())
}
@ -256,15 +256,15 @@ func TestRead(t *testing.T) {
b := &bytes.Buffer{}
_, err = ReadUint8(b)
assert.IsNotNil(t, err)
_, err = ReadBEUint16(b)
_, err = ReadBeUint16(b)
assert.IsNotNil(t, err)
_, err = ReadBEUint24(b)
_, err = ReadBeUint24(b)
assert.IsNotNil(t, err)
_, err = ReadBEUint32(b)
_, err = ReadBeUint32(b)
assert.IsNotNil(t, err)
_, err = ReadBEUint64(b)
_, err = ReadBeUint64(b)
assert.IsNotNil(t, err)
_, err = ReadLEUint32(b)
_, err = ReadLeUint32(b)
assert.IsNotNil(t, err)
b.Write([]byte{1})
@ -272,24 +272,24 @@ func TestRead(t *testing.T) {
assert.Equal(t, uint8(1), i8)
assert.Equal(t, nil, err)
b.Write([]byte{1, 2})
i16, err := ReadBEUint16(b)
assert.Equal(t, BEUint16([]byte{1, 2}), i16)
i16, err := ReadBeUint16(b)
assert.Equal(t, BeUint16([]byte{1, 2}), i16)
assert.Equal(t, nil, err)
b.Write([]byte{1, 2, 3})
i24, err := ReadBEUint24(b)
assert.Equal(t, BEUint24([]byte{1, 2, 3}), i24)
i24, err := ReadBeUint24(b)
assert.Equal(t, BeUint24([]byte{1, 2, 3}), i24)
assert.Equal(t, nil, err)
b.Write([]byte{1, 2, 3, 4})
i32, err := ReadBEUint32(b)
assert.Equal(t, BEUint32([]byte{1, 2, 3, 4}), i32)
i32, err := ReadBeUint32(b)
assert.Equal(t, BeUint32([]byte{1, 2, 3, 4}), i32)
assert.Equal(t, nil, err)
b.Write([]byte{1, 2, 3, 4, 5, 6, 7, 8})
i64, err := ReadBEUint64(b)
assert.Equal(t, BEUint64([]byte{1, 2, 3, 4, 5, 6, 7, 8}), i64)
i64, err := ReadBeUint64(b)
assert.Equal(t, BeUint64([]byte{1, 2, 3, 4, 5, 6, 7, 8}), i64)
assert.Equal(t, nil, err)
b.Write([]byte{1, 0, 0, 0})
i32, err = ReadLEUint32(b)
i32, err = ReadLeUint32(b)
assert.Equal(t, uint32(1), i32)
assert.Equal(t, nil, err)
}
@ -301,32 +301,32 @@ func TestReadString(t *testing.T) {
assert.IsNotNil(t, err)
}
func BenchmarkBEFloat64(b *testing.B) {
func BenchmarkBeFloat64(b *testing.B) {
buf := &bytes.Buffer{}
_ = binary.Write(buf, binary.BigEndian, float64(123.4))
for i := 0; i < b.N; i++ {
BEFloat64(buf.Bytes())
BeFloat64(buf.Bytes())
}
}
func BenchmarkBEPutUint24(b *testing.B) {
func BenchmarkBePutUint24(b *testing.B) {
out := make([]byte, 3)
for i := 0; i < b.N; i++ {
BEPutUint24(out, uint32(i))
BePutUint24(out, uint32(i))
}
}
func BenchmarkBEUint24(b *testing.B) {
func BenchmarkBeUint24(b *testing.B) {
buf := []byte{1, 2, 3}
for i := 0; i < b.N; i++ {
BEUint24(buf)
BeUint24(buf)
}
}
func BenchmarkWriteBE(b *testing.B) {
func BenchmarkWriteBe(b *testing.B) {
out := &bytes.Buffer{}
in := uint64(123)
for i := 0; i < b.N; i++ {
_ = WriteBE(out, in)
_ = WriteBe(out, in)
}
}

@ -14,10 +14,10 @@ import (
)
type Bitrate interface {
// @param nowUnixMSec: 变参,可选择从外部传入当前 unix 时间戳,单位毫秒
Add(bytes int, nowUnixMSec ...int64)
// @param nowUnixMs: 变参,可选择从外部传入当前 unix 时间戳,单位毫秒
Add(bytes int, nowUnixMs ...int64)
Rate(nowUnixMSec ...int64) float32
Rate(nowUnixMs ...int64) float32
}
type Unit uint8
@ -25,19 +25,19 @@ type Unit uint8
const (
UnitBitPerSec Unit = iota + 1
UnitBytePerSec
UnitKBitPerSec
UnitKBytePerSec
UnitKbitPerSec
UnitKbytePerSec
)
// TODO chef: 考虑支持配置是否在内部使用锁
type Option struct {
WindowMS int
WindowMs int
Unit Unit
}
var defaultOption = Option{
WindowMS: 1000,
Unit: UnitKBitPerSec,
WindowMs: 1000,
Unit: UnitKbitPerSec,
}
type ModOption func(option *Option)
@ -64,12 +64,12 @@ type bucket struct {
t int64 // unix 时间戳,单位毫秒
}
func (b *bitrate) Add(bytes int, nowUnixMSec ...int64) {
func (b *bitrate) Add(bytes int, nowUnixMs ...int64) {
var now int64
if len(nowUnixMSec) == 0 {
if len(nowUnixMs) == 0 {
now = time.Now().UnixNano() / 1e6
} else {
now = nowUnixMSec[0]
now = nowUnixMs[0]
}
b.mu.Lock()
@ -82,12 +82,12 @@ func (b *bitrate) Add(bytes int, nowUnixMSec ...int64) {
})
}
func (b *bitrate) Rate(nowUnixMSec ...int64) float32 {
func (b *bitrate) Rate(nowUnixMs ...int64) float32 {
var now int64
if len(nowUnixMSec) == 0 {
if len(nowUnixMs) == 0 {
now = time.Now().UnixNano() / 1e6
} else {
now = nowUnixMSec[0]
now = nowUnixMs[0]
}
b.mu.Lock()
@ -102,13 +102,13 @@ func (b *bitrate) Rate(nowUnixMSec ...int64) float32 {
var ret float32
switch b.option.Unit {
case UnitBitPerSec:
ret = float32(total*8*1000) / float32(b.option.WindowMS)
ret = float32(total*8*1000) / float32(b.option.WindowMs)
case UnitBytePerSec:
ret = float32(total*1000) / float32(b.option.WindowMS)
case UnitKBitPerSec:
ret = float32(total*8) / float32(b.option.WindowMS)
case UnitKBytePerSec:
ret = float32(total) / float32(b.option.WindowMS)
ret = float32(total*1000) / float32(b.option.WindowMs)
case UnitKbitPerSec:
ret = float32(total*8) / float32(b.option.WindowMs)
case UnitKbytePerSec:
ret = float32(total) / float32(b.option.WindowMs)
}
return ret
}
@ -117,7 +117,7 @@ func (b *bitrate) sweepStale(now int64) {
i := 0
l := len(b.bucketSlice)
for ; i < l; i++ {
if now-b.bucketSlice[i].t <= int64(b.option.WindowMS) {
if now-b.bucketSlice[i].t <= int64(b.option.WindowMs) {
break
}
}

@ -19,7 +19,7 @@ import (
func TestBitrate(t *testing.T) {
var b bitrate.Bitrate
b = bitrate.New(func(option *bitrate.Option) {
option.WindowMS = 10
option.WindowMs = 10
})
b.Add(1000)
r := b.Rate()
@ -32,12 +32,12 @@ func TestUnit(t *testing.T) {
golden := map[bitrate.Unit]float32{
bitrate.UnitBitPerSec: 800 * 1000,
bitrate.UnitBytePerSec: 100 * 1000,
bitrate.UnitKBitPerSec: 800,
bitrate.UnitKBytePerSec: 100,
bitrate.UnitKbitPerSec: 800,
bitrate.UnitKbytePerSec: 100,
}
for k, v := range golden {
b := bitrate.New(func(option *bitrate.Option) {
option.WindowMS = 10
option.WindowMs = 10
option.Unit = k
})
b.Add(1000)
@ -49,7 +49,7 @@ func TestUnit(t *testing.T) {
func TestOutsizeNow(t *testing.T) {
var b bitrate.Bitrate
b = bitrate.New(func(option *bitrate.Option) {
option.WindowMS = 10
option.WindowMs = 10
})
now := time.Now().UnixNano() / 1e6
b.Add(1000, now)

@ -64,8 +64,8 @@ type Connection interface {
// Mod类型函数不加锁需要调用方保证不发生竞态调用
ModWriteChanSize(n int)
ModWriteBufSize(n int)
ModReadTimeoutMS(n int)
ModWriteTimeoutMS(n int)
ModReadTimeoutMs(n int)
ModWriteTimeoutMs(n int)
// 连接上读取和发送的字节总数。
// 注意如果是异步发送发送字节统计的是调用底层write的值而非上层调用Connection发送的值
@ -96,8 +96,8 @@ type Option struct {
WriteBufSize int
// 如果不为0则之后每次读/写都带超时
ReadTimeoutMS int
WriteTimeoutMS int
ReadTimeoutMs int
WriteTimeoutMs int
// 如果不为0则写使用channel将数据发送到后台协程中发送
WriteChanSize int
@ -112,8 +112,8 @@ type Option struct {
var defaultOption = Option{
ReadBufSize: 0,
WriteBufSize: 0,
ReadTimeoutMS: 0,
WriteTimeoutMS: 0,
ReadTimeoutMs: 0,
WriteTimeoutMs: 0,
WriteChanSize: 0,
WriteChanFullBehavior: WriteChanFullBehaviorReturnError,
}
@ -155,16 +155,16 @@ func New(conn net.Conn, modOptions ...ModOption) Connection {
return c
}
type wMsgT int
type wMsgType int
const (
_ wMsgT = iota
wMsgTWrite
wMsgTFlush
_ wMsgType = iota
wMsgTypeWrite
wMsgTypeFlush
)
type wMsg struct {
t wMsgT
t wMsgType
b []byte
}
@ -206,23 +206,23 @@ func (c *connection) ModWriteBufSize(n int) {
c.w = bufio.NewWriterSize(c.Conn, n)
}
func (c *connection) ModReadTimeoutMS(n int) {
if c.option.ReadTimeoutMS > 0 {
func (c *connection) ModReadTimeoutMs(n int) {
if c.option.ReadTimeoutMs > 0 {
panic(ErrConnectionPanic)
}
c.option.ReadTimeoutMS = n
c.option.ReadTimeoutMs = n
}
func (c *connection) ModWriteTimeoutMS(n int) {
if c.option.WriteTimeoutMS > 0 {
func (c *connection) ModWriteTimeoutMs(n int) {
if c.option.WriteTimeoutMs > 0 {
panic(ErrConnectionPanic)
}
c.option.WriteTimeoutMS = n
c.option.WriteTimeoutMs = n
}
func (c *connection) ReadAtLeast(buf []byte, min int) (n int, err error) {
if c.option.ReadTimeoutMS > 0 {
err = c.SetReadDeadline(time.Now().Add(time.Duration(c.option.ReadTimeoutMS) * time.Millisecond))
if c.option.ReadTimeoutMs > 0 {
err = c.SetReadDeadline(time.Now().Add(time.Duration(c.option.ReadTimeoutMs) * time.Millisecond))
if err != nil {
c.close(err)
return 0, err
@ -243,8 +243,8 @@ func (c *connection) ReadLine() (line []byte, isPrefix bool, err error) {
// 目前只有使用了 bufio.Reader 时才能执行 ReadLine 操作
panic(ErrConnectionPanic)
}
if c.option.ReadTimeoutMS > 0 {
err = c.SetReadDeadline(time.Now().Add(time.Duration(c.option.ReadTimeoutMS) * time.Millisecond))
if c.option.ReadTimeoutMs > 0 {
err = c.SetReadDeadline(time.Now().Add(time.Duration(c.option.ReadTimeoutMs) * time.Millisecond))
if err != nil {
c.close(err)
return nil, false, err
@ -259,8 +259,8 @@ func (c *connection) ReadLine() (line []byte, isPrefix bool, err error) {
}
func (c *connection) Read(b []byte) (n int, err error) {
if c.option.ReadTimeoutMS > 0 {
err = c.SetReadDeadline(time.Now().Add(time.Duration(c.option.ReadTimeoutMS) * time.Millisecond))
if c.option.ReadTimeoutMs > 0 {
err = c.SetReadDeadline(time.Now().Add(time.Duration(c.option.ReadTimeoutMs) * time.Millisecond))
if err != nil {
c.close(err)
return 0, err
@ -281,11 +281,11 @@ func (c *connection) Write(b []byte) (n int, err error) {
if c.option.WriteChanSize > 0 {
switch c.option.WriteChanFullBehavior {
case WriteChanFullBehaviorBlock:
c.wChan <- wMsg{t: wMsgTWrite, b: b}
c.wChan <- wMsg{t: wMsgTypeWrite, b: b}
return len(b), nil
case WriteChanFullBehaviorReturnError:
select {
case c.wChan <- wMsg{t: wMsgTWrite, b: b}:
case c.wChan <- wMsg{t: wMsgTypeWrite, b: b}:
return len(b), nil
default:
return 0, ErrWriteChanFull
@ -300,7 +300,7 @@ func (c *connection) Flush() error {
return ErrClosedAlready
}
if c.option.WriteChanSize > 0 {
c.wChan <- wMsg{t: wMsgTFlush}
c.wChan <- wMsg{t: wMsgTypeFlush}
<-c.flushDoneChan
return nil
}
@ -357,8 +357,8 @@ func (c *connection) GetStat() (s Stat) {
}
func (c *connection) write(b []byte) (n int, err error) {
if c.option.WriteTimeoutMS > 0 {
err = c.SetWriteDeadline(time.Now().Add(time.Duration(c.option.WriteTimeoutMS) * time.Millisecond))
if c.option.WriteTimeoutMs > 0 {
err = c.SetWriteDeadline(time.Now().Add(time.Duration(c.option.WriteTimeoutMs) * time.Millisecond))
if err != nil {
c.close(err)
return 0, err
@ -380,11 +380,11 @@ func (c *connection) runWriteLoop() {
return
case msg := <-c.wChan:
switch msg.t {
case wMsgTWrite:
case wMsgTypeWrite:
if _, err := c.write(msg.b); err != nil {
return
}
case wMsgTFlush:
case wMsgTypeFlush:
if err := c.flush(); err != nil {
c.flushDoneChan <- struct{}{}
return
@ -398,8 +398,8 @@ func (c *connection) runWriteLoop() {
func (c *connection) flush() error {
w, ok := c.w.(*bufio.Writer)
if ok {
if c.option.WriteTimeoutMS > 0 {
err := c.SetWriteDeadline(time.Now().Add(time.Duration(c.option.WriteTimeoutMS) * time.Millisecond))
if c.option.WriteTimeoutMs > 0 {
err := c.SetWriteDeadline(time.Now().Add(time.Duration(c.option.WriteTimeoutMs) * time.Millisecond))
if err != nil {
c.close(err)
return err

@ -37,7 +37,7 @@ func TestWriteTimeout(t *testing.T) {
}()
conn, err := net.Dial("tcp", ":10027")
c := connection.New(conn, func(opt *connection.Option) {
opt.WriteTimeoutMS = 1000
opt.WriteTimeoutMs = 1000
})
assert.Equal(t, nil, err)
b := make([]byte, 128*1024)
@ -64,7 +64,7 @@ func TestWrite(t *testing.T) {
srvConn := connection.New(c, func(option *connection.Option) {
option.WriteChanSize = 1024
//option.WriteBufSize = 256
option.WriteTimeoutMS = 10000
option.WriteTimeoutMs = 10000
})
assert.Equal(t, nil, err)
for i := 0; i < 10; i++ {

@ -13,12 +13,12 @@ import (
"crypto/cipher"
)
var CommonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
var CommonIv = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
// @param key 16字节 -> AES128
// 24字节 -> AES192
// 32字节 -> AES256
func EncryptAESWithCBC(in []byte, key []byte, iv []byte) ([]byte, error) {
func EncryptAesWithCbc(in []byte, key []byte, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
@ -30,7 +30,7 @@ func EncryptAESWithCBC(in []byte, key []byte, iv []byte) ([]byte, error) {
return out, nil
}
func DecryptAESWithCBC(in []byte, key []byte, iv []byte) ([]byte, error) {
func DecryptAesWithCbc(in []byte, key []byte, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err

@ -41,7 +41,7 @@ var commonKey256 = []byte{
//var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
var cbcAESTests = []struct {
var cbcAesTests = []struct {
key []byte
in []byte
out []byte
@ -79,12 +79,12 @@ var cbcAESTests = []struct {
},
}
func TestAESWithCBC(t *testing.T) {
for _, item := range cbcAESTests {
enbuf, err := EncryptAESWithCBC(item.in, item.key, CommonIV)
func TestAesWithCbc(t *testing.T) {
for _, item := range cbcAesTests {
enbuf, err := EncryptAesWithCbc(item.in, item.key, CommonIv)
assert.Equal(t, nil, err)
assert.Equal(t, item.out, enbuf)
debuf, err := DecryptAESWithCBC(enbuf, item.key, CommonIV)
debuf, err := DecryptAesWithCbc(enbuf, item.key, CommonIv)
assert.Equal(t, nil, err)
assert.Equal(t, item.in, debuf)
}
@ -96,14 +96,14 @@ func TestCase1(t *testing.T) {
goldEn := "36d062398c390623e1b6c8a24c3bd48b"
key := commonKey192
iv := CommonIV
iv := CommonIv
// -----encrypt-----
// PKCS7填充
paddingOrig := EncryptPKCS7([]byte(goldenOrig), aes.BlockSize)
// Pkcs7填充
paddingOrig := EncryptPkcs7([]byte(goldenOrig), aes.BlockSize)
assert.Equal(t, goldenPaddingOrig, paddingOrig)
// AES加密
enbuf, err := EncryptAESWithCBC(paddingOrig, key, iv)
enbuf, err := EncryptAesWithCbc(paddingOrig, key, iv)
assert.Equal(t, nil, err)
// 转hex进制
en := hex.EncodeToString(enbuf)
@ -115,11 +115,11 @@ func TestCase1(t *testing.T) {
assert.Equal(t, nil, err)
assert.Equal(t, enbuf, enbuf2)
// AES解密
paddingDebuf, err := DecryptAESWithCBC(enbuf2, key, iv)
paddingDebuf, err := DecryptAesWithCbc(enbuf2, key, iv)
assert.Equal(t, nil, err)
assert.Equal(t, goldenPaddingOrig, paddingDebuf)
// 去除PKCS7填充
debuf, err := DecryptPKCS7(paddingDebuf)
// 去除Pkcs7填充
debuf, err := DecryptPkcs7(paddingDebuf)
assert.Equal(t, []byte(goldenOrig), debuf)
assert.Equal(t, nil, err)
}

@ -13,32 +13,32 @@ import (
"errors"
)
var ErrPKCS = errors.New("naza.crypto: fxxk")
var ErrPkcs = errors.New("naza.crypto: fxxk")
// @param blockSize 取值范围[0, 255]
// 如果是AES见标准库中aes.BlockSize等于16
func EncryptPKCS7(in []byte, blockSize int) []byte {
func EncryptPkcs7(in []byte, blockSize int) []byte {
paddingLength := blockSize - len(in)%blockSize
paddingBuf := bytes.Repeat([]byte{byte(paddingLength)}, paddingLength)
return append(in, paddingBuf...)
}
func DecryptPKCS7(in []byte) ([]byte, error) {
func DecryptPkcs7(in []byte) ([]byte, error) {
totalLength := len(in)
if totalLength < 1 {
return nil, ErrPKCS
return nil, ErrPkcs
}
paddingLength := int(in[totalLength-1])
if totalLength < paddingLength {
return nil, ErrPKCS
return nil, ErrPkcs
}
return in[:totalLength-int(paddingLength)], nil
}
func EncryptPKCS5(in []byte) []byte {
return EncryptPKCS7(in, 8)
func EncryptPkcs5(in []byte) []byte {
return EncryptPkcs7(in, 8)
}
func DecryptPKCS5(in []byte) ([]byte, error) {
return DecryptPKCS7(in)
func DecryptPkcs5(in []byte) ([]byte, error) {
return DecryptPkcs7(in)
}

@ -67,38 +67,38 @@ var (
}
)
func TestPKCS7(t *testing.T) {
func TestPkcs7(t *testing.T) {
for i := 0; i < len(goldenOrig)+1; i++ {
orig := []byte(goldenOrig[:i])
//nazalog.Info(hex.Dump(orig))
enbuf := EncryptPKCS7(orig, 16)
enbuf := EncryptPkcs7(orig, 16)
//nazalog.Info(hex.Dump(enbuf))
assert.Equal(t, goldenEnSlice7[i], enbuf)
debuf, err := DecryptPKCS7(enbuf)
debuf, err := DecryptPkcs7(enbuf)
//nazalog.Info(hex.Dump(debuf))
assert.Equal(t, nil, err)
assert.Equal(t, orig, debuf)
}
// corner case
_, err := DecryptPKCS7(nil)
assert.Equal(t, ErrPKCS, err)
_, err = DecryptPKCS7([]byte{16})
assert.Equal(t, ErrPKCS, err)
_, err := DecryptPkcs7(nil)
assert.Equal(t, ErrPkcs, err)
_, err = DecryptPkcs7([]byte{16})
assert.Equal(t, ErrPkcs, err)
}
func TestPKCS5(t *testing.T) {
func TestPkcs5(t *testing.T) {
for i := 0; i < len(goldenOrig)+1; i++ {
orig := []byte(goldenOrig[:i])
//nazalog.Info(hex.Dump(orig))
enbuf := EncryptPKCS5(orig)
enbuf := EncryptPkcs5(orig)
//nazalog.Info(hex.Dump(enbuf))
assert.Equal(t, goldenEnSlice5[i], enbuf)
debuf, err := DecryptPKCS5(enbuf)
debuf, err := DecryptPkcs5(enbuf)
//nazalog.Info(hex.Dump(debuf))
assert.Equal(t, nil, err)
assert.Equal(t, orig, debuf)

@ -13,9 +13,9 @@ import "time"
type deferTaskThread struct {
}
func (d *deferTaskThread) Go(deferMS int, task TaskFn, param ...interface{}) {
func (d *deferTaskThread) Go(deferMs int, task TaskFn, param ...interface{}) {
go func() {
time.Sleep(time.Duration(deferMS) * time.Millisecond)
time.Sleep(time.Duration(deferMs) * time.Millisecond)
task(param...)
}()
}

@ -10,8 +10,8 @@ package defertaskthread
var thread DeferTaskThread
func Go(deferMS int, task TaskFn, param ...interface{}) {
thread.Go(deferMS, task, param...)
func Go(deferMs int, task TaskFn, param ...interface{}) {
thread.Go(deferMs, task, param...)
}
func init() {

@ -13,7 +13,7 @@ type TaskFn func(param ...interface{})
type DeferTaskThread interface {
// 注意一个thread的多个task本应该是串行执行的语义
// 目前为了简单,让它们并行执行了,以后可能会发生变化
Go(deferMS int, task TaskFn, param ...interface{})
Go(deferMs int, task TaskFn, param ...interface{})
}
func NewDeferTaskThread() DeferTaskThread {

@ -20,11 +20,11 @@ type ExitResult struct {
var exitResult ExitResult
// 正常情况下,调用 os.Exit单元测试时可通过调用 WithFakeExit 配置为不调用 os.Exit
func OS_Exit(code int) {
func Os_Exit(code int) {
exit(code)
}
func WithFakeOSExit(fn func()) ExitResult {
func WithFakeOsExit(fn func()) ExitResult {
startFakeExit()
fn()
stopFakeExit()

@ -17,18 +17,18 @@ import (
func TestWithFakeExit(t *testing.T) {
var er fake.ExitResult
er = fake.WithFakeOSExit(func() {
fake.OS_Exit(1)
er = fake.WithFakeOsExit(func() {
fake.Os_Exit(1)
})
assert.Equal(t, true, er.HasExit)
assert.Equal(t, 1, er.ExitCode)
er = fake.WithFakeOSExit(func() {
er = fake.WithFakeOsExit(func() {
})
assert.Equal(t, false, er.HasExit)
er = fake.WithFakeOSExit(func() {
fake.OS_Exit(2)
er = fake.WithFakeOsExit(func() {
fake.Os_Exit(2)
})
assert.Equal(t, true, er.HasExit)
assert.Equal(t, 2, er.ExitCode)

@ -13,37 +13,37 @@ import (
"os"
)
type FSLDisk struct {
type FslDisk struct {
}
func (f *FSLDisk) Type() FSLType {
return FSLTypeDisk
func (f *FslDisk) Type() FslType {
return FslTypeDisk
}
func (f *FSLDisk) Create(name string) (IFile, error) {
func (f *FslDisk) Create(name string) (IFile, error) {
return os.Create(name)
}
func (f *FSLDisk) Rename(oldpath string, newpath string) error {
func (f *FslDisk) Rename(oldpath string, newpath string) error {
return os.Rename(oldpath, newpath)
}
func (f *FSLDisk) MkdirAll(path string, perm uint32) error {
func (f *FslDisk) MkdirAll(path string, perm uint32) error {
return os.MkdirAll(path, os.FileMode(perm))
}
func (f *FSLDisk) Remove(name string) error {
func (f *FslDisk) Remove(name string) error {
return os.Remove(name)
}
func (f *FSLDisk) RemoveAll(path string) error {
func (f *FslDisk) RemoveAll(path string) error {
return os.RemoveAll(path)
}
func (f *FSLDisk) ReadFile(filename string) ([]byte, error) {
func (f *FslDisk) ReadFile(filename string) ([]byte, error) {
return ioutil.ReadFile(filename)
}
func (f *FSLDisk) WriteFile(filename string, data []byte, perm uint32) error {
func (f *FslDisk) WriteFile(filename string, data []byte, perm uint32) error {
return ioutil.WriteFile(filename, data, os.FileMode(perm))
}

@ -10,8 +10,8 @@ package filesystemlayer
import "os"
var _ IFileSystemLayer = &FSLDisk{}
var _ IFileSystemLayer = &FSLMemory{}
var _ IFileSystemLayer = &FslDisk{}
var _ IFileSystemLayer = &FslMemory{}
var _ IFile = &os.File{}
var _ IFile = &file{}

@ -21,7 +21,7 @@ import (
)
func TestCase1(t *testing.T) {
fslCtx := filesystemlayer.FSLFactory(filesystemlayer.FSLTypeMemory)
fslCtx := filesystemlayer.FslFactory(filesystemlayer.FslTypeMemory)
var wg sync.WaitGroup
wg.Add(16)

@ -10,11 +10,11 @@ package filesystemlayer
//var global IFileSystemLayer
//
//func Config(t FSLType) {
// global = FSLFactory(t)
//func Config(t FslType) {
// global = FslFactory(t)
//}
//
//func Type() FSLType {
//func Type() FslType {
// return global.Type()
//}
//
@ -46,5 +46,5 @@ package filesystemlayer
//}
//
//func init() {
// global = FSLFactory(FSLTypeDisk)
// global = FslFactory(FslTypeDisk)
//}

@ -11,8 +11,13 @@ package filesystemlayer
// 注意这个package并没有完整实现所有的文件操作使用内存作为存储时存在一些限制
// 目前只是服务于我另一个项目中的特定场景 https://github.com/q191201771/lal
var (
DefaultDiskFileSystemLayer IFileSystemLayer
DefaultMemoryFileSystemLayer IFileSystemLayer
)
type IFileSystemLayer interface {
Type() FSLType
Type() FslType
// 创建文件
// 原始语义:如果文件已经存在,原文件内容被清空
@ -32,19 +37,24 @@ type IFile interface {
Close() error
}
type FSLType int
type FslType int
const (
FSLTypeDisk FSLType = 1
FSLTypeMemory = 2
FslTypeDisk FslType = 1
FslTypeMemory = 2
)
func FSLFactory(t FSLType) IFileSystemLayer {
func FslFactory(t FslType) IFileSystemLayer {
switch t {
case FSLTypeDisk:
return &FSLDisk{}
case FSLTypeMemory:
return NewFSLMemory()
case FslTypeDisk:
return &FslDisk{}
case FslTypeMemory:
return NewFslMemory()
}
return nil
}
func init() {
DefaultDiskFileSystemLayer = FslFactory(FslTypeDisk)
DefaultMemoryFileSystemLayer = FslFactory(FslTypeMemory)
}

@ -18,7 +18,7 @@ import (
var ErrNotFound = errors.New("naza filesystemlayer: not found")
type FSLMemory struct {
type FslMemory struct {
mu sync.Mutex
files map[string]*file // key filename
}
@ -27,21 +27,21 @@ type file struct {
buf []byte
}
func NewFSLMemory() *FSLMemory {
return &FSLMemory{
func NewFslMemory() *FslMemory {
return &FslMemory{
files: make(map[string]*file),
}
}
func (f *FSLMemory) Type() FSLType {
return FSLTypeMemory
func (f *FslMemory) Type() FslType {
return FslTypeMemory
}
func (f *FSLMemory) Create(name string) (IFile, error) {
func (f *FslMemory) Create(name string) (IFile, error) {
return f.openFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
}
func (f *FSLMemory) Rename(oldpath string, newpath string) error {
func (f *FslMemory) Rename(oldpath string, newpath string) error {
f.mu.Lock()
defer f.mu.Unlock()
fi, exist := f.files[oldpath]
@ -53,11 +53,11 @@ func (f *FSLMemory) Rename(oldpath string, newpath string) error {
return nil
}
func (f *FSLMemory) MkdirAll(path string, perm uint32) error {
func (f *FslMemory) MkdirAll(path string, perm uint32) error {
return nil
}
func (f *FSLMemory) Remove(name string) error {
func (f *FslMemory) Remove(name string) error {
f.mu.Lock()
defer f.mu.Unlock()
_, exist := f.files[name]
@ -68,7 +68,7 @@ func (f *FSLMemory) Remove(name string) error {
return nil
}
func (f *FSLMemory) RemoveAll(path string) error {
func (f *FslMemory) RemoveAll(path string) error {
if !os.IsPathSeparator(path[len(path)-1]) {
path = fmt.Sprintf("%s%c", path, os.PathSeparator)
}
@ -85,7 +85,7 @@ func (f *FSLMemory) RemoveAll(path string) error {
return nil
}
func (f *FSLMemory) ReadFile(filename string) ([]byte, error) {
func (f *FslMemory) ReadFile(filename string) ([]byte, error) {
f.mu.Lock()
defer f.mu.Unlock()
fi, exist := f.files[filename]
@ -95,7 +95,7 @@ func (f *FSLMemory) ReadFile(filename string) ([]byte, error) {
return fi.clone(), nil
}
func (f *FSLMemory) WriteFile(filename string, data []byte, perm uint32) error {
func (f *FslMemory) WriteFile(filename string, data []byte, perm uint32) error {
fi, err := f.openFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil {
return err
@ -107,7 +107,7 @@ func (f *FSLMemory) WriteFile(filename string, data []byte, perm uint32) error {
return err
}
func (f *FSLMemory) openFile(name string, flag int, perm uint32) (IFile, error) {
func (f *FslMemory) openFile(name string, flag int, perm uint32) (IFile, error) {
f.mu.Lock()
defer f.mu.Unlock()
fi, ok := f.files[name]

@ -9,7 +9,7 @@
// package ic 将整型切片压缩成二进制字节切片
package ic
// 具体使用见 LFCompressor 和 OriginCompressor
// 具体使用见 LfCompressor 和 OriginCompressor
type Compressor interface {
// 将整型切片压缩成二进制字节切片
Marshal(ids []uint32) (ret []byte)

@ -48,8 +48,8 @@ func marshalWrap(ids []uint32) (ret []byte) {
//var oc OriginCompressor
//ret = oc.Marshal(ids)
var lfc LFCompressor
lfc.FB = 4
var lfc LfCompressor
lfc.Fb = 4
ret = lfc.Marshal(ids)
log.Println("< marshal.")
@ -65,13 +65,13 @@ func unmarshalWrap(b []byte) (ret []uint32) {
//var oc OriginCompressor
//ret = oc.Unmarshal(b)
var lfc LFCompressor
lfc.FB = 4
var lfc LfCompressor
lfc.Fb = 4
ret = lfc.Unmarshal(b)
return
}
func TestIC(t *testing.T) {
func TestIc(t *testing.T) {
log.SetFlags(log.Lmicroseconds)
// 单元测试 case
@ -95,11 +95,11 @@ func TestIC(t *testing.T) {
compressors = append(compressors, &OriginCompressor{})
compressors = append(compressors, &OriginCompressor{ZlibExt: true})
compressors = append(compressors, &LFCompressor{FB: 0})
compressors = append(compressors, &LFCompressor{FB: 0, ZlibExt: true})
compressors = append(compressors, &LFCompressor{FB: 2})
compressors = append(compressors, &LFCompressor{FB: 4})
compressors = append(compressors, &LFCompressor{FB: 4, ZlibExt: true})
compressors = append(compressors, &LfCompressor{Fb: 0})
compressors = append(compressors, &LfCompressor{Fb: 0, ZlibExt: true})
compressors = append(compressors, &LfCompressor{Fb: 2})
compressors = append(compressors, &LfCompressor{Fb: 4})
compressors = append(compressors, &LfCompressor{Fb: 4, ZlibExt: true})
for _, c := range compressors {
for _, uids := range uidss {

@ -12,16 +12,16 @@ import (
"encoding/binary"
)
type LFCompressor struct {
FB uint32 // 用几个字节的 bit 表示跟随的数据
type LfCompressor struct {
Fb uint32 // 用几个字节的 bit 表示跟随的数据
ZlibExt bool // 压缩之后,是否再用 zlib 进一步压缩
oc OriginCompressor // FB 为0时退化成使用 OriginCompressor
}
// 传入的整型切片必须是从小到大有序排列
func (lfc *LFCompressor) Marshal(ids []uint32) (ret []byte) {
if lfc.FB == 0 {
func (lfc *LfCompressor) Marshal(ids []uint32) (ret []byte) {
if lfc.Fb == 0 {
ret = lfc.oc.Marshal(ids)
if lfc.ZlibExt {
ret = zlibWrite(ret)
@ -30,9 +30,9 @@ func (lfc *LFCompressor) Marshal(ids []uint32) (ret []byte) {
}
lBuf := make([]byte, 4)
fBuf := make([]byte, lfc.FB)
fBuf := make([]byte, lfc.Fb)
maxDiff := 8 * lfc.FB
maxDiff := 8 * lfc.Fb
var hasLeader bool
var leader uint32
@ -65,12 +65,12 @@ func (lfc *LFCompressor) Marshal(ids []uint32) (ret []byte) {
case 1:
binary.LittleEndian.PutUint32(lBuf, leader)
ret = append(ret, lBuf...)
dummy := make([]byte, lfc.FB)
dummy := make([]byte, lfc.Fb)
ret = append(ret, dummy...)
case 2:
binary.LittleEndian.PutUint32(lBuf, leader)
ret = append(ret, lBuf...)
dummy := make([]byte, lfc.FB)
dummy := make([]byte, lfc.Fb)
ret = append(ret, dummy...)
case 3:
binary.LittleEndian.PutUint32(lBuf, leader)
@ -83,11 +83,11 @@ func (lfc *LFCompressor) Marshal(ids []uint32) (ret []byte) {
return
}
func (lfc *LFCompressor) Unmarshal(b []byte) (ids []uint32) {
func (lfc *LfCompressor) Unmarshal(b []byte) (ids []uint32) {
if lfc.ZlibExt {
b = zlibRead(b)
}
if lfc.FB == 0 {
if lfc.Fb == 0 {
return lfc.oc.Unmarshal(b)
}
@ -102,7 +102,7 @@ func (lfc *LFCompressor) Unmarshal(b []byte) (ids []uint32) {
isLeaderStage = false
index += 4
} else {
for i := uint32(0); i < lfc.FB; i++ {
for i := uint32(0); i < lfc.Fb; i++ {
for j := uint32(0); j < 8; j++ {
if ((b[index+i] >> j) & 1) == 1 {
item = leader + (i * 8) + j + 1
@ -112,7 +112,7 @@ func (lfc *LFCompressor) Unmarshal(b []byte) (ids []uint32) {
}
isLeaderStage = true
index += lfc.FB
index += lfc.Fb
}
if int(index) == len(b) {

@ -10,7 +10,7 @@ package lru
import "container/list"
type LRU struct {
type Lru struct {
c int // capacity
m map[interface{}]*list.Element // mapping key -> index
l *list.List // value
@ -21,8 +21,8 @@ type pair struct {
v interface{}
}
func New(capacity int) *LRU {
return &LRU{
func New(capacity int) *Lru {
return &Lru{
c: capacity,
m: make(map[interface{}]*list.Element),
l: list.New(),
@ -30,10 +30,10 @@ func New(capacity int) *LRU {
}
// 注意:
// 1. 无论插入前,元素是否已经存在,插入后,元素都会存在于lru容器中
// 1. 无论插入前,元素是否已经存在,插入后,元素都会存在于Lru容器中
// 2. 插入元素时,也会更新热度(不管插入前元素是否已经存在)
// @return 插入前元素已经存在则返回false
func (lru *LRU) Put(k interface{}, v interface{}) bool {
func (lru *Lru) Put(k interface{}, v interface{}) bool {
var (
exist bool
e *list.Element
@ -58,7 +58,7 @@ func (lru *LRU) Put(k interface{}, v interface{}) bool {
return !exist
}
func (lru *LRU) Get(k interface{}) (v interface{}, exist bool) {
func (lru *Lru) Get(k interface{}) (v interface{}, exist bool) {
e, exist := lru.m[k]
if !exist {
return nil, false
@ -68,6 +68,6 @@ func (lru *LRU) Get(k interface{}) (v interface{}, exist bool) {
return pair.v, true
}
func (lru *LRU) Size() int {
func (lru *Lru) Size() int {
return lru.l.Len()
}

@ -16,7 +16,7 @@ import (
"github.com/q191201771/naza/pkg/lru"
)
func TestLRU(t *testing.T) {
func TestLru(t *testing.T) {
l := lru.New(3)
l.Put("chef", 1)
l.Put("yoko", 2)

@ -17,10 +17,10 @@ import (
)
// 获取http文件保存至字节切片
func GetHTTPFile(url string, timeoutMSec int) ([]byte, error) {
func GetHttpFile(url string, timeoutMs int) ([]byte, error) {
var c http.Client
if timeoutMSec > 0 {
c.Timeout = time.Duration(timeoutMSec) * time.Millisecond
if timeoutMs > 0 {
c.Timeout = time.Duration(timeoutMs) * time.Millisecond
}
resp, err := c.Get(url)
if err != nil {
@ -32,10 +32,10 @@ func GetHTTPFile(url string, timeoutMSec int) ([]byte, error) {
}
// 获取http文件保存至本地
func DownloadHTTPFile(url string, saveTo string, timeoutMSec int) (int64, error) {
func DownloadHttpFile(url string, saveTo string, timeoutMs int) (int64, error) {
var c http.Client
if timeoutMSec > 0 {
c.Timeout = time.Duration(timeoutMSec) * time.Millisecond
if timeoutMs > 0 {
c.Timeout = time.Duration(timeoutMs) * time.Millisecond
}
resp, err := c.Get(url)
if err != nil {

@ -15,25 +15,25 @@ import (
"github.com/q191201771/naza/pkg/nazahttp"
)
func TestGetHTTPFile(t *testing.T) {
content, err := nazahttp.GetHTTPFile("http://pengrl.com", 10000)
func TestGetHttpFile(t *testing.T) {
content, err := nazahttp.GetHttpFile("http://pengrl.com", 10000)
assert.IsNotNil(t, content)
assert.Equal(t, nil, err)
content, err = nazahttp.GetHTTPFile("http://127.0.0.1:12356", 10000)
content, err = nazahttp.GetHttpFile("http://127.0.0.1:12356", 10000)
assert.Equal(t, nil, content)
assert.IsNotNil(t, err)
}
func TestDownloadHTTPFile(t *testing.T) {
n, err := nazahttp.DownloadHTTPFile("http://pengrl.com", "/tmp/index.html", 10000)
func TestDownloadHttpFile(t *testing.T) {
n, err := nazahttp.DownloadHttpFile("http://pengrl.com", "/tmp/index.html", 10000)
assert.Equal(t, true, n > 0)
assert.Equal(t, nil, err)
n, err = nazahttp.DownloadHTTPFile("http://127.0.0.1:12356", "/tmp/index.html", 10000)
n, err = nazahttp.DownloadHttpFile("http://127.0.0.1:12356", "/tmp/index.html", 10000)
assert.IsNotNil(t, err)
// 保存文件至不存在的本地目录下
n, err = nazahttp.DownloadHTTPFile("http://pengrl.com", "/notexist/index.html", 10000)
n, err = nazahttp.DownloadHttpFile("http://pengrl.com", "/notexist/index.html", 10000)
assert.IsNotNil(t, err)
}

@ -18,7 +18,7 @@ type LineReader interface {
// @return firstLine: request的request line或response的status line
// @return headers: request header fileds的键值对
func ReadHTTPHeader(r LineReader) (firstLine string, headers map[string]string, err error) {
func ReadHttpHeader(r LineReader) (firstLine string, headers map[string]string, err error) {
headers = make(map[string]string)
var line []byte
@ -28,7 +28,7 @@ func ReadHTTPHeader(r LineReader) (firstLine string, headers map[string]string,
return
}
if len(line) == 0 || isPrefix {
err = ErrHTTPHeader
err = ErrHttpHeader
return
}
firstLine = string(line)
@ -39,7 +39,7 @@ func ReadHTTPHeader(r LineReader) (firstLine string, headers map[string]string,
break
}
if isPrefix {
err = ErrHTTPHeader
err = ErrHttpHeader
return
}
if err != nil {
@ -48,7 +48,7 @@ func ReadHTTPHeader(r LineReader) (firstLine string, headers map[string]string,
l := string(line)
pos := strings.Index(l, ":")
if pos == -1 {
err = ErrHTTPHeader
err = ErrHttpHeader
return
}
headers[strings.Trim(l[0:pos], " ")] = strings.Trim(l[pos+1:], " ")
@ -57,24 +57,24 @@ func ReadHTTPHeader(r LineReader) (firstLine string, headers map[string]string,
}
// Request-Line = Method SP URI SP Version CRLF
func ParseHTTPRequestLine(line string) (method string, uri string, version string, err error) {
func ParseHttpRequestLine(line string) (method string, uri string, version string, err error) {
return parseFirstLine(line)
}
// Status-Line = Version SP Status-Code SP Reason CRLF
func ParseHTTPStatusLine(line string) (version string, statusCode string, reason string, err error) {
func ParseHttpStatusLine(line string) (version string, statusCode string, reason string, err error) {
return parseFirstLine(line)
}
func parseFirstLine(line string) (item1, item2, item3 string, err error) {
f := strings.Index(line, " ")
if f == -1 {
err = ErrHTTPHeader
err = ErrHttpHeader
return
}
s := strings.Index(line[f+1:], " ")
if s == -1 || f+1+s+1 == len(line) {
err = ErrHTTPHeader
err = ErrHttpHeader
return
}

@ -30,18 +30,18 @@ func TestHeader(t *testing.T) {
}
go func() {
_, _ = nazahttp.GetHTTPFile(fmt.Sprintf("http://%s/test", addr), 100)
_, _ = nazahttp.GetHttpFile(fmt.Sprintf("http://%s/test", addr), 100)
}()
conn, err := ln.Accept()
r := bufio.NewReader(conn)
fl, hs, err := nazahttp.ReadHTTPHeader(r)
fl, hs, err := nazahttp.ReadHttpHeader(r)
assert.Equal(t, nil, err)
assert.Equal(t, true, len(hs) > 0)
nazalog.Debugf("first line:%s", fl)
nazalog.Debugf("header fields:%+v", hs)
m, u, v, err := nazahttp.ParseHTTPRequestLine(fl)
m, u, v, err := nazahttp.ParseHttpRequestLine(fl)
assert.Equal(t, nil, err)
nazalog.Debugf("method:%s, uri:%s, version:%s", m, u, v)
assert.Equal(t, "GET", m)
@ -51,14 +51,14 @@ func TestHeader(t *testing.T) {
}
}
func TestParseHTTPStatusLine(t *testing.T) {
v, c, r, e := nazahttp.ParseHTTPStatusLine("HTTP/1.0 200 OK")
func TestParseHttpStatusLine(t *testing.T) {
v, c, r, e := nazahttp.ParseHttpStatusLine("HTTP/1.0 200 OK")
assert.Equal(t, nil, e)
assert.Equal(t, "HTTP/1.0", v)
assert.Equal(t, "200", c)
assert.Equal(t, "OK", r)
v, c, r, e = nazahttp.ParseHTTPStatusLine("HTTP/1.1 400 Bad Request")
v, c, r, e = nazahttp.ParseHttpStatusLine("HTTP/1.1 400 Bad Request")
assert.Equal(t, nil, e)
assert.Equal(t, "HTTP/1.1", v)
assert.Equal(t, "400", c)
@ -67,7 +67,7 @@ func TestParseHTTPStatusLine(t *testing.T) {
statusLine := "HTTP/1.1 400 "
for i := 0; i <= len(statusLine); i++ {
sl := statusLine[0:i]
_, _, _, e = nazahttp.ParseHTTPStatusLine(sl)
_, _, _, e = nazahttp.ParseHttpStatusLine(sl)
assert.IsNotNil(t, e, sl)
}
}

@ -11,7 +11,7 @@ package nazahttp
import "errors"
var (
ErrHTTPHeader = errors.New("nazahttp: fxxk")
ErrHttpHeader = errors.New("nazahttp: fxxk")
ErrParamMissing = errors.New("nazahttp: param missing")
)

@ -14,28 +14,28 @@ import (
)
// e.g. bufio.Reader
type HTTPReader interface {
type HttpReader interface {
LineReader
io.Reader
}
type HTTPMsgCtx struct {
type HttpMsgCtx struct {
ReqMethodOrRespVersion string
ReqURIOrRespStatusCode string
ReqUriOrRespStatusCode string
ReqVersionOrRespReason string
Headers map[string]string
Body []byte
}
type HTTPReqMsgCtx struct {
type HttpReqMsgCtx struct {
Method string
URI string
Uri string
Version string
Headers map[string]string
Body []byte
}
type HTTPRespMsgCtx struct {
type HttpRespMsgCtx struct {
Version string
StatusCode string
Reason string
@ -43,26 +43,26 @@ type HTTPRespMsgCtx struct {
Body []byte
}
func ReadHTTPRequestMessage(r HTTPReader) (ctx HTTPReqMsgCtx, err error) {
msgCtx, err := ReadHTTPMessage(r)
func ReadHttpRequestMessage(r HttpReader) (ctx HttpReqMsgCtx, err error) {
msgCtx, err := ReadHttpMessage(r)
if err != nil {
return
}
ctx.Method = msgCtx.ReqMethodOrRespVersion
ctx.URI = msgCtx.ReqURIOrRespStatusCode
ctx.Uri = msgCtx.ReqUriOrRespStatusCode
ctx.Version = msgCtx.ReqVersionOrRespReason
ctx.Headers = msgCtx.Headers
ctx.Body = msgCtx.Body
return
}
func ReadHTTPResponseMessage(r HTTPReader) (ctx HTTPRespMsgCtx, err error) {
msgCtx, err := ReadHTTPMessage(r)
func ReadHttpResponseMessage(r HttpReader) (ctx HttpRespMsgCtx, err error) {
msgCtx, err := ReadHttpMessage(r)
if err != nil {
return
}
ctx.Version = msgCtx.ReqMethodOrRespVersion
ctx.StatusCode = msgCtx.ReqURIOrRespStatusCode
ctx.StatusCode = msgCtx.ReqUriOrRespStatusCode
ctx.Reason = msgCtx.ReqVersionOrRespReason
ctx.Headers = msgCtx.Headers
ctx.Body = msgCtx.Body
@ -70,13 +70,13 @@ func ReadHTTPResponseMessage(r HTTPReader) (ctx HTTPRespMsgCtx, err error) {
}
// 注意如果HTTP Header中不包含`Content-Length`则不会读取HTTP Body并且err返回值为nil
func ReadHTTPMessage(r HTTPReader) (ctx HTTPMsgCtx, err error) {
func ReadHttpMessage(r HttpReader) (ctx HttpMsgCtx, err error) {
var requestLine string
requestLine, ctx.Headers, err = ReadHTTPHeader(r)
requestLine, ctx.Headers, err = ReadHttpHeader(r)
if err != nil {
return ctx, err
}
ctx.ReqMethodOrRespVersion, ctx.ReqURIOrRespStatusCode, ctx.ReqVersionOrRespReason, err = ParseHTTPRequestLine(requestLine)
ctx.ReqMethodOrRespVersion, ctx.ReqUriOrRespStatusCode, ctx.ReqVersionOrRespReason, err = ParseHttpRequestLine(requestLine)
if err != nil {
return ctx, err
}

@ -13,24 +13,24 @@ import (
"strings"
)
type JSON struct {
type Json struct {
//raw []byte
m map[string]interface{}
}
func New(raw []byte) (JSON, error) {
var j JSON
func New(raw []byte) (Json, error) {
var j Json
err := j.Init(raw)
return j, err
}
func (j *JSON) Init(raw []byte) error {
func (j *Json) Init(raw []byte) error {
return json.Unmarshal(raw, &j.m)
}
// 判断 json 中某个字段是否存在
// @param path 支持多级格式,用句号`.`分隔,比如 log.level
func (j *JSON) Exist(path string) bool {
func (j *Json) Exist(path string) bool {
return exist(j.m, path)
}

@ -40,7 +40,7 @@ func Errorf(format string, v ...interface{}) {
func Fatalf(format string, v ...interface{}) {
global.Out(LevelFatal, 2, fmt.Sprintf(format, v...))
fake.OS_Exit(1)
fake.Os_Exit(1)
}
func Panicf(format string, v ...interface{}) {
@ -70,7 +70,7 @@ func Error(v ...interface{}) {
func Fatal(v ...interface{}) {
global.Out(LevelFatal, 2, fmt.Sprint(v...))
fake.OS_Exit(1)
fake.Os_Exit(1)
}
func Panic(v ...interface{}) {
@ -95,7 +95,7 @@ func Println(v ...interface{}) {
}
func Fatalln(v ...interface{}) {
global.Out(LevelInfo, 2, fmt.Sprint(v...))
fake.OS_Exit(1)
fake.Os_Exit(1)
}
func Panicln(v ...interface{}) {
global.Out(LevelInfo, 2, fmt.Sprint(v...))
@ -110,7 +110,7 @@ func Assert(expected interface{}, actual interface{}) {
global.Out(LevelError, 2, err)
case AssertFatal:
global.Out(LevelFatal, 2, err)
fake.OS_Exit(1)
fake.Os_Exit(1)
case AssertPanic:
global.Out(LevelPanic, 2, err)
panic(err)

@ -81,7 +81,7 @@ type Option struct {
ShortFileFlag bool `json:"short_file_flag"` // 是否在每行日志尾部添加源码文件及行号的信息
TimestampFlag bool `json:"timestamp_flag"` // 是否在每行日志首部添加时间戳的信息
TimestampWithMSFlag bool `json:"timestamp_with_ms_flag"` // 时间戳是否精确到毫秒
TimestampWithMsFlag bool `json:"timestamp_with_ms_flag"` // 时间戳是否精确到毫秒
LevelFlag bool `json:"level_flag"` // 日志是否包含日志级别字段
AssertBehavior AssertBehavior `json:"assert_behavior"` // 断言失败时的行为
@ -95,7 +95,7 @@ var defaultOption = Option{
IsRotateDaily: false,
ShortFileFlag: true,
TimestampFlag: true,
TimestampWithMSFlag: true,
TimestampWithMsFlag: true,
LevelFlag: true,
AssertBehavior: AssertError,
}

@ -100,7 +100,7 @@ func (l *logger) Errorf(format string, v ...interface{}) {
func (l *logger) Fatalf(format string, v ...interface{}) {
l.Out(LevelFatal, 2, fmt.Sprintf(format, v...))
fake.OS_Exit(1)
fake.Os_Exit(1)
}
func (l *logger) Panicf(format string, v ...interface{}) {
@ -130,7 +130,7 @@ func (l *logger) Error(v ...interface{}) {
func (l *logger) Fatal(v ...interface{}) {
l.Out(LevelFatal, 2, fmt.Sprint(v...))
fake.OS_Exit(1)
fake.Os_Exit(1)
}
func (l *logger) Panic(v ...interface{}) {
@ -157,7 +157,7 @@ func (l *logger) Println(v ...interface{}) {
func (l *logger) Fatalln(v ...interface{}) {
l.Out(LevelInfo, 2, fmt.Sprint(v...))
fake.OS_Exit(1)
fake.Os_Exit(1)
}
func (l *logger) Panicln(v ...interface{}) {
@ -173,7 +173,7 @@ func (l *logger) Assert(expected interface{}, actual interface{}) {
l.Out(LevelError, 2, err)
case AssertFatal:
l.Out(LevelFatal, 2, err)
fake.OS_Exit(1)
fake.Os_Exit(1)
case AssertPanic:
l.Out(LevelPanic, 2, err)
panic(err)
@ -200,7 +200,7 @@ func (l *logger) Out(level Level, calldepth int, s string) {
l.core.buf.Reset()
if l.core.option.TimestampFlag {
writeTime(&l.core.buf, now, l.core.option.TimestampWithMSFlag)
writeTime(&l.core.buf, now, l.core.option.TimestampWithMsFlag)
}
if l.core.option.LevelFlag {
@ -342,7 +342,7 @@ func validate(option Option) error {
return nil
}
func writeTime(buf *bytes.Buffer, t time.Time, withMS bool) {
func writeTime(buf *bytes.Buffer, t time.Time, withMs bool) {
year, month, day := t.Date()
itoa(buf, year, 4)
buf.WriteByte('/')
@ -358,7 +358,7 @@ func writeTime(buf *bytes.Buffer, t time.Time, withMS bool) {
buf.WriteByte(':')
itoa(buf, sec, 2)
if withMS {
if withMs {
buf.WriteByte('.')
itoa(buf, t.Nanosecond()/1e3, 6)
}

@ -167,19 +167,19 @@ func TestPanic(t *testing.T) {
func TestFatal(t *testing.T) {
var er fake.ExitResult
er = fake.WithFakeOSExit(func() {
er = fake.WithFakeOsExit(func() {
nazalog.Fatal("Fatal")
})
assert.Equal(t, true, er.HasExit)
assert.Equal(t, 1, er.ExitCode)
er = fake.WithFakeOSExit(func() {
er = fake.WithFakeOsExit(func() {
nazalog.Fatalf("Fatalf%s", ".")
})
assert.Equal(t, true, er.HasExit)
assert.Equal(t, 1, er.ExitCode)
er = fake.WithFakeOSExit(func() {
er = fake.WithFakeOsExit(func() {
nazalog.Fatalln("Fatalln")
})
assert.Equal(t, true, er.HasExit)
@ -190,19 +190,19 @@ func TestFatal(t *testing.T) {
})
assert.IsNotNil(t, logger)
assert.Equal(t, nil, err)
er = fake.WithFakeOSExit(func() {
er = fake.WithFakeOsExit(func() {
logger.Fatal("Fatal")
})
assert.Equal(t, true, er.HasExit)
assert.Equal(t, 1, er.ExitCode)
er = fake.WithFakeOSExit(func() {
er = fake.WithFakeOsExit(func() {
logger.Fatalf("Fatalf%s", ".")
})
assert.Equal(t, true, er.HasExit)
assert.Equal(t, 1, er.ExitCode)
er = fake.WithFakeOSExit(func() {
er = fake.WithFakeOsExit(func() {
logger.Fatalln("Fatalln")
})
assert.Equal(t, true, er.HasExit)
@ -239,7 +239,7 @@ func TestAssert(t *testing.T) {
_ = nazalog.Init(func(option *nazalog.Option) {
option.AssertBehavior = nazalog.AssertFatal
})
err := fake.WithFakeOSExit(func() {
err := fake.WithFakeOsExit(func() {
nazalog.Assert(nil, 1)
})
assert.Equal(t, true, err.HasExit)
@ -258,7 +258,7 @@ func TestAssert(t *testing.T) {
l, _ = nazalog.New(func(option *nazalog.Option) {
option.AssertBehavior = nazalog.AssertFatal
})
err = fake.WithFakeOSExit(func() {
err = fake.WithFakeOsExit(func() {
l.Assert(nil, 1)
})
assert.Equal(t, true, err.HasExit)
@ -303,7 +303,7 @@ func TestTimestamp(t *testing.T) {
l.Debug("without timestamp.")
l.Info("without timestamp.")
l, _ = nazalog.New(func(option *nazalog.Option) {
option.TimestampWithMSFlag = false
option.TimestampWithMsFlag = false
})
l.Debug("without timestamp.")
l.Info("timestamp without ms.")

@ -14,7 +14,7 @@ import (
)
// 返回32字节小写字符串
func MD5(b []byte) string {
func Md5(b []byte) string {
h := md5.New()
h.Write(b)
return hex.EncodeToString(h.Sum(nil))

@ -19,8 +19,8 @@ type md5Test struct {
out string
}
func TestMD5(t *testing.T) {
assert.Equal(t, "d41d8cd98f00b204e9800998ecf8427e", MD5(nil))
func TestMd5(t *testing.T) {
assert.Equal(t, "d41d8cd98f00b204e9800998ecf8427e", Md5(nil))
golden := []md5Test{
{"", "d41d8cd98f00b204e9800998ecf8427e"},
{"aaa", "47bce5c74f589f4867dbd57e9ca9f808"},
@ -28,6 +28,6 @@ func TestMD5(t *testing.T) {
{"HELLO WORLD!", "b59bc37d6441d96785bda7ab2ae98f75"},
}
for _, g := range golden {
assert.Equal(t, g.out, MD5([]byte(g.in)))
assert.Equal(t, g.out, Md5([]byte(g.in)))
}
}

@ -16,7 +16,7 @@ import (
// 从指定的UDP端口范围内寻找可绑定监听的端口绑定监听并返回
// Pool只提供Acquire获取接口不提供释放接口连接资源是标准*net.UDPConn对象需要释放时外部直接Close即可
//
type AvailUDPConnPool struct {
type AvailUdpConnPool struct {
minPort uint16
maxPort uint16
@ -24,15 +24,15 @@ type AvailUDPConnPool struct {
lastPort uint16
}
func NewAvailUDPConnPool(minPort uint16, maxPort uint16) *AvailUDPConnPool {
return &AvailUDPConnPool{
func NewAvailUdpConnPool(minPort uint16, maxPort uint16) *AvailUdpConnPool {
return &AvailUdpConnPool{
minPort: minPort,
maxPort: maxPort,
lastPort: minPort,
}
}
func (a *AvailUDPConnPool) Acquire() (*net.UDPConn, uint16, error) {
func (a *AvailUdpConnPool) Acquire() (*net.UDPConn, uint16, error) {
a.m.Lock()
defer a.m.Unlock()
@ -45,7 +45,7 @@ func (a *AvailUDPConnPool) Acquire() (*net.UDPConn, uint16, error) {
}
loopFirstFlag = false
conn, err := listenUDPWithPort(p)
conn, err := listenUdpWithPort(p)
// 绑定失败,尝试下一个端口
if err != nil {
@ -62,7 +62,7 @@ func (a *AvailUDPConnPool) Acquire() (*net.UDPConn, uint16, error) {
// 有的业务场景,需要返回两个可用的端口,并且必须是连续的
// @return 前面的是端口小的,后面的是端口+1的
//
func (a *AvailUDPConnPool) Acquire2() (*net.UDPConn, uint16, *net.UDPConn, uint16, error) {
func (a *AvailUdpConnPool) Acquire2() (*net.UDPConn, uint16, *net.UDPConn, uint16, error) {
a.m.Lock()
defer a.m.Unlock()
@ -81,7 +81,7 @@ func (a *AvailUDPConnPool) Acquire2() (*net.UDPConn, uint16, *net.UDPConn, uint1
continue
}
conn, err := listenUDPWithPort(p)
conn, err := listenUdpWithPort(p)
// 第一个就绑定失败,尝试下一个端口
if err != nil {
@ -92,7 +92,7 @@ func (a *AvailUDPConnPool) Acquire2() (*net.UDPConn, uint16, *net.UDPConn, uint1
// 绑定成功,因为我们需要两个,所以我们还要找第二个
// 因为前面已经有判断最大值了,所以直接+1
conn2, err := listenUDPWithPort(p + 1)
conn2, err := listenUdpWithPort(p + 1)
// 第二个失败了,关闭第一个,然后从第二个的下一个重新尝试
if err != nil {
@ -108,7 +108,7 @@ func (a *AvailUDPConnPool) Acquire2() (*net.UDPConn, uint16, *net.UDPConn, uint1
}
// 通过Acquire获取到可用net.UDPConn对象后将对象关闭只返回可用的端口
func (a *AvailUDPConnPool) Peek() (uint16, error) {
func (a *AvailUdpConnPool) Peek() (uint16, error) {
conn, port, err := a.Acquire()
if err == nil {
err = conn.Close()
@ -116,7 +116,7 @@ func (a *AvailUDPConnPool) Peek() (uint16, error) {
return port, err
}
func (a *AvailUDPConnPool) nextPort(p uint16) uint16 {
func (a *AvailUdpConnPool) nextPort(p uint16) uint16 {
if p == a.maxPort {
return a.minPort
}

@ -19,9 +19,9 @@ import (
"github.com/q191201771/naza/pkg/nazanet"
)
func TestAvailUDPConnPool_Acquire(t *testing.T) {
func TestAvailUdpConnPool_Acquire(t *testing.T) {
var conns []*net.UDPConn
aucp := nazanet.NewAvailUDPConnPool(8000, 8005)
aucp := nazanet.NewAvailUdpConnPool(8000, 8005)
closedOnlyOnceFlag := false
// 循环次数大于端口范围,测试后面的获取是否返回错误
@ -49,8 +49,8 @@ func TestAvailUDPConnPool_Acquire(t *testing.T) {
}
}
func TestAvailUDPConnPool_Acquire2(t *testing.T) {
aucp := nazanet.NewAvailUDPConnPool(8000, 8005)
func TestAvailUdpConnPool_Acquire2(t *testing.T) {
aucp := nazanet.NewAvailUdpConnPool(8000, 8005)
closedOnlyOnceFlag := false
// 循环次数大于端口范围,测试后面的获取是否返回错误
@ -69,7 +69,7 @@ func TestAvailUDPConnPool_Acquire2(t *testing.T) {
}
}
func TestAvailUDPConnPool_Peek(t *testing.T) {
aucp := nazanet.NewAvailUDPConnPool(8000, 8005)
func TestAvailUdpConnPool_Peek(t *testing.T) {
aucp := nazanet.NewAvailUdpConnPool(8000, 8005)
nazalog.Debug(aucp.Peek())
}

@ -13,12 +13,12 @@ import (
"net"
)
func listenUDPWithPort(port uint16) (*net.UDPConn, error) {
func listenUdpWithPort(port uint16) (*net.UDPConn, error) {
addr := fmt.Sprintf(":%d", port)
return listenUDPWithAddr(addr)
return listenUdpWithAddr(addr)
}
func listenUDPWithAddr(addr string) (*net.UDPConn, error) {
func listenUdpWithAddr(addr string) (*net.UDPConn, error) {
udpAddr, err := net.ResolveUDPAddr(udpNetwork, addr)
if err != nil {
return nil, err

@ -13,11 +13,11 @@ import (
"time"
)
// @return 上层回调返回false则关闭UDPConnection
// @return 上层回调返回false则关闭UdpConnection
//
type OnReadUDPPacket func(b []byte, raddr *net.UDPAddr, err error) bool
type OnReadUdpPacket func(b []byte, raddr *net.UDPAddr, err error) bool
type UDPConnectionOption struct {
type UdpConnectionOption struct {
// 两种初始化方式:
// 方式一:直接传入外部创建好的连接对象供内部使用
Conn *net.UDPConn
@ -37,22 +37,22 @@ type UDPConnectionOption struct {
AllocEachRead bool // 使用Read Loop时是否每次读取都申请新的内存块如果为false则复用一块内存块
}
var defaultOption = UDPConnectionOption{
var defaultOption = UdpConnectionOption{
MaxReadPacketSize: 1500,
AllocEachRead: true,
}
type UDPConnection struct {
option UDPConnectionOption
type UdpConnection struct {
option UdpConnectionOption
ruaddr *net.UDPAddr
}
type ModUDPConnectionOption func(option *UDPConnectionOption)
type ModUdpConnectionOption func(option *UdpConnectionOption)
func NewUDPConnection(modOptions ...ModUDPConnectionOption) (*UDPConnection, error) {
func NewUdpConnection(modOptions ...ModUdpConnectionOption) (*UdpConnection, error) {
var err error
c := &UDPConnection{}
c := &UdpConnection{}
c.option = defaultOption
for _, fn := range modOptions {
fn(&c.option)
@ -64,7 +64,7 @@ func NewUDPConnection(modOptions ...ModUDPConnectionOption) (*UDPConnection, err
return c, nil
}
if c.option.Conn, err = listenUDPWithAddr(c.option.LAddr); err != nil {
if c.option.Conn, err = listenUdpWithAddr(c.option.LAddr); err != nil {
return nil, err
}
return c, err
@ -74,7 +74,7 @@ func NewUDPConnection(modOptions ...ModUDPConnectionOption) (*UDPConnection, err
//
// @return error: 如果外部调用Dispose会返回error
//
func (c *UDPConnection) RunLoop(onRead OnReadUDPPacket) error {
func (c *UdpConnection) RunLoop(onRead OnReadUdpPacket) error {
var b []byte
if !c.option.AllocEachRead {
b = make([]byte, c.option.MaxReadPacketSize)
@ -97,9 +97,9 @@ func (c *UDPConnection) RunLoop(onRead OnReadUDPPacket) error {
// 直接读取数据不使用RunLoop
//
func (c *UDPConnection) ReadWithTimeout(timeoutMS int) ([]byte, *net.UDPAddr, error) {
if timeoutMS > 0 {
if err := c.option.Conn.SetReadDeadline(time.Now().Add(time.Duration(timeoutMS) * time.Millisecond)); err != nil {
func (c *UdpConnection) ReadWithTimeout(timeoutMs int) ([]byte, *net.UDPAddr, error) {
if timeoutMs > 0 {
if err := c.option.Conn.SetReadDeadline(time.Now().Add(time.Duration(timeoutMs) * time.Millisecond)); err != nil {
return nil, nil, err
}
}
@ -111,16 +111,16 @@ func (c *UDPConnection) ReadWithTimeout(timeoutMS int) ([]byte, *net.UDPAddr, er
return b[:n], raddr, nil
}
func (c *UDPConnection) Write(b []byte) error {
func (c *UdpConnection) Write(b []byte) error {
_, err := c.option.Conn.WriteToUDP(b, c.ruaddr)
return err
}
func (c *UDPConnection) Write2Addr(b []byte, ruaddr *net.UDPAddr) error {
func (c *UdpConnection) Write2Addr(b []byte, ruaddr *net.UDPAddr) error {
_, err := c.option.Conn.WriteToUDP(b, ruaddr)
return err
}
func (c *UDPConnection) Dispose() error {
func (c *UdpConnection) Dispose() error {
return c.option.Conn.Close()
}

@ -38,13 +38,13 @@ import (
// fail:
//
func TestUDPConnection(t *testing.T) {
p := nazanet.NewAvailUDPConnPool(4000, 8000)
func TestUdpConnection(t *testing.T) {
p := nazanet.NewAvailUdpConnPool(4000, 8000)
srvConn, srvPort, err := p.Acquire()
assert.Equal(t, nil, err)
toAddr1 := fmt.Sprintf("127.0.0.1:%d", srvPort)
toAddr2 := fmt.Sprintf("[::1]:%d", srvPort)
srv, err := nazanet.NewUDPConnection(func(option *nazanet.UDPConnectionOption) {
srv, err := nazanet.NewUdpConnection(func(option *nazanet.UdpConnectionOption) {
option.Conn = srvConn
})
assert.Equal(t, nil, err)
@ -68,7 +68,7 @@ func TestUDPConnection(t *testing.T) {
assert.IsNotNil(t, err)
}()
cli, err := nazanet.NewUDPConnection(func(option *nazanet.UDPConnectionOption) {
cli, err := nazanet.NewUdpConnection(func(option *nazanet.UdpConnectionOption) {
option.RAddr = toAddr1
})
assert.Equal(t, nil, err)
@ -83,7 +83,7 @@ func TestUDPConnection(t *testing.T) {
wg.Done()
}()
cli2, err := nazanet.NewUDPConnection(func(option *nazanet.UDPConnectionOption) {
cli2, err := nazanet.NewUdpConnection(func(option *nazanet.UdpConnectionOption) {
option.RAddr = toAddr2
})
assert.Equal(t, nil, err)

@ -35,6 +35,8 @@ func StringToSliceByteTmp(s string) []byte {
return *(*[]byte)(unsafe.Pointer(&ret))
}
// @deprecated 这个函数不再使用了后续直接标准库中的hex.EncodeToString,hex.DecodeString
func DumpSliceByte(b []byte) string {
// 我在写单元测试时经常遇到一个场景,
// 测试结果输出的字节切片很长,我在第一次编写时,人肉确认输出结果是正确的后,
// 我需要将这个字节切片的值作为期望值,硬编码进单元测试的代码中,供后续每次单元测试做验证。
@ -42,7 +44,7 @@ func StringToSliceByteTmp(s string) []byte {
// 有了这个函数,我可以在第一次编写时,调用该函数,将得到的结果拷贝至单元测试的代码中,
// 之后将调用该函数的代码删除。
//
func DumpSliceByte(b []byte) string {
if len(b) == 0 {
return "nil"
}

@ -17,9 +17,9 @@ import (
// NOTICE copy from https://github.com/golang/net/blob/master/http2/gotrack.go
var ErrObtainGoroutineID = errors.New("nazasync: obtain current goroutine id failed")
var ErrObtainGoroutineId = errors.New("nazasync: obtain current goroutine id failed")
func CurGoroutineID() (int64, error) {
func CurGoroutineId() (int64, error) {
var goroutineSpace = []byte("goroutine ")
b := make([]byte, 128)
@ -27,7 +27,7 @@ func CurGoroutineID() (int64, error) {
b = bytes.TrimPrefix(b, goroutineSpace)
i := bytes.IndexByte(b, ' ')
if i < 0 {
return -1, ErrObtainGoroutineID
return -1, ErrObtainGoroutineId
}
return strconv.ParseInt(string(b[:i]), 10, 64)
}

@ -17,24 +17,24 @@ import (
"github.com/q191201771/naza/pkg/nazalog"
)
func TestCurGoroutineID(t *testing.T) {
func TestCurGoroutineId(t *testing.T) {
max := 5
gid, err := CurGoroutineID()
gid, err := CurGoroutineId()
assert.Equal(t, nil, err)
nazalog.Infof("> main. gid=%d", gid)
var wg sync.WaitGroup
wg.Add(max)
for i := 0; i < max; i++ {
go func(ii int) {
gid, err := CurGoroutineID()
gid, err := CurGoroutineId()
assert.Equal(t, nil, err)
nazalog.Infof("> %d. gid=%d", ii, gid)
wg.Done()
}(i)
}
wg.Wait()
gid, err = CurGoroutineID()
gid, err = CurGoroutineId()
assert.Equal(t, nil, err)
nazalog.Infof("< main. gid=%d", gid)
}

@ -36,7 +36,7 @@ func (m *Mutex) Lock() {
if m.uniqueKey == "" {
m.uniqueKey = uniqueGen.GenUniqueKey()
}
gid, _ := CurGoroutineID()
gid, _ := CurGoroutineId()
if gid == m.gid {
nazalog.Out(nazalog.LevelError, 3, fmt.Sprintf("[%s] recursive lock. gid=%d", m.uniqueKey, gid))
}
@ -50,7 +50,7 @@ func (m *Mutex) Lock() {
func (m *Mutex) Unlock() {
m.mu.Lock()
gid, _ := CurGoroutineID()
gid, _ := CurGoroutineId()
if gid != m.gid {
if m.gid == unlockedGid {
nazalog.Out(nazalog.LevelError, 3,

@ -31,7 +31,7 @@ func TestLeakyBucket(t *testing.T) {
if err == nil {
nazalog.Debugf("TryAquire succ. goroutine=%d, index=%d", j, k)
} else {
time.Sleep(time.Duration(lb.MaybeAvailableIntervalMSec()) * time.Millisecond)
time.Sleep(time.Duration(lb.MaybeAvailableIntervalMs()) * time.Millisecond)
}
}
}(i)

@ -18,16 +18,16 @@ var ErrResourceNotAvailable = errors.New("naza.ratelimit: resource not available
// 漏桶
type LeakyBucket struct {
intervalMSec int64
intervalMs int64
mu sync.Mutex
lastTick int64
}
// @param intervalMSec 多长时间以上,允许获取到一个资源,单位毫秒
func NewLeakyBucket(intervalMSec int) *LeakyBucket {
// @param intervalMs 多长时间以上,允许获取到一个资源,单位毫秒
func NewLeakyBucket(intervalMs int) *LeakyBucket {
return &LeakyBucket{
intervalMSec: int64(intervalMSec),
intervalMs: int64(intervalMs),
// 注意,第一次获取资源,需要与创建对象时的时间点做比较
lastTick: time.Now().UnixNano() / 1e6,
}
@ -38,11 +38,11 @@ func NewLeakyBucket(intervalMSec int) *LeakyBucket {
func (lb *LeakyBucket) TryAquire() error {
lb.mu.Lock()
defer lb.mu.Unlock()
nowMSec := time.Now().UnixNano() / 1e6
nowMs := time.Now().UnixNano() / 1e6
// 距离上次获取成功时间超过了间隔阈值,返回成功
if nowMSec-lb.lastTick > lb.intervalMSec {
lb.lastTick = nowMSec
if nowMs-lb.lastTick > lb.intervalMs {
lb.lastTick = nowMs
return nil
}
@ -52,35 +52,35 @@ func (lb *LeakyBucket) TryAquire() error {
// 阻塞直到获取到资源
func (lb *LeakyBucket) WaitUntilAquire() {
lb.mu.Lock()
nowMSec := time.Now().UnixNano() / 1e6
nowMs := time.Now().UnixNano() / 1e6
diff := nowMSec - lb.lastTick
if diff > lb.intervalMSec {
lb.lastTick = nowMSec
diff := nowMs - lb.lastTick
if diff > lb.intervalMs {
lb.lastTick = nowMs
lb.mu.Unlock()
return
}
// 没有达到间隔我们更新lastTick再出锁使得其他想获取资源的协程以新的lastTick作为判断条件
lb.lastTick += lb.intervalMSec
lb.lastTick += lb.intervalMs
lb.mu.Unlock()
// 我们不需要等整个interval间隔因为可能已经过去了一段时间了
// 注意diff是根据更新前的lastTick计算得到的
time.Sleep(time.Duration(lb.intervalMSec-diff) * time.Millisecond)
time.Sleep(time.Duration(lb.intervalMs-diff) * time.Millisecond)
return
}
// 最快可获取到资源距离当前的时长, 但是不保证获取时一定能抢到
// 返回0说明可以获取返回非0则是对应的时长单位毫秒
func (lb *LeakyBucket) MaybeAvailableIntervalMSec() int64 {
func (lb *LeakyBucket) MaybeAvailableIntervalMs() int64 {
lb.mu.Lock()
defer lb.mu.Unlock()
nowMSec := time.Now().UnixNano() / 1e6
nowMs := time.Now().UnixNano() / 1e6
if nowMSec-lb.lastTick > lb.intervalMSec {
if nowMs-lb.lastTick > lb.intervalMs {
return 0
}
return lb.lastTick + lb.intervalMSec - nowMSec
return lb.lastTick + lb.intervalMs - nowMs
}

@ -20,7 +20,7 @@ import (
func TestNewLeakyBucket(t *testing.T) {
lb := ratelimit.NewLeakyBucket(10)
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
}
func TestLeakyBucket_TryAquire(t *testing.T) {
@ -32,20 +32,20 @@ func TestLeakyBucket_TryAquire(t *testing.T) {
lb = ratelimit.NewLeakyBucket(1)
time.Sleep(10 * time.Millisecond)
err = lb.TryAquire()
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
assert.Equal(t, nil, err)
time.Sleep(10 * time.Millisecond)
err = lb.TryAquire()
assert.Equal(t, nil, err)
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
lb = ratelimit.NewLeakyBucket(100)
err = lb.TryAquire()
assert.Equal(t, ratelimit.ErrResourceNotAvailable, err)
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
err = lb.TryAquire()
assert.Equal(t, ratelimit.ErrResourceNotAvailable, err)
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
}
func TestLeakyBucket_WaitUntilAquire(t *testing.T) {
@ -53,14 +53,14 @@ func TestLeakyBucket_WaitUntilAquire(t *testing.T) {
lb = ratelimit.NewLeakyBucket(1)
lb.WaitUntilAquire()
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
time.Sleep(100 * time.Millisecond)
lb.WaitUntilAquire()
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
lb = ratelimit.NewLeakyBucket(200)
lb.WaitUntilAquire()
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
lb.WaitUntilAquire()
nazalog.Debugf("MaybeAvailableIntervalMSec=%d", lb.MaybeAvailableIntervalMSec())
nazalog.Debugf("MaybeAvailableIntervalMs=%d", lb.MaybeAvailableIntervalMs())
}

@ -33,12 +33,12 @@ type TokenBucket struct {
}
// @param capacity: 桶容量大小
// @param prodTokenIntervalMSec: 生产令牌的时间间隔,单位毫秒
// @param prodTokenIntervalMs: 生产令牌的时间间隔,单位毫秒
// @param prodTokenNumEveryInterval: 每次生产多少个令牌
func NewTokenBucket(capacity int, prodTokenIntervalMSec int, prodTokenNumEveryInterval int) *TokenBucket {
func NewTokenBucket(capacity int, prodTokenIntervalMs int, prodTokenNumEveryInterval int) *TokenBucket {
tb := &TokenBucket{
capacity: capacity,
prodTokenInterval: time.Duration(time.Duration(prodTokenIntervalMSec) * time.Millisecond),
prodTokenInterval: time.Duration(time.Duration(prodTokenIntervalMs) * time.Millisecond),
prodTokenNumEveryInterval: prodTokenNumEveryInterval,
}
tb.cond = sync.NewCond(&tb.mu)

@ -20,29 +20,29 @@ var (
)
type Option struct {
DataCenterIDBits int // 数据中心编号字段在所生成 ID 所占的位数,取值范围见 validate 函数
WorkerIDBits int // 节点编号
DataCenterIdBits int // 数据中心编号字段在所生成 ID 所占的位数,取值范围见 validate 函数
WorkerIdBits int // 节点编号
SequenceBits int // 递增序列
Twepoch int64 // 基准时间点
AlwaysPositive bool // 是否只生成正数 ID如果是则时间戳所占位数会减少1位
}
var defaultOption = Option{
DataCenterIDBits: 5,
WorkerIDBits: 5,
DataCenterIdBits: 5,
WorkerIdBits: 5,
SequenceBits: 12,
Twepoch: int64(1288834974657), // 对应现实时间: 2010/11/4 9:42:54.657
AlwaysPositive: false,
}
type Node struct {
dataCenterID int64
workerID int64
dataCenterId int64
workerId int64
option Option
seqMask uint32
workerIDShift uint32
dataCenterIDShift uint32
workerIdShift uint32
dataCenterIdShift uint32
timestampShift uint32
mu sync.Mutex
@ -52,40 +52,40 @@ type Node struct {
type ModOption func(option *Option)
// dataCenterID 和 workerID 的取值范围取决于 DataCenterIDBits 和 WorkerIDBits
// 假设 DataCenterIDBits 为 5则 dataCenterID 取值范围为 [0, 32]
func New(dataCenterID int, workerID int, modOptions ...ModOption) (*Node, error) {
// dataCenterId 和 workerId 的取值范围取决于 DataCenterIdBits 和 WorkerIdBits
// 假设 DataCenterIdBits 为 5则 dataCenterId 取值范围为 [0, 32]
func New(dataCenterId int, workerId int, modOptions ...ModOption) (*Node, error) {
option := defaultOption
for _, fn := range modOptions {
fn(&option)
}
if err := validate(dataCenterID, workerID, option); err != nil {
if err := validate(dataCenterId, workerId, option); err != nil {
return nil, err
}
return &Node{
dataCenterID: int64(dataCenterID),
workerID: int64(workerID),
dataCenterId: int64(dataCenterId),
workerId: int64(workerId),
option: option,
seqMask: uint32(bitsToMax(option.SequenceBits)),
workerIDShift: uint32(option.SequenceBits),
dataCenterIDShift: uint32(option.SequenceBits + option.WorkerIDBits),
timestampShift: uint32(option.SequenceBits + option.WorkerIDBits + option.DataCenterIDBits),
workerIdShift: uint32(option.SequenceBits),
dataCenterIdShift: uint32(option.SequenceBits + option.WorkerIdBits),
timestampShift: uint32(option.SequenceBits + option.WorkerIdBits + option.DataCenterIdBits),
lastTs: -1,
}, nil
}
func (n *Node) Gen(nowUnixMSec ...int64) (int64, error) {
func (n *Node) Gen(nowUnixMs ...int64) (int64, error) {
n.mu.Lock()
defer n.mu.Unlock()
// 当前 Unix 时间戳可由外部传入
var now int64
if len(nowUnixMSec) == 0 {
if len(nowUnixMs) == 0 {
now = time.Now().UnixNano() / 1e6
} else {
now = nowUnixMSec[0]
now = nowUnixMs[0]
}
// 时间戳回退,返回错误
@ -115,31 +115,31 @@ func (n *Node) Gen(nowUnixMSec ...int64) (int64, error) {
ts <<= n.timestampShift
// 用所有字段组合生成 ID 返回
return ts | (n.dataCenterID << n.dataCenterIDShift) | (n.workerID << n.workerIDShift) | int64(n.seq), nil
return ts | (n.dataCenterId << n.dataCenterIdShift) | (n.workerId << n.workerIdShift) | int64(n.seq), nil
}
func validate(dataCenterID int, workerID int, option Option) error {
if option.DataCenterIDBits < 0 || option.DataCenterIDBits > 31 {
func validate(dataCenterId int, workerId int, option Option) error {
if option.DataCenterIdBits < 0 || option.DataCenterIdBits > 31 {
return ErrInitial
}
if option.WorkerIDBits < 0 || option.WorkerIDBits > 31 {
if option.WorkerIdBits < 0 || option.WorkerIdBits > 31 {
return ErrInitial
}
if option.SequenceBits < 0 || option.SequenceBits > 31 {
return ErrInitial
}
if option.DataCenterIDBits+option.WorkerIDBits+option.SequenceBits >= 64 {
if option.DataCenterIdBits+option.WorkerIdBits+option.SequenceBits >= 64 {
return ErrInitial
}
if option.DataCenterIDBits > 0 {
if dataCenterID > bitsToMax(option.DataCenterIDBits) {
if option.DataCenterIdBits > 0 {
if dataCenterId > bitsToMax(option.DataCenterIdBits) {
return ErrInitial
}
}
if option.WorkerIDBits > 0 {
if workerID > bitsToMax(option.WorkerIDBits) {
if option.WorkerIdBits > 0 {
if workerId > bitsToMax(option.WorkerIdBits) {
return ErrInitial
}
}

@ -59,29 +59,29 @@ func TestErrInitial(t *testing.T) {
assert.Equal(t, snowflake.ErrInitial, err)
n, err = snowflake.New(0, 0, func(option *snowflake.Option) {
option.WorkerIDBits = 64
option.WorkerIdBits = 64
})
assert.Equal(t, snowflake.ErrInitial, err)
n, err = snowflake.New(0, 0, func(option *snowflake.Option) {
option.DataCenterIDBits = 64
option.DataCenterIdBits = 64
})
assert.Equal(t, snowflake.ErrInitial, err)
n, err = snowflake.New(0, 0, func(option *snowflake.Option) {
option.DataCenterIDBits = 31
option.WorkerIDBits = 31
option.DataCenterIdBits = 31
option.WorkerIdBits = 31
option.SequenceBits = 31
})
assert.Equal(t, snowflake.ErrInitial, err)
n, err = snowflake.New(100, 0, func(option *snowflake.Option) {
option.DataCenterIDBits = 1
option.DataCenterIdBits = 1
})
assert.Equal(t, snowflake.ErrInitial, err)
n, err = snowflake.New(0, 100, func(option *snowflake.Option) {
option.WorkerIDBits = 1
option.WorkerIdBits = 1
})
assert.Equal(t, snowflake.ErrInitial, err)
@ -110,7 +110,7 @@ func TestErrGen(t *testing.T) {
nazalog.Debug(id)
}
func TestMT(t *testing.T) {
func TestMt(t *testing.T) {
var (
n *snowflake.Node
err error

Loading…
Cancel
Save