Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions USE_GO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 初始化项目要进入 full-check中进行这两个命令
go mod init full_check
go mod tidy

# 自动下载缺失的模块并更新 go.sum 文件
go get -t ./common

# 执行模块下的断言
go test D:\IntelliJIDEA2022.3.3\idea-project\RedisFullCheck\src\full_check\common -v
go test ./common -v
11 changes: 6 additions & 5 deletions src/full_check/checker/base.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package checker

import (
"full_check/client"
"full_check/common"
"sync"
"full_check/metric"
"full_check/client"
"sync"
)

type FullCheckParameter struct {
Expand All @@ -16,11 +16,12 @@ type FullCheckParameter struct {
BatchCount int
Parallel int
FilterTree *common.Trie
BlockTree *common.Trie
}

type VerifierBase struct {
Stat *metric.Stat
Param *FullCheckParameter
Stat *metric.Stat
Param *FullCheckParameter
}

func (p *VerifierBase) IncrKeyStat(oneKeyInfo *common.Key) {
Expand Down Expand Up @@ -102,4 +103,4 @@ type IVerifier interface {

type ValueOutlineVerifier struct {
VerifierBase
}
}
11 changes: 9 additions & 2 deletions src/full_check/common/common.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package common

import (
"github.com/cihub/seelog"
"fmt"
"github.com/cihub/seelog"
)

const (
Expand Down Expand Up @@ -42,6 +42,13 @@ func CheckFilter(filterTree *Trie, keyBytes []byte) bool {
return filterTree.Search(keyBytes)
}

func CheckBlock(filterTree *Trie, keyBytes []byte) bool {
if filterTree == nil { // all pass when filter list is empty
return false
}
return filterTree.Search(keyBytes)
}

func HandleLogLevel(logLevel string) (string, error) {
// seelog library is disgusting
switch logLevel {
Expand All @@ -58,4 +65,4 @@ func HandleLogLevel(logLevel string) (string, error) {
default:
return "", fmt.Errorf("unknown log level[%v]", logLevel)
}
}
}
151 changes: 133 additions & 18 deletions src/full_check/common/trieTree.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,103 @@
package common

const (
Star = byte('*')
import (
"regexp"
"strings"
)

type TrieNode struct {
children map[byte]*TrieNode
isEnd bool
isStar bool // is ending by *
isEnd bool // 精确匹配
isPrefix bool // 前缀匹配
isSuffix bool // 后缀匹配
isAll bool // 全匹配(空串或 "*")
}

func newTrieNode() *TrieNode {
return &TrieNode{children: make(map[byte]*TrieNode), isEnd: false, isStar: false}
return &TrieNode{
children: make(map[byte]*TrieNode),
}
}

type Trie struct {
root *TrieNode
root *TrieNode
regexList []*regexp.Regexp // 存储正则表达式
}

func NewTrie() *Trie {
return &Trie{root: newTrieNode()}
return &Trie{
root: newTrieNode(),
regexList: make([]*regexp.Regexp, 0),
}
}

func reverse(word []byte) []byte {
for i, j := 0, len(word)-1; i < j; i, j = i+1, j-1 {
word[i], word[j] = word[j], word[i]
}
return word
}

//func isRegex(str string) bool {
// // 简单判断是否是正则表达式(也可以用更严谨的规则)
// return strings.HasPrefix(str, "^") || strings.HasSuffix(str, "$") || strings.Contains(str, ".*")
//}

func isRegex(str string) bool {
// 如果是前缀或后缀匹配(单个 * 在开头或结尾),不算正则表达式
if strings.HasSuffix(str, "*") || strings.HasPrefix(str, "*") {
return false
}
// 如果包含真正的正则符号,则认为是正则表达式
return strings.ContainsAny(str, "^$+?.[](){}|\\")
}

func (trie *Trie) Insert(word []byte) {
node := trie.root
for _, char := range word {
if char == Star {
node.isStar = true
break
str := string(word)

// 如果是正则表达式,直接加入 regexList
if isRegex(str) {
if re, err := regexp.Compile(str); err == nil {
trie.regexList = append(trie.regexList, re)
}
return
}

// 全匹配
if len(word) == 0 || (len(word) == 1 && word[0] == '*') {
node.isAll = true
return
}

// 前缀匹配(xxx*)
if word[len(word)-1] == '*' {
for _, char := range word[:len(word)-1] {
if _, ok := node.children[char]; !ok {
node.children[char] = newTrieNode()
}
node = node.children[char]
}
node.isPrefix = true
return
}

_, ok := node.children[char]
if !ok {
// 后缀匹配(*xxx)
if word[0] == '*' {
reversedWord := reverse(word[1:])
for _, char := range reversedWord {
if _, ok := node.children[char]; !ok {
node.children[char] = newTrieNode()
}
node = node.children[char]
}
node.isSuffix = true
return
}

// 精确匹配
for _, char := range word {
if _, ok := node.children[char]; !ok {
node.children[char] = newTrieNode()
}
node = node.children[char]
Expand All @@ -41,14 +107,63 @@ func (trie *Trie) Insert(word []byte) {

func (trie *Trie) Search(word []byte) bool {
node := trie.root

if node.isAll {
return true
}

// 精确匹配
curr := node
for _, char := range word {
if _, ok := curr.children[char]; !ok {
curr = nil
break
}
curr = curr.children[char]
}
if curr != nil && curr.isEnd {
return true
}

// 前缀匹配
curr = node
for _, char := range word {
if node.isStar {
if curr.isPrefix {
return true
}
if _, ok := node.children[char]; !ok {
return false
if _, ok := curr.children[char]; !ok {
curr = nil
break
}
node = node.children[char]
curr = curr.children[char]
}
if curr != nil && curr.isPrefix {
return true
}
return node.isEnd || node.isStar

// 后缀匹配
reversedWord := reverse(append([]byte(nil), word...))
curr = node
for _, char := range reversedWord {
if curr.isSuffix {
return true
}
if _, ok := curr.children[char]; !ok {
curr = nil
break
}
curr = curr.children[char]
}
if curr != nil && curr.isSuffix {
return true
}

// 正则匹配
for _, re := range trie.regexList {
if re.Match(word) {
return true
}
}

return false
}
Loading