From 6c4d17e4fe6873558c981a725b21c46e2c1435bb Mon Sep 17 00:00:00 2001 From: aozhiwei Date: Sat, 12 Aug 2023 12:21:19 +0800 Subject: [PATCH] 1 --- go.mod | 2 +- metamgr.go | 316 --------------------------------------------------- metatable.go | 138 ++++++++++++++++++++++ sysutils.go | 6 + 4 files changed, 145 insertions(+), 317 deletions(-) delete mode 100644 metamgr.go create mode 100644 metatable.go diff --git a/go.mod b/go.mod index 1e0f5f3..593a56e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module f5 -go 1.14 +go 1.20 require ( github.com/golang/protobuf v1.4.2 diff --git a/metamgr.go b/metamgr.go deleted file mode 100644 index 6ca8e4d..0000000 --- a/metamgr.go +++ /dev/null @@ -1,316 +0,0 @@ -package f5 - -import ( - "os" - "bufio" - "strings" - "reflect" - "fmt" - "strconv" - "encoding/json" - "q5" - - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/jsonpb" - "google.golang.org/protobuf/reflect/protoreflect" -) - -type MetaClass struct { - FileName string - Idx int - RawMeta interface{} - WrapMeta interface{} - PrimKey string - SecKey string - eleMeta reflect.Type -} - -type MetaMgr struct { - metaClasses *[]MetaClass - rawList []interface{} - wrapList []interface{} - wrapIdHash []map[int64]interface{} - wrapNameHash []map[string]interface{} -} - -func (this *MetaMgr) Init() { - -} - -func (this *MetaMgr) UnInit() { - -} - -func (this *MetaMgr) RegisterMetaClasses(metaClasses *[]MetaClass) { - for i := 0; i < len(*metaClasses); i++ { - metaClass := &(*metaClasses)[i] - msgType := reflect.TypeOf(metaClass.RawMeta).Elem() - msg := reflect.New(msgType) - metaClass.eleMeta = reflect.TypeOf(msg.Elem().FieldByName("Values").Interface()).Elem().Elem() - if metaClass.eleMeta == nil { - panic(fmt.Sprintf( - "registerMetaClasses error not found Values field %s", - metaClass.FileName)) - } - } - this.metaClasses = metaClasses -} - -func (this *MetaMgr) Load() { - this.rawList = make([]interface{}, len(*this.metaClasses)) - this.wrapList = make([]interface{}, len(*this.metaClasses)) - this.wrapIdHash = make([]map[int64]interface{}, len(*this.metaClasses)) - this.wrapNameHash = make([]map[string]interface{}, len(*this.metaClasses)) - this.loadRawMetaTable() - this.bindPrimKey() - this.firstInitMetaList() - this.secondInitMetaList() -} - -func (this *MetaMgr) loadRawMetaTable() { - for _, metaClass := range *this.metaClasses { - rawMeta, _ := this.loadJson(&metaClass) - values := rawMeta.Elem().FieldByName("Values") - wrapMetaType := reflect.TypeOf(metaClass.WrapMeta) - wrapMetaList := reflect.MakeSlice(reflect.SliceOf(wrapMetaType), 0, values.Len()) - for i := 0; i < values.Len(); i++ { - val := values.Index(i) - - wrapMeta := reflect.New(reflect.TypeOf(wrapMetaList.Interface()).Elem().Elem()) - clsName := reflect.TypeOf(val.Elem().Interface()).Name() - clsField := wrapMeta.Elem().FieldByName(clsName) - clsField.Set(val) - - wrapMetaList = reflect.Append(wrapMetaList, wrapMeta) - } - - this.rawList[metaClass.Idx] = rawMeta - this.wrapList[metaClass.Idx] = wrapMetaList.Interface() - this.wrapIdHash[metaClass.Idx] = map[int64]interface{}{} - this.wrapNameHash[metaClass.Idx] = map[string]interface{}{} - } -} - -func (this *MetaMgr) bindPrimKey() { - bindFunc := func (metaClass *MetaClass, wrapMeta reflect.Value) { - primVal := wrapMeta.Elem().FieldByName(metaClass.PrimKey) - secVal := wrapMeta.Elem().FieldByName(metaClass.SecKey) - nameHash := this.wrapNameHash[metaClass.Idx] - idHash := this.wrapIdHash[metaClass.Idx] - if fieldVal, ok := primVal.Interface().(*string); ok { - if _, ok := nameHash[*fieldVal]; ok { - panic(fmt.Sprintf( - "bindPrimKey duplicated key error %s %s", - metaClass.FileName, - *fieldVal)) - } - nameHash[*fieldVal] = wrapMeta - } else if fieldVal, ok := primVal.Interface().(*int32); ok { - if metaClass.SecKey == "" { - if _, ok := idHash[int64(*fieldVal)]; ok { - panic(fmt.Sprintf( - "bindPrimKey duplicated key error %s %s", - metaClass.FileName, - *fieldVal)) - } - idHash[int64(*fieldVal)] = wrapMeta.Interface() - } else { - if subFieldVal, ok := secVal.Interface().(*int32); ok { - if _, ok := idHash[q5.MkInt64(*fieldVal, *subFieldVal)]; ok { - panic(fmt.Sprintf( - "bindPrimKey duplicated key error %s %s", - metaClass.FileName, - q5.MkInt64(*fieldVal, *subFieldVal))) - } - idHash[q5.MkInt64(*fieldVal, *subFieldVal)] = wrapMeta.Interface() - } else { - panic(fmt.Sprintf("bindPrimKey subField error %s", metaClass.FileName)) - } - } - } else { - panic(fmt.Sprintf("bindPrimKey primKey error %s", metaClass.FileName)) - } - } - for _, metaClass := range *this.metaClasses { - wrapMetaList := reflect.ValueOf(this.wrapList[metaClass.Idx]) - for i := 0; i < wrapMetaList.Len(); i++ { - wrapMeta := wrapMetaList.Index(i) - if metaClass.PrimKey == "" { - this.wrapIdHash[metaClass.Idx][int64(i + 1)] = wrapMeta.Interface() - } else { - bindFunc(&metaClass, wrapMeta) - } - } - } -} - -func (this *MetaMgr) loadJson(metaClass *MetaClass) (reflect.Value, error) { - if f, err := os.Open(metaClass.FileName); err == nil { - data, _ := bufio.NewReader(f).ReadString(0) - switch q5.JsonStrType(data) { - case q5.JSON_ARRAY: - break - case q5.JSON_OBJECT: - data = "[" + data + "]" - default: - panic(fmt.Sprintf("error json format %s", metaClass.FileName)) - } - data = this.adjustJsonForamt(metaClass, data) - data = "{\"values\":" + data + "}" - - msgType := reflect.TypeOf(metaClass.RawMeta).Elem() - msg := reflect.New(msgType) - msgPb := msg.Interface().(proto.Message) - u := jsonpb.Unmarshaler{AllowUnknownFields: true} - err := u.Unmarshal(strings.NewReader(data), msgPb) - if err != nil { - panic(fmt.Sprintf( - "parse json error %s %s %s", - err, - metaClass.FileName, - msgType.Name())) - } - return msg, err - } else { - panic(fmt.Sprintf("open metafile error %s %s", metaClass.FileName, err)) - } -} - -func (this *MetaMgr) GetMetaById(idx int, id int32) interface{} { - return this.GetMetaById64(idx, int64(id)) -} - -func (this *MetaMgr) GetMetaById64(idx int, id int64) interface{} { - if idx >=0 && idx < len(this.wrapIdHash) { - idHash := this.wrapIdHash[idx] - if v, ok := idHash[id]; ok { - return reflect.ValueOf(v).Interface() - } else { - return nil - } - } - return nil -} - -func (this *MetaMgr) GetMetaByName(idx int, name string) interface{} { - if idx >=0 && idx < len(this.wrapNameHash) { - nameHash := this.wrapNameHash[idx] - if v, ok := nameHash[name]; ok { - return v - } else { - return nil - } - } - return nil -} - -func (this *MetaMgr) GetMetaList(idx int) interface{} { - if idx >=0 && idx < len(this.wrapList) { - return this.wrapList[idx] - } - return nil -} - -func (this *MetaMgr) adjustJsonForamt(metaClass *MetaClass, rawData string) string { - adjustFieldFunc := func(msg map[string]interface{}, key string, val interface{}, field protoreflect.FieldDescriptor) { - switch field.Kind() { - case - protoreflect.Int32Kind, - protoreflect.Sint32Kind, - protoreflect.Int64Kind, - protoreflect.Sint64Kind, - protoreflect.Uint64Kind, - protoreflect.Sfixed32Kind, - protoreflect.Fixed32Kind, - protoreflect.FloatKind, - protoreflect.Sfixed64Kind, - protoreflect.Fixed64Kind, - protoreflect.DoubleKind: - if q5.IsNumberType(val) { - } else if reflect.TypeOf(val).Kind() == reflect.String { - strVal := val.(string) - if strVal == "" { - msg[key] = 0 - } else { - intVal, err := strconv.ParseInt(strVal, 10, 64) - if err == nil { - msg[key] = intVal - } else { - floatVal, err := strconv.ParseFloat(strVal, 64) - if err == nil { - msg[key] = floatVal - } else { - panic(fmt.Sprintf( - "adjustJsonFormat error %s %s %s", - metaClass.FileName, - key, - val)) - } - } - } - } - case - protoreflect.BoolKind, - protoreflect.EnumKind, - protoreflect.BytesKind, - //protoreflect.MessageKind, - protoreflect.GroupKind: - panic(fmt.Sprintf( - "adjustJsonFormat error %s %s %s", - metaClass.FileName, - key, - val)) - case protoreflect.MessageKind: - break - } - } - var rawJson []map[string]interface{} - err := json.Unmarshal([]byte(rawData), &rawJson) - if err != nil { - panic(fmt.Sprintf("adjustJsonFormat unmarshal error %s %s", metaClass.FileName, err)) - } - msgType := proto.MessageReflect(reflect.New(metaClass.eleMeta).Interface().(proto.Message)) - for i := 0; i < len(rawJson); i++ { - msg := rawJson[i] - for key, val := range msg { - field := msgType.Descriptor().Fields().ByName(protoreflect.Name(key)) - if field != nil { - adjustFieldFunc(msg, key, val, field) - } - } - } - - newData, err := json.Marshal(rawJson) - //fmt.Println("rawData ", string(rawData)) - //fmt.Println("newData ", string(newData)) - if err != nil { - panic(fmt.Sprintf("adjustJsonFormat marshal error %s %s", metaClass.FileName, err)) - } - return string(newData) -} - -func (this *MetaMgr) firstInitMetaList() { - for i := 0; i < len(this.wrapList); i++ { - metaList := reflect.ValueOf(this.wrapList[i]) - for ii := 0; ii < metaList.Len(); ii++ { - meta := metaList.Index(ii) - initFunc := meta.MethodByName("Init") - if initFunc.IsValid() { - initFunc.Call(nil) - } - } - } -} - -func (this *MetaMgr) secondInitMetaList() { - for i := 0; i < len(this.wrapList); i++ { - metaList := reflect.ValueOf(this.wrapList[i]) - for i := 0; i < metaList.Len(); i++ { - meta := metaList.Index(i) - init2Func := meta.MethodByName("Init2") - if init2Func.IsValid() { - init2Func.Call(nil) - } - } - } -} diff --git a/metatable.go b/metatable.go new file mode 100644 index 0000000..d8b624a --- /dev/null +++ b/metatable.go @@ -0,0 +1,138 @@ +package f5 + +import ( + "reflect" +) + +type MetaTable interface { + IsNoLoad() bool + Load() + PreInit1() + ElementsInit(int) + PostInit1() +} + +type LoadFromJson interface { + LoadFromJsonStr(string) +} + +type RawMetaTable[T any] struct { + FileName string + PrimKey string + NoLoad bool + rawList []*T +} + +type IdMetaTable[T any] struct { + RawMetaTable[T] + idHash map[int64]*T +} + +type NameMetaTable[T any] struct { + RawMetaTable[T] + nameHash map[string]*T +} + +func (this *RawMetaTable[T]) Traverse(cb func (*T) bool) { + for _, val := range this.rawList { + if !cb(val) { + break + } + } +} + +func (this *RawMetaTable[T]) IsNoLoad() bool { + return this.NoLoad +} + +func (this *RawMetaTable[T]) PreInit1() { +} + +func (this *RawMetaTable[T]) ElementInit(round int) { + type RoundInit1 interface { + Init1() + } + type RoundInit2 interface { + Init2() + } + type RoundInit3 interface { + Init3() + } + this.Traverse(func (obj *T) bool { + var x interface{} = obj + switch round { + case 0: + if init, ok := x.(RoundInit1); ok { + init.Init1() + } + case 1: + if init, ok := x.(RoundInit2); ok { + init.Init2() + } + case 2: + if init, ok := x.(RoundInit3); ok { + init.Init3() + } + } + return true + }) +} + +func (this *IdMetaTable[T]) GetById(id int64) *T { + if v, ok := this.idHash[id]; ok { + return v + } else { + return nil + } +} + +func (this *IdMetaTable[T]) Load() { + if this.NoLoad { + return + } +} + +func (this *NameMetaTable[T]) GetByName(name string) *T { + if v, ok := this.nameHash[name]; ok { + return v + } else { + return nil + } +} + +func (this *NameMetaTable[T]) Load() { + if this.NoLoad { + return + } +} + +func LoadMetaTable(table interface{}) { + ele := reflect.ValueOf(table).Elem() + for i := 0; i < ele.NumField(); i++ { + var tbl MetaTable = ele.Field(i).Interface().(MetaTable) + if !tbl.IsNoLoad() { + tbl.PreInit1() + } + } + for i := 0; i < ele.NumField(); i++ { + var tbl MetaTable = ele.Field(i).Interface().(MetaTable) + if !tbl.IsNoLoad() { + tbl.Load() + } + } + for i := 0; i < 3; i++ { + for ii := 0; ii < ele.NumField(); ii++ { + var tbl MetaTable = ele.Field(ii).Interface().(MetaTable) + if !tbl.IsNoLoad() { + tbl.Load() + } + tbl.ElementsInit(i) + } + } + for i := 0; i < ele.NumField(); i++ { + var tbl MetaTable = ele.Field(i).Interface().(MetaTable) + if !tbl.IsNoLoad() { + tbl.PostInit1() + } + } +} diff --git a/sysutils.go b/sysutils.go index dd69f9a..45682d6 100644 --- a/sysutils.go +++ b/sysutils.go @@ -71,6 +71,12 @@ func ExtractOpenIdFromAccountId(accountId string) string { return strings.Join(tmpStrings[2:], "_") } +func New[T any](cb func(*T)) *T { + obj := new(T) + cb(obj) + return obj +} + func init() { switch os.Getenv("SERVER_ENV") { case "TEST":