From b2a9d97eb5cb6954aa865b1d04ea42e84917e062 Mon Sep 17 00:00:00 2001 From: walon Date: Mon, 16 Nov 2020 13:01:53 +0800 Subject: [PATCH] add db and proto job. fix some compile error. --- src/Luban.Job.Db/Luban.Job.Db.csproj | 18 + src/Luban.Job.Db/Source/Defs/DbDefLoader.cs | 52 ++ src/Luban.Job.Db/Source/Defs/DbDefTypeBase.cs | 9 + src/Luban.Job.Db/Source/Defs/DefAssembly.cs | 109 +++ src/Luban.Job.Db/Source/Defs/DefBean.cs | 182 +++++ src/Luban.Job.Db/Source/Defs/DefField.cs | 15 + src/Luban.Job.Db/Source/Defs/DefTable.cs | 52 ++ src/Luban.Job.Db/Source/Generate/CsRender.cs | 357 ++++++++++ src/Luban.Job.Db/Source/JobController.cs | 18 + src/Luban.Job.Db/Source/Program.cs | 119 ++++ src/Luban.Job.Db/Source/RawDefs/Defines.cs | 20 + src/Luban.Job.Db/Source/RawDefs/Table.cs | 17 + src/Luban.Job.Db/Source/RpcController.cs | 623 ++++++++++++++++++ src/Luban.Job.Db/Source/TTypeExtensions.cs | 18 + .../TypeVisitors/DbCsInitFieldVisitor.cs | 133 ++++ .../Source/TypeVisitors/DbWriteBlob.cs | 136 ++++ .../Source/TypeVisitors/ImmutableTypeName.cs | 125 ++++ src/Luban.Job.Proto/Luban.Job.Proto.csproj | 18 + .../Source/Defs/DefAssembly.cs | 111 ++++ src/Luban.Job.Proto/Source/Defs/DefBean.cs | 18 + src/Luban.Job.Proto/Source/Defs/DefField.cs | 15 + src/Luban.Job.Proto/Source/Defs/DefProto.cs | 37 ++ src/Luban.Job.Proto/Source/Defs/DefRpc.cs | 50 ++ .../Source/Defs/ProtoDefLoader.cs | 100 +++ .../Source/Defs/ProtoDefTypeBase.cs | 29 + .../Source/Generate/CsRender.cs | 324 +++++++++ .../Source/Generate/LuaRender.cs | 303 +++++++++ src/Luban.Job.Proto/Source/GenerateProto.cs | 56 ++ src/Luban.Job.Proto/Source/JobController.cs | 16 + src/Luban.Job.Proto/Source/RawDefs/Defines.cs | 26 + src/Luban.Job.Proto/Source/RawDefs/PProto.cs | 17 + src/Luban.Job.Proto/Source/RawDefs/PRpc.cs | 16 + src/Luban.Job.Proto/Source/RawDefs/Service.cs | 12 + src/Luban.Job.Proto/Source/RpcController.cs | 623 ++++++++++++++++++ src/Luban.Server/Luban.Server.csproj | 2 + src/Luban.Server/Source/Program.cs | 2 + src/Luban.sln | 12 + 37 files changed, 3790 insertions(+) create mode 100644 src/Luban.Job.Db/Luban.Job.Db.csproj create mode 100644 src/Luban.Job.Db/Source/Defs/DbDefLoader.cs create mode 100644 src/Luban.Job.Db/Source/Defs/DbDefTypeBase.cs create mode 100644 src/Luban.Job.Db/Source/Defs/DefAssembly.cs create mode 100644 src/Luban.Job.Db/Source/Defs/DefBean.cs create mode 100644 src/Luban.Job.Db/Source/Defs/DefField.cs create mode 100644 src/Luban.Job.Db/Source/Defs/DefTable.cs create mode 100644 src/Luban.Job.Db/Source/Generate/CsRender.cs create mode 100644 src/Luban.Job.Db/Source/JobController.cs create mode 100644 src/Luban.Job.Db/Source/Program.cs create mode 100644 src/Luban.Job.Db/Source/RawDefs/Defines.cs create mode 100644 src/Luban.Job.Db/Source/RawDefs/Table.cs create mode 100644 src/Luban.Job.Db/Source/RpcController.cs create mode 100644 src/Luban.Job.Db/Source/TTypeExtensions.cs create mode 100644 src/Luban.Job.Db/Source/TypeVisitors/DbCsInitFieldVisitor.cs create mode 100644 src/Luban.Job.Db/Source/TypeVisitors/DbWriteBlob.cs create mode 100644 src/Luban.Job.Db/Source/TypeVisitors/ImmutableTypeName.cs create mode 100644 src/Luban.Job.Proto/Luban.Job.Proto.csproj create mode 100644 src/Luban.Job.Proto/Source/Defs/DefAssembly.cs create mode 100644 src/Luban.Job.Proto/Source/Defs/DefBean.cs create mode 100644 src/Luban.Job.Proto/Source/Defs/DefField.cs create mode 100644 src/Luban.Job.Proto/Source/Defs/DefProto.cs create mode 100644 src/Luban.Job.Proto/Source/Defs/DefRpc.cs create mode 100644 src/Luban.Job.Proto/Source/Defs/ProtoDefLoader.cs create mode 100644 src/Luban.Job.Proto/Source/Defs/ProtoDefTypeBase.cs create mode 100644 src/Luban.Job.Proto/Source/Generate/CsRender.cs create mode 100644 src/Luban.Job.Proto/Source/Generate/LuaRender.cs create mode 100644 src/Luban.Job.Proto/Source/GenerateProto.cs create mode 100644 src/Luban.Job.Proto/Source/JobController.cs create mode 100644 src/Luban.Job.Proto/Source/RawDefs/Defines.cs create mode 100644 src/Luban.Job.Proto/Source/RawDefs/PProto.cs create mode 100644 src/Luban.Job.Proto/Source/RawDefs/PRpc.cs create mode 100644 src/Luban.Job.Proto/Source/RawDefs/Service.cs create mode 100644 src/Luban.Job.Proto/Source/RpcController.cs diff --git a/src/Luban.Job.Db/Luban.Job.Db.csproj b/src/Luban.Job.Db/Luban.Job.Db.csproj new file mode 100644 index 0000000..aa0bab2 --- /dev/null +++ b/src/Luban.Job.Db/Luban.Job.Db.csproj @@ -0,0 +1,18 @@ + + + + Library + net5.0 + + + + + + + + + + + + + diff --git a/src/Luban.Job.Db/Source/Defs/DbDefLoader.cs b/src/Luban.Job.Db/Source/Defs/DbDefLoader.cs new file mode 100644 index 0000000..e1ed832 --- /dev/null +++ b/src/Luban.Job.Db/Source/Defs/DbDefLoader.cs @@ -0,0 +1,52 @@ +using Luban.Job.Common.Utils; +using Luban.Job.Common.Defs; +using System.Collections.Generic; +using System.Xml.Linq; +using Luban.Server.Common; +using Luban.Common.Utils; +using Luban.Job.Db.RawDefs; + +namespace Luban.Job.Db.Defs +{ + class DbDefLoader : CommonDefLoader + { + private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger(); + + private readonly List _tables = new List
(); + + public DbDefLoader(RemoteAgent agent) : base(agent) + { + RegisterModuleDefineHandler("table", AddTable); + } + + public Defines BuildDefines() + { + return new Defines(); + } + + + + private readonly List _tableOptionalAttrs = new List { "memory" }; + private readonly List _tableRequireAttrs = new List { "name", "id", "key", "value" }; + + private void AddTable(XElement e) + { + ValidAttrKeys(e, _tableOptionalAttrs, _tableRequireAttrs); + var p = new Table() + { + Id = XmlUtil.GetRequiredIntAttribute(e, "id"), + Name = XmlUtil.GetRequiredAttribute(e, "name"), + Namespace = CurNamespace, + KeyType = XmlUtil.GetRequiredAttribute(e, "key"), + ValueType = XmlUtil.GetRequiredAttribute(e, "value"), + IsPersistent = !XmlUtil.GetOptionBoolAttribute(e, "memory"), + }; + + s_logger.Trace("add Db:{@Db}", p); + _tables.Add(p); + } + + + + } +} diff --git a/src/Luban.Job.Db/Source/Defs/DbDefTypeBase.cs b/src/Luban.Job.Db/Source/Defs/DbDefTypeBase.cs new file mode 100644 index 0000000..a3618b0 --- /dev/null +++ b/src/Luban.Job.Db/Source/Defs/DbDefTypeBase.cs @@ -0,0 +1,9 @@ +using Luban.Job.Common.Defs; + +namespace Luban.Job.Db.Defs +{ + abstract class DbDefTypeBase : DefTypeBase + { + public DefAssembly Assembly => (DefAssembly)AssemblyBase; + } +} diff --git a/src/Luban.Job.Db/Source/Defs/DefAssembly.cs b/src/Luban.Job.Db/Source/Defs/DefAssembly.cs new file mode 100644 index 0000000..fdc49af --- /dev/null +++ b/src/Luban.Job.Db/Source/Defs/DefAssembly.cs @@ -0,0 +1,109 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Db.RawDefs; +using Luban.Server.Common; +using System; +using System.Collections.Generic; + +namespace Luban.Job.Db.Defs +{ + class DefAssembly : DefAssemblyBase + { + private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger(); + + private readonly Dictionary name2DbTables = new Dictionary(); + + private readonly Dictionary id2DbTables = new Dictionary(); + + public void AddDbTable(DefTable table) + { + if (!name2DbTables.TryAdd(table.FullName, table)) + { + throw new Exception($"table:{table.FullName} duplicated"); + } + if (!id2DbTables.TryAdd(table.TableUId, table)) + { + throw new Exception($"table:{table.FullName} 与 table:{id2DbTables[table.TableUId].FullName} id:{table.TableUId} duplicated"); + } + } + + + public void Load(Defines defines, RemoteAgent agent) + { + this.Agent = agent; + TopModule = defines.TopModule; + + + foreach (var c in defines.Consts) + { + AddType(new DefConst(c)); + } + + foreach (var e in defines.Enums) + { + AddType(new DefEnum(e)); + } + + foreach (var b in defines.Beans) + { + AddType(new DefBean(b)); + } + + foreach (var p in defines.DbTables) + { + AddType(new DefTable(p)); + } + + foreach (var type in Types.Values) + { + type.AssemblyBase = this; + } + + foreach (var type in Types.Values) + { + try + { + s_logger.Trace("precompile type:{0} begin", type.FullName); + type.PreCompile(); + s_logger.Trace("precompile type:{0} end", type.FullName); + } + catch (Exception) + { + agent.Error("precompile type:{0} error", type.FullName); + throw; + } + } + foreach (var type in Types.Values) + { + try + { + s_logger.Trace("compile type:{0} begin", type.FullName); + type.Compile(); + s_logger.Trace("compile type:{0} end", type.FullName); + } + catch (Exception) + { + agent.Error("compile type:{0} error", type.FullName); + s_logger.Error("compile type:{0} error", type.FullName); + throw; + } + } + foreach (var type in Types.Values) + { + try + { + s_logger.Trace("post compile type:{0} begin", type.FullName); + type.PostCompile(); + s_logger.Trace("post compile type:{0} end", type.FullName); + } + catch (Exception) + { + agent.Error("post compile type:{0} error", type.FullName); + s_logger.Error("post compile type:{0} error", type.FullName); + throw; + } + } + } + + + } +} diff --git a/src/Luban.Job.Db/Source/Defs/DefBean.cs b/src/Luban.Job.Db/Source/Defs/DefBean.cs new file mode 100644 index 0000000..e2717c7 --- /dev/null +++ b/src/Luban.Job.Db/Source/Defs/DefBean.cs @@ -0,0 +1,182 @@ +using Luban.Job.Common.RawDefs; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Luban.Job.Db.Defs +{ + class DefBean : DbDefTypeBase + { + public const string TYPE_NAME_KEY = "__type__"; + + public bool IsBean => true; + + public string Parent { get; } + + public bool IsValueType { get; } + + public bool IsMultiRow { get; set; } + + public DefBean ParentDefType { get; protected set; } + + public DefBean RootDefType => this.ParentDefType == null ? this : this.ParentDefType.RootDefType; + + public bool IsSerializeCompatible { get; } + + public List Children { get; private set; } + + public List HierarchyNotAbstractChildren { get; private set; } + + public bool IsNotAbstractType => Children == null; + + public bool IsAbstractType => Children != null; + + public List HierarchyFields { get; private set; } = new List(); + + public List Fields { get; } = new List(); + + public string CsClassModifier => IsAbstractType ? "abstract" : "sealed"; + + public string CsMethodModifier => ParentDefType != null ? "override" : (IsAbstractType ? "virtual" : ""); + + public DefBean(Bean b) + { + Name = b.Name; + Namespace = b.Namespace; + Parent = b.Parent; + Id = b.TypeId; + IsValueType = b.IsValueType; + foreach (var field in b.Fields) + { + Fields.Add(new DefField(this, field, 0)); + } + } + + private void CollectHierarchyNotAbstractChildren(List children) + { + if (IsAbstractType) + { + foreach (var c in Children) + { + c.CollectHierarchyNotAbstractChildren(children); + } + } + else + { + children.Add(this); + } + } + + internal DefBean GetNotAbstractChildType(string typeNameOrAliasName) + { + if (string.IsNullOrWhiteSpace(typeNameOrAliasName)) + { + return null; + } + foreach (var c in HierarchyNotAbstractChildren) + { + if (c.Name == typeNameOrAliasName) + { + return c; + } + } + return null; + } + + internal DefField GetField(string index) + { + return HierarchyFields.Where(f => f.Name == index).FirstOrDefault(); + } + + internal bool TryGetField(string index, out DefField field, out int fieldIndexId) + { + for (int i = 0; i < HierarchyFields.Count; i++) + { + if (HierarchyFields[i].Name == index) + { + field = HierarchyFields[i]; + fieldIndexId = i; + return true; + } + } + field = null; + fieldIndexId = 0; + return false; + } + + private void CollectHierarchyFields(List fields) + { + if (ParentDefType != null) + { + ParentDefType.CollectHierarchyFields(fields); + } + fields.AddRange(Fields); + } + + public override void PreCompile() + { + var agent = AssemblyBase.Agent; + agent.Trace("compile bean module:{0} name:{1} begin", Namespace, Name); + if (!string.IsNullOrEmpty(Parent)) + { + if ((ParentDefType = (DefBean)Assembly.GetDefType(Namespace, Parent)) == null) + { + throw new Exception($"bean:{FullName} parent:{Parent} not exist"); + } + if (ParentDefType.Children == null) + { + ParentDefType.Children = new List(); + } + ParentDefType.Children.Add(this); + } + + CollectHierarchyFields(HierarchyFields); + } + + public override void Compile() + { + var agent = AssemblyBase.Agent; + var cs = new List(); + if (Children != null) + { + CollectHierarchyNotAbstractChildren(cs); + } + HierarchyNotAbstractChildren = cs; + + + var ids = new HashSet(); + foreach (var c in cs) + { + if (c.Id == 0) + { + throw new Exception($"bean:{FullName} is child of dynamic type. beanid:{Id} can't be 0!"); + } + if (!ids.Add(c.Id)) + { + throw new Exception($"bean:{c.FullName} beanid:{c.Id} duplicate!"); + } + } + + DefField.CompileFields(this, HierarchyFields, true); + if (IsValueType && HierarchyFields.Any(f => f.CType.NeedSetChildrenRoot())) + { + foreach (var f in Fields) + { + if (f.CType.NeedSetChildrenRoot()) + { + throw new Exception($"bean:{FullName} value type field:{f.Name} must be primitive type"); + } + } + + } + } + + public override void PostCompile() + { + foreach (var field in HierarchyFields) + { + field.PostCompile(); + } + } + } +} diff --git a/src/Luban.Job.Db/Source/Defs/DefField.cs b/src/Luban.Job.Db/Source/Defs/DefField.cs new file mode 100644 index 0000000..f545d04 --- /dev/null +++ b/src/Luban.Job.Db/Source/Defs/DefField.cs @@ -0,0 +1,15 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Common.RawDefs; + +namespace Luban.Job.Db.Defs +{ + class DefField : DefFieldBase + { + public DefAssembly Assembly => (DefAssembly)HostType.AssemblyBase; + + public DefField(DbDefTypeBase host, Field f, int idOffset) : base(host, f, idOffset) + { + + } + } +} diff --git a/src/Luban.Job.Db/Source/Defs/DefTable.cs b/src/Luban.Job.Db/Source/Defs/DefTable.cs new file mode 100644 index 0000000..c3df85f --- /dev/null +++ b/src/Luban.Job.Db/Source/Defs/DefTable.cs @@ -0,0 +1,52 @@ +using Luban.Job.Common.Types; +using Luban.Job.Db.RawDefs; +using System; + +namespace Luban.Job.Db.Defs +{ + class DefTable : DbDefTypeBase + { + public DefTable(Table b) + { + Name = b.Name; + Namespace = b.Namespace; + TableUId = b.Id; + KeyType = b.KeyType; + ValueType = b.ValueType; + IsPersistent = b.IsPersistent; + } + + public string KeyType { get; } + + public string ValueType { get; } + + public bool IsPersistent { get; } + + public TType KeyTType { get; private set; } + + public TBean ValueTType { get; private set; } + + public int TableUId { get; set; } + + public string InternalTableType => "_" + Name; + + //public string BaseTableType => KeyTType.GetDbCsBaseTableType(KeyTType, ValueTType); + + public override void Compile() + { + var ass = Assembly; + + ass.AddDbTable(this); + + if ((KeyTType = ass.CreateType(Namespace, KeyType)) == null) + { + throw new Exception($"table:{FullName} key:{KeyType} 类型不合法"); + } + + if ((ValueTType = (TBean)ass.CreateType(Namespace, ValueType)) == null) + { + throw new Exception($"table:{FullName} value:{ValueType} 类型不合法"); + } + } + } +} diff --git a/src/Luban.Job.Db/Source/Generate/CsRender.cs b/src/Luban.Job.Db/Source/Generate/CsRender.cs new file mode 100644 index 0000000..29a390d --- /dev/null +++ b/src/Luban.Job.Db/Source/Generate/CsRender.cs @@ -0,0 +1,357 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Common.Utils; +using Luban.Job.Db.Defs; +using Scriban; +using System; +using System.Collections.Generic; + +namespace Luban.Job.Db.Generate +{ + class CsRender + { + public string RenderAny(object o) + { + switch (o) + { + case DefConst c: return Render(c); + case DefEnum e: return Render(e); + case DefBean b: return Render(b); + case DefTable p: return Render(p); + default: throw new Exception($"unknown render type:{o}"); + } + } + + public string Render(DefConst c) + { + return RenderUtil.RenderCsConstClass(c); + } + + public string Render(DefEnum e) + { + return RenderUtil.RenderCsEnumClass(e); + } + + [ThreadStatic] + private static Template t_beanRender; + public string Render(DefBean b) + { + var template = t_beanRender ??= Template.Parse(@" +using Bright.Serialization; + +namespace {{namespace_with_top_module}} +{ + +{{if !is_value_type}} +public {{cs_class_modifier}} class {{name}} : {{if parent_def_type}} {{parent}} {{else}} Bright.Transaction.BeanBase {{end}} +{ + {{- for field in fields }} + {{if is_abstract_type}}protected{{else}}private{{end}} {{field.ctype.db_cs_define_type}} {{field.internal_name}}; + {{-end}} + + public {{name}}() + { + {{- for field in fields }} + {{if field.ctype.need_init}}{{field.db_cs_init_field}} {{end}} + {{end}} + } + + {{- for field in fields }} + {{if field.ctype.has_setter}} + + private sealed class {{field.log_type}} : Bright.Transaction.FieldLogger<{{name}}, {{field.ctype.db_cs_define_type}}> + { + public {{field.log_type}}({{name}} self, {{field.ctype.db_cs_define_type}} value) : base(self, value) { } + + public override long FieldId => host._objectId_ + {{field.id}}; + + public override void Commit() { this.host.{{field.internal_name}} = this.Value; } + + + public override void WriteBlob(ByteBuf _buf) + { + _buf.WriteInt(FieldTag.{{field.ctype.tag_name}}); + {{field.db_write_blob}} + } + } + + public {{field.ctype.db_cs_define_type}} {{field.public_name}} + { + get + { + if (this.InitedObjectId) + { + var txn = Bright.Transaction.TransactionContext.ThreadStaticTxn; + if (txn == null) return {{field.internal_name}}; + var log = ({{field.log_type}})txn.GetField(_objectId_ + {{field.id}}); + return log != null ? log.Value : {{field.internal_name}}; + } + else + { + return {{field.internal_name}}; + } + } + set + { + {{if db_field_cannot_null}}if (value == null) throw new ArgumentNullException();{{end}} + if (this.InitedObjectId) + { + var txn = Bright.Transaction.TransactionContext.ThreadStaticTxn; + txn.PutField(_objectId_ + {{field.id}}, new {{field.log_type}}(this, value)); + {{-if field.ctype.need_set_children_root}} + value?.InitRoot(GetRoot()); + {{end}} + } + else + { + {{field.internal_name}} = value; + } + } + } + {{else}} + + {{if field.ctype.is_collection}} + + private class {{field.log_type}} : {{field.ctype.db_cs_define_type}}.Log + { + private readonly {{name}} host; + public {{field.log_type}}({{name}} host, {{field.ctype.immutable_type}} value) : base(value) { this.host = host; } + + public override long FieldId => host._objectId_ + {{field.id}}; + + public override Bright.Transaction.BeanBase Host => host; + + public override void Commit() + { + Commit(host.{{field.internal_name}}); + } + + public override void WriteBlob(ByteBuf _buf) + { + _buf.WriteInt(FieldTag.{{field.ctype.tag_name}}); + {{field.db_write_blob}} + } + } + {{end}} + + public {{field.ctype.db_cs_define_type}} {{field.public_name}} => {{field.internal_name}}; + {{end}} + {{-end}} + + {{if is_abstract_type}} + public static void Serialize{{name}}(ByteBuf _buf, {{name}} x) + { + if (x == null) { _buf.WriteInt(0); return; } + _buf.WriteInt(x.GetTypeId()); + x.Serialize(_buf); + } + + public static {{name}} Deserialize{{name}}(ByteBuf _buf) + { + {{name}} x; + switch (_buf.ReadInt()) + { + case 0 : return null; + {{- for child in hierarchy_not_abstract_children}} + case {{child.full_name}}.ID: x = new {{child.full_name}}(); break; + {{-end}} + default: throw new SerializationException(); + } + x.Deserialize(_buf); + return x; + } + {{else}} + public override void Serialize(ByteBuf _buf) + { + _buf.WriteLong(_objectId_); + {{- for field in hierarchy_fields }} + { _buf.WriteInt(FieldTag.{{field.ctype.tag_name}} | ({{field.id}} << FieldTag.TAG_SHIFT)); {{field.db_serialize_compatible}} } + {{-end}} + } + + public override void Deserialize(ByteBuf _buf) + { + _objectId_ = _buf.ReadLong(); + while(_buf.NotEmpty) + { + int _tag_ = _buf.ReadInt(); + switch (_tag_) + { + {{- for field in hierarchy_fields }} + case FieldTag.{{field.ctype.tag_name}} | ({{field.id}} << FieldTag.TAG_SHIFT) : { {{field.db_deserialize_compatible}} break; } + {{-end}} + default: { _buf.SkipUnknownField(_tag_); break; } + } + } + } + + public const int ID = {{id}}; + public override int GetTypeId() => ID; + + {{end}} + + protected override void InitChildrenRoot(Bright.Transaction.TKey root) + { + {{- for field in hierarchy_fields }} + {{if field.ctype.need_set_children_root}}this.{{field.internal_name}}?.InitRoot(root);{{end}} + {{-end}} + } + + public override string ToString() + { + return ""{{full_name}}{ "" + {{- for field in hierarchy_fields }} + + ""{{field.public_name}}:"" + {{field.db_cs_to_string}} + "","" + {{-end}} + + ""}""; + } +} + +{{else}} + public struct {{name}} : ISerializable +{ + {{- for field in fields }} + private {{field.ctype.db_cs_define_type}} {{field.internal_name}}; + {{-end}} + + {{- for field in fields }} + public {{field.ctype.db_cs_define_type}} {{field.public_name}} {get => {{field.internal_name}}; set => {{field.internal_name}} = value;} + {{-end}} + + public void Serialize(ByteBuf _buf) + { + _buf.WriteSize({{hierarchy_fields.size}}); + {{- for field in hierarchy_fields }} + { _buf.WriteInt(FieldTag.{{field.ctype.tag_name}} | ({{field.id}} << FieldTag.TAG_SHIFT)); {{field.db_serialize_compatible}} } + {{-end}} + } + + public void Deserialize(ByteBuf _buf) + { + for (int _var_num_ = _buf.ReadSize(); -- _var_num_ >= 0;) + { + int _tag_ = _buf.ReadInt(); + switch (_tag_) + { + {{- for field in hierarchy_fields }} + case FieldTag.{{field.ctype.tag_name}} | ({{field.id}} << FieldTag.TAG_SHIFT) : { {{field.db_deserialize_compatible}} break; } + {{-end}} + default: { _buf.SkipUnknownField(_tag_); break; } + } + } + } + + public int GetTypeId() => 0; + + public override string ToString() + { + return ""{{full_name}}{ "" + {{- for field in hierarchy_fields }} + + ""{{field.public_name}}:"" + {{field.db_cs_to_string}} + "","" + {{-end}} + + ""}""; + } +} + +{{end}} + +} +"); + var result = template.Render(b); + return result; + } + + [ThreadStatic] + private static Template t_tableRender; + public string Render(DefTable p) + { + var template = t_tableRender ??= Template.Parse(@" +using System; +using System.Threading.Tasks; + +namespace {{namespace_with_top_module}} +{ + +public sealed class {{name}} +{ + public static {{base_table_type}} Table { get; } = new {{internal_table_type}}({{table_uid}}); + + private class {{internal_table_type}} : {{base_table_type}} + { + public {{internal_table_type}}(int tableId) : base(tableId) + { + + } + }; + + public static {{value_ttype.cs_define_type}} Get({{key_ttype.cs_define_type}} key) + { + return Table.Get(key); + } + + public static {{value_ttype.cs_define_type}} CreateIfNotExist({{key_ttype.cs_define_type}} key) + { + return Table.CreateIfNotExist(key); + } + + public static void Insert({{key_ttype.cs_define_type}} key, {{value_ttype.cs_define_type}} value) + { + Table.Insert(key, value); + } + + public static void Remove({{key_ttype.cs_define_type}} key) + { + Table.Remove(key); + } + + public static void Put({{key_ttype.cs_define_type}} key, {{value_ttype.cs_define_type}} value) + { + Table.Put(key, value); + } + + public static {{value_ttype.cs_define_type}} Select({{key_ttype.cs_define_type}} key) + { + return Table.Select(key); + } +} +} + +"); + var result = template.Render(p); + + return result; + } + + [ThreadStatic] + private static Template t_stubRender; + public string RenderTables(string name, string module, List tables) + { + var template = t_stubRender ??= Template.Parse(@" +using Bright.Serialization; + +namespace {{namespace}} +{ + +public static class {{name}} +{ + public static System.Collections.Generic.List TableList { get; } = new System.Collections.Generic.List + { + {{- for table in tables }} + {{table.full_name}}.Table, + {{-end}} + }; +} + +} + +"); + var result = template.Render(new + { + Name = name, + Namespace = module, + Tables = tables, + }); + + return result; + } + } +} diff --git a/src/Luban.Job.Db/Source/JobController.cs b/src/Luban.Job.Db/Source/JobController.cs new file mode 100644 index 0000000..71c29f9 --- /dev/null +++ b/src/Luban.Job.Db/Source/JobController.cs @@ -0,0 +1,18 @@ +using Luban.Common.Protos; +using Luban.Server.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Luban.Job.Db +{ + public class JobController : IJobController + { + public Task GenAsync(RemoteAgent agent, GenJob rpc) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Luban.Job.Db/Source/Program.cs b/src/Luban.Job.Db/Source/Program.cs new file mode 100644 index 0000000..27f0d46 --- /dev/null +++ b/src/Luban.Job.Db/Source/Program.cs @@ -0,0 +1,119 @@ +//using Bright.Common; +//using CommandLine; +//using CommandLine.Text; +//using Gen.Client.Common.Net; +//using Gen.Client.Common.Utils; +//using Gen.Db.Common.RawDefs; +//using Luban.Job.Common.Net; +//using Luban.Job.Common.Utils; +//using System; + +//namespace Luban.Job.Db.Client +//{ +// public class CommandLineOptions +// { +// [Option('h', "host", Required = true, HelpText = "gen server host")] +// public string Host { get; set; } + +// [Option('p', "port", Required = false, HelpText = "gen server port")] +// public int Port { get; set; } = 8899; + +// [Option('d', "define", Required = true, HelpText = "define file")] +// public string DefineFile { get; set; } + +// [Option('c', "outputcodedir", Required = true, HelpText = "output code directory")] +// public string OutputCodeDir { get; set; } + +// [Option('l', "language", Required = true, HelpText = "code language. only support cs currently")] +// public string Languange { get; set; } = "cs"; + +// [Option('v', "verbose", Required = false, HelpText = "verbose output")] +// public bool Verbose { get; set; } + +// [Option("cachemetainfofile", Required = false, HelpText = "cache meta info file")] +// public string CacheMetaInfoFile { get; set; } = ".cache.meta"; +// } + +// class Program +// { +// private static NLog.Logger s_logger; + +// private static CommandLineOptions _options; + +// static void Main(string[] args) +// { +// var parseResult = Parser.Default.ParseArguments(args); + +// parseResult.WithNotParsed(errs => +// { +// Environment.Exit(1); +// }); + +// parseResult.WithParsed(opts => +// { +// _options = opts; +// }); + +// LogUtil.InitSimpleNLogConfigure(NLog.LogLevel.Info); + +// s_logger = NLog.LogManager.GetCurrentClassLogger(); + +// int exitCode = 0; +// try +// { +// var timer = new ProfileTimer(); +// timer.StartPhase("total"); + +// long beginTime = Bright.Time.TimeUtil.NowMillis; + +// timer.StartPhase("load cache meta file"); +// CacheMetaManager.Ins.Load(_options.CacheMetaInfoFile); +// timer.EndPhaseAndLog(); + +// RpcManager.Ins.Start(); +// var conn = GenClient.Ins.Start(_options.Host, _options.Port, ProtocolStub.Factories, _options.Verbose); +// conn.Wait(); + +// timer.StartPhase("load defines"); +// var loader = new DbDefLoader(); +// loader.Load(_options.DefineFile); +// timer.EndPhaseAndLog(); + +// timer.StartPhase("call GenDb"); +// string outputDir = _options.OutputCodeDir; + +// var rpc = new GenDb(); +// var res = rpc.Call(GenClient.Ins.Session, new GenDbArg() +// { +// Define = loader.BuildDefines(), +// OutputCodeRelatePath = outputDir, + +// }).Result; +// timer.EndPhaseAndLog(); + +// if (res.OK) +// { +// timer.StartPhase("fetch generated files"); +// DownloadFileUtil.DownloadGeneratedFiles(outputDir, res.NewCodeFiles).Wait(); +// timer.EndPhaseAndLog(); + +// CacheMetaManager.Ins.Save(); +// timer.EndPhaseAndLog(); +// s_logger.Info("==== run succ ===="); +// } +// else +// { +// timer.EndPhaseAndLog(); +// s_logger.Error("==== run fail ===="); +// exitCode = 1; +// } +// } +// catch (Exception e) +// { +// s_logger.Error(e, "==== run fail ===="); +// exitCode = 1; +// } +// Environment.Exit(exitCode); +// } +// } +//} diff --git a/src/Luban.Job.Db/Source/RawDefs/Defines.cs b/src/Luban.Job.Db/Source/RawDefs/Defines.cs new file mode 100644 index 0000000..cb5b7d7 --- /dev/null +++ b/src/Luban.Job.Db/Source/RawDefs/Defines.cs @@ -0,0 +1,20 @@ +using Luban.Job.Common.RawDefs; +using System.Collections.Generic; + +namespace Luban.Job.Db.RawDefs +{ + public class Defines + { + public string Language { get; set; } = "cs"; + + public string TopModule { get; set; } = ""; + + public List Beans { get; set; } = new List(); + + public List Consts { get; set; } = new List(); + + public List Enums { get; set; } = new List(); + + public List
DbTables { get; set; } = new List
(); + } +} diff --git a/src/Luban.Job.Db/Source/RawDefs/Table.cs b/src/Luban.Job.Db/Source/RawDefs/Table.cs new file mode 100644 index 0000000..681d164 --- /dev/null +++ b/src/Luban.Job.Db/Source/RawDefs/Table.cs @@ -0,0 +1,17 @@ +namespace Luban.Job.Db.RawDefs +{ + public class Table + { + public string Namespace { get; set; } + + public string Name { get; set; } + + public int Id { get; set; } + + public string KeyType { get; set; } + + public string ValueType { get; set; } + + public bool IsPersistent { get; set; } + } +} diff --git a/src/Luban.Job.Db/Source/RpcController.cs b/src/Luban.Job.Db/Source/RpcController.cs new file mode 100644 index 0000000..d2befb6 --- /dev/null +++ b/src/Luban.Job.Db/Source/RpcController.cs @@ -0,0 +1,623 @@ +namespace Luban.Job.Db +{ + class RpcController + { + + //private void LogException(IContext ctx, Exception e) + //{ + // if (e is AggregateException ae) + // { + // foreach (var ie in ae.InnerExceptions) + // { + // LogException(ctx, ie); + // } + // } + // else + // { + + // s_logger.Error(e, "发生异常"); + // ctx.Error(e, " {0} \n ", e.StackTrace); + // } + //} + + //private bool ValidateDataType(string outputDataType) + //{ + // switch (outputDataType) + // { + // case "bin": + // case "cbin": + // case "json": return true; + // default: return false; + // } + //} + + //private void OnGenDb(Session session, GenDb proto) + //{ + // var timer = new ProfileTimer(); + + // timer.StartPhase("生成代码"); + + // var res = new GenDbRes(); + + // string relatePath = proto.Arg.OutputCodeRelatePath; + + // var ass = new DefAssembly(); + // var ctx = new SessionContext(session, proto.Arg.Verbose); + // try + // { + // var genCodeTasks = new List(); + // var outputFiles = new ConcurrentBag(); + + // ass.Load(EJobType.DB, proto.Arg.Define, ctx); + // var render = new Generate.Db.CsRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = "Tables"; + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTables(name, module, ass.Types.Values.Where(t => t is BTable).ToList()), "cs"); + // var file = FileUtil.GetCsDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // Task.WhenAll(genCodeTasks).Wait(); + // ctx.Info(timer.EndPhaseAndLogToString()); + + // res.NewCodeFiles = outputFiles.ToList(); + // res.OK = true; + // } + // catch (Exception e) + // { + // res.OK = false; + // LogException(ctx, e); + // } + + // proto.ReturnResult(session, res); + //} + + //private ICsCodeRender CreateCsCodeRender(string outputDataType) + //{ + // switch (outputDataType) + // { + // case "bin": return new AppCsBinCodeRender(); + // case "cbin": return new AppCsCompatibleBinCodeRender(); + // case "json": return new AppCsJsonCodeRender(); + // default: throw new ArgumentException($"not support output data type:{outputDataType}"); + // } + //} + + //private void OnGenCfg(Session session, GenCfg proto) + //{ + // var res = new GenCfgRes(); + + // string lan = proto.Arg.Define.Language; + + // DefAssembly ass = new DefAssembly(); + + // var ctx = new SessionContext(session, proto.Arg.Verbose); + + + // var allJobs = new List(); + + + // try + // { + // string outputDataType = proto.Arg.OutputDataType; + // if (!ValidateDataType(outputDataType)) + // { + // throw new ArgumentException($"unknown outputdatatype:{outputDataType}"); + // } + + // bool exportTestData = proto.Arg.ExportTestData; + + // long genStartTime = TimeUtil.NowMillis; + // var genCodeTasks = new List(); + // var outputCodeFiles = new ConcurrentBag(); + + // ass.Load(EJobType.CONFIG, proto.Arg.Define, ctx); + // EGenTypes genTypes = proto.Arg.GenTypes; + // var targetService = ass.CfgTargetService; + + // List exportTables = ass.Types.Values.Where(t => t is CTable ct && ct.NeedExport).Select(t => (CTable)t).ToList(); + + // if (genTypes.HasFlag(EGenTypes.APP_CODE)) + // { + // var refTypes = new Dictionary(); + // long genCodeStartTime = TimeUtil.NowMillis; + + // foreach (var refType in targetService.Refs) + // { + // if (!ass.Types.ContainsKey(refType)) + // { + // throw new Exception($"service:{targetService.Name} ref:{refType} 类型不存在"); + // } + // if (!refTypes.TryAdd(refType, ass.Types[refType])) + // { + // throw new Exception($"service:{targetService.Name} ref:{refType} 重复引用"); + // } + // } + + // foreach (var table in exportTables) + // { + // refTypes[table.FullName] = table; + // table.ValueTType.Apply(RefTypeVisitor.Ins, refTypes); + // } + + // foreach (var type in ass.Types) + // { + // if (type.Value is DefConst || type.Value is DefEnum) + // { + // refTypes[type.Key] = type.Value; + // } + // } + + // List exportTypes = refTypes.Values.ToList(); + + // switch (lan) + // { + // case "cs": + // { + // ICsCodeRender render = CreateCsCodeRender(outputDataType); + // foreach (var c in exportTypes) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = targetService.Manager; + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderService(name, module, exportTables), "cs"); + // var file = FileUtil.GetCsDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + + // break; + // } + // case "go": + // { + // // + // // TODO? + // // 由于 go 语言不支持类型继承 + // // go 不支持 table.value_type 为多态的表 + // // + // // + // var render = new AppGoCodeRender(); + + + // foreach (var c in exportTypes) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "go"); + // var file = FileUtil.GetGoDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = targetService.Manager; + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderService(name, module, exportTables), "go"); + // var file = FileUtil.GetGoDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + + // break; + // } + // case "lua": + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var render = new Generate.Cfg.LuaRender(); + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAll(exportTypes.ToList()), "lua"); + // var file = "CfgTypes.lua"; + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // case "editor_cs": + // { + // var render = new EditorCsRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // break; + // } + // case "editor_cpp": + // { + // var render = new EditorCppRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // break; + // } + // case "editor_ue_cpp": + // { + // var render = new UE4EditorCppRender(); + + // var renderTypes = ass.Types.Values.Where(c => c is DefEnum || c is DefBean).ToList(); + + // foreach (var c in renderTypes) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp"); + // var file = c.UeEditorHeaderFileName; + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + // int TYPE_PER_STUB_FILE = 200; + + // for (int i = 0, n = (renderTypes.Count + TYPE_PER_STUB_FILE - 1) / TYPE_PER_STUB_FILE; i < n; i++) + // { + // int index = i; + // genCodeTasks.Add(Task.Run(() => + // { + // int startIndex = index * TYPE_PER_STUB_FILE; + // var content = RenderUtils.ConcatAutoGenerationHeader( + // render.RenderStub(renderTypes.GetRange(startIndex, Math.Min(TYPE_PER_STUB_FILE, renderTypes.Count - startIndex))), + // "cpp"); + // var file = $"Stub_{index}.cpp"; + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // break; + // } + // case "ue_bp_cpp": + // { + // var render = new UE4BpCppRender(); + // foreach (var c in exportTypes) + // { + // if (c is DefConst || c is CTable) + // { + // continue; + // } + + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp"); + // var file = c.UeBpHeaderFileName; + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + // //{ + // // var module = ass.TopModule; + // // var name = targetService.Manager; + // // var content = render.RenderService(name, module, exportTables); + // // var file = FileUtil.GetCppDefTypeCppFilePath(name); + // // var md5 = GenMd5AndAddCache(file, content); + // // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // //} + // break; + // } + // default: + // { + // throw new Exception($"unknown language:{lan}"); + // } + // } + + + // allJobs.Add(Task.Run(async () => + // { + // await Task.WhenAll(genCodeTasks); + // res.NewAppCodeFiles = outputCodeFiles.ToList(); + // long genCodeEndTime = TimeUtil.NowMillis; + // ctx.Info("====== 生成代码 总共耗时 {0} ms ======", (genCodeEndTime - genCodeStartTime)); + // })); + // } + + // if ((genTypes & (EGenTypes.APP_DATA | EGenTypes.APP_RESOURCE_LIST)) != 0) + // { + // var genDataTasks = new List(); + // var outputDataFiles = new ConcurrentBag(); + // var render = new AppBinaryDataRender(); + // long genDataStartTime = TimeUtil.NowMillis; + + // foreach (CTable c in exportTables) + // { + // genDataTasks.Add(Task.Run(async () => + // { + // long beginTime = TimeUtil.NowMillis; + // await c.Load(session, exportTestData); + // long endTime = TimeUtil.NowMillis; + // if (endTime - beginTime > 100) + // { + // ctx.Info("====== 配置表 {0} 加载耗时 {1} ms ======", c.FullName, (endTime - beginTime)); + // } + // })); + // } + // Task.WaitAll(genDataTasks.ToArray()); + // } + + + // if (genTypes.HasFlag(EGenTypes.APP_DATA)) + // { + // var genDataTasks = new List(); + // var outputDataFiles = new ConcurrentBag(); + // var render = new AppBinaryDataRender(); + // long genDataStartTime = TimeUtil.NowMillis; + + // foreach (CTable c in exportTables) + // { + // genDataTasks.Add(Task.Run(() => + // { + // var content = c.ToOutputData(outputDataType); + // var file = c.OutputDataFile; + // var md5 = GenMd5AndAddCache(file, content); + // outputDataFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + // allJobs.Add(Task.Run(async () => + // { + // await Task.WhenAll(genDataTasks); + // long genDataEndTime = TimeUtil.NowMillis; + // ctx.Info("====== 生成配置数据 总共耗时 {0} ms ======", (genDataEndTime - genDataStartTime)); + // res.NewAppDataFiles = outputDataFiles.ToList(); + + // long verifyStartTime = TimeUtil.NowMillis; + // render.VerifyTables(exportTables); + // res.PathQueries = ass.GetPathQueries(); + + // long verifyEndTime = TimeUtil.NowMillis; + // ctx.Info("====== 校验配置 总共耗时 {0} ms ======", (verifyEndTime - verifyStartTime)); + // })); + // } + + // if (genTypes.HasFlag(EGenTypes.APP_RESOURCE_LIST)) + // { + // var genDataTasks = new List>>(); + // var render = new AppBinaryDataRender(); + // long genDataStartTime = TimeUtil.NowMillis; + + // foreach (CTable c in exportTables) + // { + // genDataTasks.Add(Task.Run(() => + // { + // return c.ExportResourceList(); + // })); + // } + + // allJobs.Add(Task.Run(async () => + // { + // var ress = new HashSet<(string, string)>(10000); + // foreach (var task in genDataTasks) + // { + // foreach (var ri in await task) + // { + // if (ress.Add((ri.Resource, ri.Tag))) + // { + // res.ResourceList.Add(ri); + // } + // } + // } + // long genDataEndTime = TimeUtil.NowMillis; + // ctx.Info("====== 生成导出资源列表 总共耗时 {0} ms ======", (genDataEndTime - genDataStartTime)); + // })); + // } + + // Task.WhenAll(allJobs).Wait(); + + // long genEndTime = TimeUtil.NowMillis; + // ctx.Info("======== 服务器端 总共耗时 {0} ms =======", (genEndTime - genStartTime)); + + // res.OK = true; + // } + // catch (Exception e) + // { + // res.OK = false; + // LogException(ctx, e); + // } + + // proto.ReturnResult(session, res); + //} + + //private void OnGenProto(Session session, GenProto proto) + //{ + // var timer = new ProfileTimer(); + + // timer.StartPhase("服务器生成代码"); + + // var res = new GenProtoRes(); + + // string relatePath = proto.Arg.OutputCodeRelatePath; + + // DefAssembly ass = new DefAssembly(); + // var ctx = new SessionContext(session, proto.Arg.Verbose); + // try + // { + // var genCodeTasks = new List(); + // var outputFiles = new ConcurrentBag(); + + // ass.Load(EJobType.PROTO, proto.Arg.Define, ctx); + // var outputSyncFiles = new ConcurrentBag(); + + // switch (proto.Arg.Define.Language) + // { + // case "cs": + // { + // var render = new CsRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = "ProtocolStub"; + // var content = RenderUtils.ConcatAutoGenerationHeader( + // render.RenderStubs(name, module, + // ass.Types.Values.Where(t => t is PProto).ToList(), + // ass.Types.Values.Where(t => t is PRpc).ToList()), + // "cs"); + // var file = FileUtil.GetCsDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // case "lua": + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var render = new Generate.Proto.LuaRender(); + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTypes(ass.Types.Values.ToList()), "lua"); + // var file = "ProtoTypes.lua"; + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // default: + // { + // throw new Exception($"unknown lan:{proto.Arg.Define.Language}"); + // } + // } + + // Task.WhenAll(genCodeTasks).Wait(); + // res.NewCodeFiles = outputFiles.ToList(); + + // ctx.Info(timer.EndPhaseAndLogToString()); + + // res.OK = true; + // } + // catch (Exception e) + // { + // res.OK = false; + // LogException(ctx, e); + // } + + // proto.ReturnResult(session, res); + //} + + //private void OnGenRep(Session session, GenRep proto) + //{ + // var timer = new ProfileTimer(); + + // timer.StartPhase("服务器生成代码"); + + // var res = new GenRepRes(); + + // string relatePath = proto.Arg.OutputCodeRelatePath; + + // DefAssembly ass = new DefAssembly(); + // var ctx = new SessionContext(session, proto.Arg.Verbose); + // try + // { + // var genCodeTasks = new List(); + // var outputFiles = new ConcurrentBag(); + + // ass.Load(EJobType.REP, proto.Arg.Define, ctx); + // var outputSyncFiles = new ConcurrentBag(); + + // switch (proto.Arg.Define.Language) + // { + // case "cs": + // { + // var render = new Generate.Rep.CsRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = "RepStub"; + // var content = RenderUtils.ConcatAutoGenerationHeader( + // render.RenderStubs(name, module, ass.Types.Values.Where(t => (t is DefActor) || (t is DefComponent)).ToList()), + // "cs"); + // var file = FileUtil.GetCsDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // case "lua": + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var render = new Generate.Rep.LuaRender(); + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTypes(ass.Types.Values.ToList()), "lua"); + // var file = "RepTypes.lua"; + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // default: + // { + // throw new Exception($"unknown lan:{proto.Arg.Define.Language}"); + // } + // } + + // Task.WhenAll(genCodeTasks).Wait(); + // res.NewCodeFiles = outputFiles.ToList(); + + // ctx.Info(timer.EndPhaseAndLogToString()); + + // res.OK = true; + // } + // catch (Exception e) + // { + // res.OK = false; + // LogException(ctx, e); + // } + + // proto.ReturnResult(session, res); + //} + } +} diff --git a/src/Luban.Job.Db/Source/TTypeExtensions.cs b/src/Luban.Job.Db/Source/TTypeExtensions.cs new file mode 100644 index 0000000..d0a982e --- /dev/null +++ b/src/Luban.Job.Db/Source/TTypeExtensions.cs @@ -0,0 +1,18 @@ +using Luban.Job.Common.Types; +using System; + +namespace Luban.Job.Db +{ + static class TTypeExtensions + { + public static string DbCsDefineType(this TType type) + { + throw new NotImplementedException(); + } + + public static bool NeedSetChildrenRoot(this TType type) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Luban.Job.Db/Source/TypeVisitors/DbCsInitFieldVisitor.cs b/src/Luban.Job.Db/Source/TypeVisitors/DbCsInitFieldVisitor.cs new file mode 100644 index 0000000..7f1e9b5 --- /dev/null +++ b/src/Luban.Job.Db/Source/TypeVisitors/DbCsInitFieldVisitor.cs @@ -0,0 +1,133 @@ +using Luban.Job.Common.Types; +using Luban.Job.Common.TypeVisitors; +using System; + +namespace Luban.Job.Db.TypeVisitors +{ + class DbCsInitFieldVisitor : ITypeFuncVisitor + { + public static DbCsInitFieldVisitor Ins { get; } = new DbCsInitFieldVisitor(); + + public string Accept(TBool type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TByte type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TShort type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TFshort type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TInt type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TFint type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TLong type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TFlong type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TFloat type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TDouble type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TEnum type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TString type, string fieldName, string logType) + { + return $"{fieldName} = \"\";"; + } + + public string Accept(TBytes type, string fieldName, string logType) + { + return $"{fieldName} = System.Array.Empty();"; + } + + public string Accept(TText type, string fieldName, string logType) + { + throw new NotSupportedException(); + } + + public string Accept(TBean type, string fieldName, string logType) + { + if (type.Bean.IsAbstractType) + { + return $"{fieldName} = default;"; + } + else + { + return $"{fieldName} = new {type.DbCsDefineType()}();"; + } + } + + public string Accept(TArray type, string fieldName, string logType) + { + throw new NotSupportedException(); + } + + public string Accept(TList type, string fieldName, string logType) + { + return $"{fieldName} = new {type.DbCsDefineType()}(_v => new {logType}(this, _v));"; + } + + public string Accept(TSet type, string fieldName, string logType) + { + return $"{fieldName} = new {type.DbCsDefineType()}(_v => new {logType}(this, _v));"; + } + + public string Accept(TMap type, string fieldName, string logType) + { + return $"{fieldName} = new {type.DbCsDefineType()}(_v => new {logType}(this, _v));"; + } + + public string Accept(TVector2 type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TVector3 type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TVector4 type, string fieldName, string logType) + { + return $"{fieldName} = default;"; + } + + public string Accept(TDateTime type, string x, string y) + { + throw new NotSupportedException(); + } + } +} diff --git a/src/Luban.Job.Db/Source/TypeVisitors/DbWriteBlob.cs b/src/Luban.Job.Db/Source/TypeVisitors/DbWriteBlob.cs new file mode 100644 index 0000000..eda6716 --- /dev/null +++ b/src/Luban.Job.Db/Source/TypeVisitors/DbWriteBlob.cs @@ -0,0 +1,136 @@ +using Luban.Job.Common.Types; +using Luban.Job.Common.TypeVisitors; +using System; + +namespace Luban.Job.Db.TypeVisitors +{ + class DbWriteBlob : ITypeFuncVisitor + { + public static DbWriteBlob Ins { get; } = new DbWriteBlob(); + + public string Accept(TBool type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteBool({fieldName});"; + } + + public string Accept(TByte type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteByte({fieldName});"; + } + + public string Accept(TShort type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteShort({fieldName});"; + } + + public string Accept(TFshort type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteFshort({fieldName});"; + } + + public string Accept(TInt type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteInt({fieldName});"; + } + + public string Accept(TFint type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteFint({fieldName});"; + } + + public string Accept(TLong type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteLong({fieldName});"; + } + + public string Accept(TFlong type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteFlong({fieldName});"; + } + + public string Accept(TFloat type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteFloat({fieldName});"; + } + + public string Accept(TDouble type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteDouble({fieldName});"; + } + + public string Accept(TEnum type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteInt((int){fieldName});"; + } + + public string Accept(TString type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteString({fieldName});"; + } + + public string Accept(TBytes type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteBytes({fieldName});"; + } + + public string Accept(TText type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteString({fieldName});"; + } + + public string Accept(TBean type, string byteBufName, string fieldName) + { + var bean = type.Bean; + if (bean.IsNotAbstractType) + { + + return $"{fieldName}.Serialize({byteBufName});"; + } + else + { + return $"{bean.FullName}.Serialize{bean.Name}({byteBufName}, {fieldName});"; + } + } + + public string Accept(TArray type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteSize({fieldName}.Length); foreach(var _e in {fieldName}) {{ {type.ElementType.Apply(this, byteBufName, "_e")} }}"; + } + + public string Accept(TList type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteSize({fieldName}.Count); foreach(var _e in {fieldName}) {{ {type.ElementType.Apply(this, byteBufName, "_e")} }}"; + } + + public string Accept(TSet type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteSize({fieldName}.Count); foreach(var _e in {fieldName}) {{ {type.ElementType.Apply(this, byteBufName, "_e")} }}"; + } + + public string Accept(TMap type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteSize({fieldName}.Count); foreach(var _e in {fieldName}) {{ {type.KeyType.Apply(this, byteBufName, "_e.Key")} {type.ValueType.Apply(this, byteBufName, "_e.Value")}}}"; + + } + + public string Accept(TVector2 type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteVector2({fieldName});"; + } + + public string Accept(TVector3 type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteVector3({fieldName});"; + } + + public string Accept(TVector4 type, string byteBufName, string fieldName) + { + return $"{byteBufName}.WriteVector4({fieldName});"; + } + + public string Accept(TDateTime type, string x, string y) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Luban.Job.Db/Source/TypeVisitors/ImmutableTypeName.cs b/src/Luban.Job.Db/Source/TypeVisitors/ImmutableTypeName.cs new file mode 100644 index 0000000..144ccb6 --- /dev/null +++ b/src/Luban.Job.Db/Source/TypeVisitors/ImmutableTypeName.cs @@ -0,0 +1,125 @@ +using Luban.Job.Common.Types; +using Luban.Job.Common.TypeVisitors; + +namespace Luban.Job.Db.TypeVisitors +{ + class ImmutableTypeName : ITypeFuncVisitor + { + public static ImmutableTypeName Ins { get; } = new ImmutableTypeName(); + + public string Accept(TBool type) + { + return ""; + } + + public string Accept(TByte type) + { + return ""; + } + + public string Accept(TShort type) + { + return ""; + } + + public string Accept(TFshort type) + { + return ""; + } + + public string Accept(TInt type) + { + return ""; + } + + public string Accept(TFint type) + { + return ""; + } + + public string Accept(TLong type) + { + return ""; + } + + public string Accept(TFlong type) + { + return ""; + } + + public string Accept(TFloat type) + { + return ""; + } + + public string Accept(TDouble type) + { + return ""; + } + + public string Accept(TEnum type) + { + return ""; + } + + public string Accept(TString type) + { + return ""; + } + + public string Accept(TBytes type) + { + return ""; + } + + public string Accept(TText type) + { + return ""; + } + + public string Accept(TBean type) + { + return ""; + } + + public string Accept(TArray type) + { + return ""; + } + + public string Accept(TList type) + { + return $"System.Collections.Immutable.ImmutableList<{type.ElementType.DbCsDefineType()}>"; + } + + public string Accept(TSet type) + { + return $"System.Collections.Immutable.ImmutableHashSet<{type.ElementType.DbCsDefineType()}>"; + } + + public string Accept(TMap type) + { + return $"System.Collections.Immutable.ImmutableDictionary<{type.KeyType.DbCsDefineType()}, {type.ValueType.DbCsDefineType()}>"; + } + + public string Accept(TVector2 type) + { + return ""; + } + + public string Accept(TVector3 type) + { + return ""; + } + + public string Accept(TVector4 type) + { + return ""; + } + + public string Accept(TDateTime type) + { + return ""; + } + } +} diff --git a/src/Luban.Job.Proto/Luban.Job.Proto.csproj b/src/Luban.Job.Proto/Luban.Job.Proto.csproj new file mode 100644 index 0000000..c23729e --- /dev/null +++ b/src/Luban.Job.Proto/Luban.Job.Proto.csproj @@ -0,0 +1,18 @@ + + + + Library + net5.0 + + + + + + + + + + + + + diff --git a/src/Luban.Job.Proto/Source/Defs/DefAssembly.cs b/src/Luban.Job.Proto/Source/Defs/DefAssembly.cs new file mode 100644 index 0000000..9c161f9 --- /dev/null +++ b/src/Luban.Job.Proto/Source/Defs/DefAssembly.cs @@ -0,0 +1,111 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Proto.RawDefs; +using Luban.Server.Common; +using System; +using System.Collections.Generic; + +namespace Luban.Job.Proto.Defs +{ + + class DefAssembly : DefAssemblyBase + { + private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger(); + + private readonly Dictionary id2Protos = new Dictionary(); + + public DefTypeBase GetProto(int id) + { + return id2Protos.TryGetValue(id, out var p) ? p : null; + } + + public void AddProto(DefTypeBase proto) + { + if (!id2Protos.TryAdd(proto.Id, proto)) + { + throw new Exception($"proto:{proto.FullName} id:{proto.Id} duplicated with {id2Protos[proto.Id].FullName}"); + } + } + + + public void Load(Defines defines, RemoteAgent agent) + { + this.Agent = agent; + TopModule = defines.TopModule; + + foreach (var c in defines.Consts) + { + AddType(new DefConst(c)); + } + + foreach (var e in defines.Enums) + { + AddType(new DefEnum(e)); + } + + foreach (var b in defines.Beans) + { + AddType(new DefBean(b)); + } + + foreach (var p in defines.Protos) + { + AddType(new DefProto(p)); + } + foreach (var r in defines.Rpcs) + { + AddType(new DefRpc(r)); + } + + foreach (var type in Types.Values) + { + type.AssemblyBase = this; + } + + foreach (var type in Types.Values) + { + try + { + s_logger.Trace("precompile type:{0} begin", type.FullName); + type.PreCompile(); + s_logger.Trace("precompile type:{0} end", type.FullName); + } + catch (Exception) + { + agent.Error("precompile type:{0} error", type.FullName); + throw; + } + } + foreach (var type in Types.Values) + { + try + { + s_logger.Trace("compile type:{0} begin", type.FullName); + type.Compile(); + s_logger.Trace("compile type:{0} end", type.FullName); + } + catch (Exception) + { + agent.Error("compile type:{0} error", type.FullName); + s_logger.Error("compile type:{0} error", type.FullName); + throw; + } + } + foreach (var type in Types.Values) + { + try + { + s_logger.Trace("post compile type:{0} begin", type.FullName); + type.PostCompile(); + s_logger.Trace("post compile type:{0} end", type.FullName); + } + catch (Exception) + { + agent.Error("post compile type:{0} error", type.FullName); + s_logger.Error("post compile type:{0} error", type.FullName); + throw; + } + } + + } + } +} diff --git a/src/Luban.Job.Proto/Source/Defs/DefBean.cs b/src/Luban.Job.Proto/Source/Defs/DefBean.cs new file mode 100644 index 0000000..a7fe8cb --- /dev/null +++ b/src/Luban.Job.Proto/Source/Defs/DefBean.cs @@ -0,0 +1,18 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Common.RawDefs; + +namespace Luban.Job.Proto.Defs +{ + class DefBean : DefBeanBase + { + public DefBean(Bean b) : base(b) + { + + } + + protected override DefFieldBase CreateField(Field f, int idOffset) + { + return new DefField(this, f, idOffset); + } + } +} diff --git a/src/Luban.Job.Proto/Source/Defs/DefField.cs b/src/Luban.Job.Proto/Source/Defs/DefField.cs new file mode 100644 index 0000000..fffc0de --- /dev/null +++ b/src/Luban.Job.Proto/Source/Defs/DefField.cs @@ -0,0 +1,15 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Common.RawDefs; + +namespace Luban.Job.Proto.Defs +{ + class DefField : DefFieldBase + { + public DefAssembly Assembly => (DefAssembly)HostType.AssemblyBase; + + public DefField(DefTypeBase host, Field f, int idOffset) : base(host, f, idOffset) + { + + } + } +} diff --git a/src/Luban.Job.Proto/Source/Defs/DefProto.cs b/src/Luban.Job.Proto/Source/Defs/DefProto.cs new file mode 100644 index 0000000..c9f24bc --- /dev/null +++ b/src/Luban.Job.Proto/Source/Defs/DefProto.cs @@ -0,0 +1,37 @@ + +using Luban.Common.Utils; +using Luban.Job.Common.Utils; +using Luban.Job.Proto.RawDefs; +using System.Collections.Generic; + +namespace Luban.Job.Proto.Defs +{ + class DefProto : ProtoDefTypeBase + { + + public DefProto(PProto b) + { + Name = b.Name; + Namespace = b.Namespace; + Id = b.Id; + + foreach (var field in b.Fields) + { + Fields.Add(new DefField(this, field, 0)); + } + } + + public List Fields { get; set; } = new List(); + + public override void Compile() + { + var pass = Assembly; + if (Id == 0) + { + Id = (int)TypeUtil.ComputProtoHashIdByName(FullName); + } + pass.AddProto(this); + DefField.CompileFields(this, Fields, false); + } + } +} diff --git a/src/Luban.Job.Proto/Source/Defs/DefRpc.cs b/src/Luban.Job.Proto/Source/Defs/DefRpc.cs new file mode 100644 index 0000000..d5d345f --- /dev/null +++ b/src/Luban.Job.Proto/Source/Defs/DefRpc.cs @@ -0,0 +1,50 @@ +using Luban.Job.Common.Utils; +using Luban.Job.Common.Types; +using System; +using Luban.Job.Proto.RawDefs; +using Luban.Common.Utils; + +namespace Luban.Job.Proto.Defs +{ + class DefRpc : ProtoDefTypeBase + { + + public DefRpc(PRpc r) + { + Name = r.Name; + Namespace = r.Namespace; + Id = r.Id; + ArgType = r.ArgType; + ResType = r.ResType; + } + + public string ArgType { get; set; } + + public string ResType { get; set; } + + public TType TArgType { get; private set; } + + public TType TResType { get; private set; } + + + public override void Compile() + { + var pass = Assembly; + if (Id == 0) + { + Id = (int)TypeUtil.ComputProtoHashIdByName(FullName); + } + pass.AddProto(this); + + if ((TArgType = Assembly.CreateType(Namespace, ArgType)) == null) + { + throw new Exception($"rpc name:{FullName} arg:{ArgType} is invalid"); + } + + if ((TResType = Assembly.CreateType(Namespace, ResType)) == null) + { + throw new Exception($"rpc name:{FullName} res:{ResType} is invalid"); + } + } + } +} diff --git a/src/Luban.Job.Proto/Source/Defs/ProtoDefLoader.cs b/src/Luban.Job.Proto/Source/Defs/ProtoDefLoader.cs new file mode 100644 index 0000000..150f628 --- /dev/null +++ b/src/Luban.Job.Proto/Source/Defs/ProtoDefLoader.cs @@ -0,0 +1,100 @@ +using Luban.Job.Common.Utils; +using Luban.Job.Common.Defs; +using Luban.Server.Common; +using System; +using System.Collections.Generic; +using System.Xml.Linq; +using Luban.Common.Utils; +using Luban.Job.Proto.RawDefs; + +namespace Luban.Job.Proto.Defs +{ + class ProtoDefLoader : CommonDefLoader + { + private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger(); + + private readonly List _protos = new List(); + private readonly List _rpcs = new List(); + + public ProtoDefLoader(RemoteAgent agent) : base(agent) + { + RegisterRootDefineHandler("service", AddService); + RegisterModuleDefineHandler("proto", AddProto); + RegisterModuleDefineHandler("rpc", AddRpc); + } + + public Defines BuildDefines() + { + return new Defines(); + } + + private readonly List rpcAttrs = new List { "id" }; + private readonly List rpcRequiredAttrs = new List { "name", "arg", "res" }; + private void AddRpc(XElement e) + { + ValidAttrKeys(e, rpcAttrs, rpcRequiredAttrs); + var r = new PRpc() + { + Name = XmlUtil.GetRequiredAttribute(e, "name"), + Namespace = CurNamespace, + ArgType = XmlUtil.GetRequiredAttribute(e, "arg"), + ResType = XmlUtil.GetRequiredAttribute(e, "res"), + }; + s_logger.Trace("add rpc:{@rpc}", r); + _rpcs.Add(r); + } + + + private readonly List protoAttrs = new List { "id" }; + private readonly List protoRequiredAttrs = new List { "name" }; + + private void AddProto(XElement e) + { + ValidAttrKeys(e, protoAttrs, protoRequiredAttrs); + + var p = new PProto() + { + Name = XmlUtil.GetRequiredAttribute(e, "name"), + Namespace = CurNamespace, + Id = XmlUtil.GetOptionIntAttribute(e, "id"), + }; + + foreach (XElement fe in e.Elements()) + { + switch (fe.Name.LocalName) + { + case "var": + { + p.Fields.Add(CreateField(fe)); ; + break; + } + default: + { + throw new Exception($"定义文件:{CurImportFile} 不支持 tag:{fe.Name}"); + } + } + + } + + s_logger.Trace("add proto:{@proto}", p); + _protos.Add(p); + } + + private readonly List serviceAttrs = new List { "name" }; + private void AddService(XElement e) + { + var name = XmlUtil.GetRequiredAttribute(e, "name"); + s_logger.Trace("service {service}", name); + ValidAttrKeys(e, serviceAttrs, serviceAttrs); + foreach (XElement ele in e.Elements()) + { + s_logger.Trace("service {service_name} node: {name} {value}", name, ele.Name, ele.Attribute("value")?.Value); + } + } + + protected override void AddBean(XElement e, string parent) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Luban.Job.Proto/Source/Defs/ProtoDefTypeBase.cs b/src/Luban.Job.Proto/Source/Defs/ProtoDefTypeBase.cs new file mode 100644 index 0000000..2180ba7 --- /dev/null +++ b/src/Luban.Job.Proto/Source/Defs/ProtoDefTypeBase.cs @@ -0,0 +1,29 @@ +using Luban.Job.Common.Utils; +using Luban.Job.Common.Defs; +using Luban.Common.Utils; + +namespace Luban.Job.Proto.Defs +{ + abstract class ProtoDefTypeBase : DefTypeBase + { + public DefAssembly Assembly => (DefAssembly)AssemblyBase; + + public virtual string UeBpName => "U" + Name; + + public virtual string UeBpFullName => TypeUtil.MakeCppJoinedFullName("U" + Namespace, Name); + + //public string UeBpHeaderFileName => "bp_" + FileUtil.GetUeCppDefTypeHeaderFilePath(FullName); + + //public string UeBpHeaderFileNameWithoutSuffix => "bp_" + FileUtil.GetUeCppDefTypeHeaderFilePathWithoutSuffix(FullName); + + //public string EditorUeFullName => TypeUtil.MakeCppFullName(Namespace, Name); + + //public string UeFname => "F" + Name; + + //public string UeFfullName => TypeUtil.MakeCppFullName(Namespace, UeFname); + + //public string UeHeaderFileName => FileUtil.GetUeCppDefTypeHeaderFilePath(FullName); + + //public string UeEditorHeaderFileName => "editor_" + FileUtil.GetUeCppDefTypeHeaderFilePath(FullName); + } +} diff --git a/src/Luban.Job.Proto/Source/Generate/CsRender.cs b/src/Luban.Job.Proto/Source/Generate/CsRender.cs new file mode 100644 index 0000000..a3e972a --- /dev/null +++ b/src/Luban.Job.Proto/Source/Generate/CsRender.cs @@ -0,0 +1,324 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Common.Utils; +using Luban.Job.Proto.Defs; +using Scriban; +using System; +using System.Collections.Generic; + +namespace Luban.Job.Proto.Generate +{ + class CsRender + { + public string RenderAny(object o) + { + switch (o) + { + case DefConst c: return Render(c); + case DefEnum e: return Render(e); + case DefBean b: return Render(b); + case DefProto p: return Render(p); + case DefRpc r: return Render(r); + + default: throw new Exception($"unknown render type:{o}"); + } + } + + public string Render(DefConst c) + { + return RenderUtil.RenderCsConstClass(c); + } + + public string Render(DefEnum e) + { + return RenderUtil.RenderCsEnumClass(e); + } + + [ThreadStatic] + private static Template t_beanRender; + public string Render(DefBean b) + { + var template = t_beanRender ??= Template.Parse(@" +using Bright.Serialization; + +namespace {{namespace_with_top_module}} +{ + + public {{if is_value_type}}struct{{else}}{{cs_class_modifier}} class{{end}} {{name}} : {{if parent_def_type}} {{parent}} {{else}} BeanBase {{end}} + { + {{if !is_value_type}} + public {{name}}() + { + } + {{end}} + + public {{name}}(Bright.Common.NotNullInitialization _) {{if parent_def_type}} : base(_) {{end}} + { + {{if is_value_type}} + {{- for field in fields }} + {{if field.ctype.need_init}}{{field.proto_cs_init_field}}{{else}}{{field.proto_cs_init_field_default_value}} {{end}} + {{-end}} + {{else}} + {{- for field in fields }} + {{if field.ctype.need_init}}{{field.proto_cs_init_field}}{{end}} + {{-end}} + {{end}} + } + + public static void Serialize{{name}}(ByteBuf _buf, {{name}} x) + { + {{if is_abstract_type}} + if (x != null) + { + _buf.WriteInt(x.GetTypeId()); + x.Serialize(_buf); + } + else + { + _buf.WriteInt(0); + } + {{else}} + x.Serialize(_buf); + {{end}} + } + + public static {{name}} Deserialize{{name}}(ByteBuf _buf) + { + {{if is_abstract_type}} + {{full_name}} x; + switch (_buf.ReadInt()) + { + case 0 : return null; + {{- for child in hierarchy_not_abstract_children}} + case {{child.full_name}}.ID: x = new {{child.full_name}}(); break; + {{-end}} + default: throw new SerializationException(); + } + x.Deserialize(_buf); + {{else}} + var x = new {{full_name}}(); + x.Deserialize(_buf); + {{end}} + return x; + } + {{- for field in fields }} + public {{field.ctype.cs_define_type}} {{field.lan_style_name}}; + {{-end}} + + {{if !is_abstract_type}} + public const int ID = {{id}}; + public override int GetTypeId() => ID; + {{end}} + + public override void Serialize(ByteBuf _buf) + { + {{if parent_def_type}} base.Serialize(_buf); {{end}} + {{- for field in fields }} + {{field.cs_serialize}} + {{-end}} + } + + public override void Deserialize(ByteBuf _buf) + { + {{if parent_def_type}} base.Deserialize(_buf); {{end}} + {{- for field in fields }} + {{field.cs_deserialize}} + {{-end}} + } + + public override string ToString() + { + return ""{{full_name}}{ "" + {{- for field in hierarchy_fields }} + + ""{{field.lan_style_name}}:"" + {{field.proto_cs_to_string}} + "","" + {{-end}} + + ""}""; + } + } + +} + +"); + var result = template.Render(b); + + return result; + } + + [ThreadStatic] + private static Template t_protoRender; + public string Render(DefProto p) + { + var template = t_protoRender ??= Template.Parse(@" +using Bright.Serialization; + +namespace {{namespace_with_top_module}} +{ + + public sealed class {{name}} : Bright.Net.Codecs.Protocol + { + {{- for field in fields }} + public {{field.ctype.cs_define_type}} {{field.lan_style_name}}; + {{-end}} + public {{name}}() + { + } + + public {{name}}(Bright.Common.NotNullInitialization _) + { + {{- for field in fields }} + {{if field.ctype.need_init}}{{field.proto_cs_init_field}}{{end}} + {{-end}} + } + public const int ID = {{id}}; + + public override int GetTypeId() + { + return ID; + } + + public override void Serialize(ByteBuf _buf) + { + {{- for field in fields }} + {{field.cs_serialize}} + {{-end}} + } + + public override void Deserialize(ByteBuf _buf) + { + {{- for field in fields }} + {{field.cs_deserialize}} + {{-end}} + } + + public override void Reset() + { + throw new System.NotImplementedException(); + } + + public override object Clone() + { + throw new System.NotImplementedException(); + } + + public override string ToString() + { + return ""{{full_name}}{ "" + {{- for field in fields }} + + ""{{field.lan_style_name}}:"" + {{field.proto_cs_to_string}} + "","" + {{-end}} + + ""}""; + } + } + +} + +"); + var result = template.Render(p); + + return result; + } + + [ThreadStatic] + private static Template t_rpcRender; + public string Render(DefRpc r) + { + var template = t_rpcRender ??= Template.Parse(@" +using Bright.Serialization; + +namespace {{namespace_with_top_module}} +{ + + public sealed class {{name}} : Bright.Net.Codecs.Rpc<{{targ_type.cs_define_type}}, {{tres_type.cs_define_type}}> + { + public {{name}}() + { + } + + public const int ID = {{id}}; + + public override int GetTypeId() + { + return ID; + } + + public override void SerializeArg(ByteBuf buf, {{targ_type.cs_define_type}} arg) + { + {{targ_type.cs_define_type}}.Serialize{{targ_type.bean.name}}(buf, arg); + } + + public override {{targ_type.cs_define_type}} DeserializeArg(ByteBuf buf) + { + return {{targ_type.cs_define_type}}.Deserialize{{targ_type.bean.name}}(buf); + } + + public override void SerializeRes(ByteBuf buf, {{tres_type.cs_define_type}} res) + { + {{tres_type.cs_define_type}}.Serialize{{tres_type.bean.name}}(buf, res); + } + + public override {{tres_type.cs_define_type}} DeserializeRes(ByteBuf buf) + { + return {{tres_type.cs_define_type}}.Deserialize{{tres_type.bean.name}}(buf); + } + + public override void Reset() + { + throw new System.NotImplementedException(); + } + + public override object Clone() + { + throw new System.NotImplementedException(); + } + + public override string ToString() + { + return $""{{full_name}}{%{ {{arg:{Arg},res:{Res} }} }%}""; + } + } +} + +"); + var result = template.Render(r); + + return result; + } + + [ThreadStatic] + private static Template t_stubRender; + public string RenderStubs(string name, string module, List protos, List rpcs) + { + var template = t_stubRender ??= Template.Parse(@" +using Bright.Serialization; + +namespace {{namespace}} +{ + + public static class {{name}} + { + public static System.Collections.Generic.Dictionary Factories { get; } = new System.Collections.Generic.Dictionary + { + {{- for proto in protos }} + [{{proto.full_name}}.ID] = () => new {{proto.full_name}}(), + {{-end}} + + {{- for rpc in rpcs }} + [{{rpc.full_name}}.ID] = () => new {{rpc.full_name}}(), + {{-end}} + }; + } + +} + +"); + var result = template.Render(new + { + Name = name, + Namespace = module, + Protos = protos, + Rpcs = rpcs, + }); + + return result; + } + } +} diff --git a/src/Luban.Job.Proto/Source/Generate/LuaRender.cs b/src/Luban.Job.Proto/Source/Generate/LuaRender.cs new file mode 100644 index 0000000..17d6500 --- /dev/null +++ b/src/Luban.Job.Proto/Source/Generate/LuaRender.cs @@ -0,0 +1,303 @@ +using Luban.Job.Common.Defs; +using Luban.Job.Proto.Defs; +using Scriban; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Luban.Job.Proto.Generate +{ + class LuaRender + { + + [ThreadStatic] + private static Template t_allRender; + public string RenderTypes(List types) + { + var consts = types.Where(t => t is DefConst).ToList(); + var enums = types.Where(t => t is DefEnum).ToList(); + var beans = types.Where(t => t is DefBean).ToList(); + var protos = types.Where(t => t is DefProto).ToList(); + var rpcs = types.Where(t => t is DefRpc).ToList(); + var template = t_allRender ??= Template.Parse(@" +local setmetatable = setmetatable +local pairs = pairs +local ipairs = ipairs +local tinsert = table.insert + +local function SimpleClass() + local class = {} + class.__index = class + class.New = function(...) + local ctor = class.ctor + local o = ctor and ctor(...) or {} + setmetatable(o, class) + return o + end + return class +end + + +local function get_map_size(m) + local n = 0 + for _ in pairs(m) do + n = n + 1 + end + return n +end + +local consts = +{ + {{- for c in consts }} + ---@class {{c.full_name}} + {{- for item in c.items }} + ---@field public {{item.name}} {{item.type}} + {{-end}} + ['{{c.full_name}}'] = { {{ for item in c.items }} {{item.name}}={{item.to_lua_const_value}}, {{end}} }; + {{-end}} +} + +local enums = +{ + {{- for c in enums }} + ---@class {{c.full_name}} + {{- for item in c.items }} + ---@field public {{item.name}} int + {{-end}} + ['{{c.full_name}}'] = { {{ for item in c.items }} {{item.name}}={{item.int_value}}, {{end}} }; + {{-end}} +} + + +local function InitTypes(methods) + local readBool = methods.readBool + local writeBool = methods.writeBool + local readByte = methods.readByte + local writeByte = methods.writeByte + local readShort = methods.readShort + local writeShort = methods.writeShort + local readFshort = methods.readFshort + local writeInt = methods.writeInt + local readInt = methods.readInt + local writeFint = methods.writeFint + local readFint = methods.readFint + local readLong = methods.readLong + local writeLong = methods.writeLong + local readFlong = methods.readFlong + local writeFlong = methods.writeFlong + local readFloat = methods.readFloat + local writeFloat = methods.writeFloat + local readDouble = methods.readDouble + local writeDouble = methods.writeDouble + local readSize = methods.readSize + local writeSize = methods.writeSize + + local readString = methods.readString + local writeString = methods.writeString + local readBytes = methods.readBytes + local writeBytes = methods.writeBytes + + local function readVector2(bs) + return { x = readFloat(bs), y = readFloat(bs) } + end + + local function writeVector2(bs, v) + writeFloat(bs, v.x) + writeFloat(bs, v.y) + end + + local function readVector3(bs) + return { x = readFloat(bs), y = readFloat(bs), z = readFloat(bs) } + end + + local function writeVector3(bs, v) + writeFloat(bs, v.x) + writeFloat(bs, v.y) + writeFloat(bs, v.z) + end + + + local function readVector4(bs) + return { x = readFloat(bs), y = readFloat(bs), z = readFloat(bs), w = readFloat(bs) } + end + + local function writeVector4(bs, v) + writeFloat(bs, v.x) + writeFloat(bs, v.y) + writeFloat(bs, v.z) + writeFloat(bs, v.w) + end + + local function writeList(bs, list, keyFun) + writeSize(bs, #list) + for _, v in pairs(list) do + keyFun(bs, v) + end + end + + local function readList(bs, keyFun) + local list = {} + local v + for i = 1, readSize(bs) do + tinsert(list, keyFun(bs)) + end + return list + end + + local writeArray = writeList + local readArray = readList + + local function writeSet(bs, set, keyFun) + writeSize(bs, #set) + for _, v in ipairs(set) do + keyFun(bs, v) + end + end + + local function readSet(bs, keyFun) + local set = {} + local v + for i = 1, readSize(bs) do + tinsert(set, keyFun(bs)) + end + return set + end + + local function writeMap(bs, map, keyFun, valueFun) + writeSize(bs, get_map_size(map)) + for k, v in pairs(map) do + keyFun(bs, k) + valueFun(bs, v) + end + end + + local function readMap(bs, keyFun, valueFun) + local map = {} + for i = 1, readSize(bs) do + local k = keyFun(bs) + local v = valueFun(bs) + map[k] = v + end + return map + end + + local default_vector2 = {x=0,y=0} + local default_vector3 = {x=0,y=0,z=0} + local default_vector4 = {x=0,y=0,z=0,w=0} + + local beans = {} +{{ for bean in beans }} + do + ---@class {{bean.full_name}} {{if bean.parent_def_type}}:{{bean.parent}} {{end}} + {{- for field in bean.fields}} + ---@field public {{field.name}} {{field.lua_comment_type}} + {{-end}} + local class = SimpleClass() + class._id = {{bean.id}} + class._name = '{{bean.full_name}}' + --local name2id = { {{for c in bean.hierarchy_not_abstract_children}} ['{{c.full_name}}'] = {{c.id}}, {{end}} } + local id2name = { {{for c in bean.hierarchy_not_abstract_children}} [{{c.id}}] = '{{c.full_name}}', {{end}} } +{{if bean.is_abstract_type}} + class._serialize = function(bs, self) + writeInt(bs, self._id) + beans[self._name]._serialize(bs, self) + end + class._deserialize = function(bs) + local id = readInt(bs) + return beans[id2name[id]]._deserialize(bs) + end +{{else}} + class._serialize = function(bs, self) + {{- for field in bean.hierarchy_fields }} + {{field.proto_lua_serialize_while_nil}} + {{-end}} + end + class._deserialize = function(bs) + local o = { + {{- for field in bean.hierarchy_fields }} + {{field.name}} = {{field.proto_lua_deserialize}}, + {{-end}} + } + setmetatable(o, class) + return o + end +{{end}} + beans[class._name] = class + end +{{end}} + + local protos = { } +{{ for proto in protos }} + do + ---@class {{proto.full_name}} + {{- for field in proto.fields}} + ---@field public {{field.name}} {{field.lua_comment_type}} + {{-end}} + local class = SimpleClass() + class._id = {{proto.id}} + class._name = '{{proto.full_name}}' + class._serialize = function(self, bs) + {{- for field in proto.fields }} + {{field.proto_lua_serialize_while_nil}} + {{-end}} + end + class._deserialize = function(self, bs) + {{- for field in proto.fields }} + self.{{field.name}} = {{field.proto_lua_deserialize}} + {{-end}} + end + protos[class._id] = class + protos[class._name] = class + end +{{end}} + + local rpcs = { } +{{ for rpc in rpcs }} + do + ---@class {{rpc.full_name}} + ---@field public is_request bool + ---@field public rpc_id long + ---@field public arg {{rpc.targ_type.lua_comment_type}} + ---@field public res {{rpc.tres_type.lua_comment_type}} + local class = SimpleClass() + class._id = {{rpc.id}} + class._name = '{{rpc.full_name}}' + class._arg_name = '{{rpc.targ_type.bean.full_name}}' + class._res_name = '{{rpc.tres_type.bean.full_name}}' + class._serialize = function(self, bs) + local composite_id = self.rpc_id * 2 + if self.is_request then + writeLong(bs, composite_id) + beans['{{rpc.targ_type.bean.full_name}}']._serialize(self.arg, bs) + else + writeLong(bs, composite_id + 1) + beans['{{rpc.tres_type.bean.full_name}}']._serialize(self.res, bs) + end + end + class._deserialize = function(self, bs) + local composite_id = readLong(bs) + self.rpc_id = composite_id // 2 + if composite_id % 2 == 0 then + self.is_request = true + self.arg = beans['{{rpc.targ_type.bean.full_name}}']._deserialize(bs) + else + self.is_request = false + self.res = beans['{{rpc.tres_type.bean.full_name}}']._deserialize(bs) + end + end + rpcs[class._id] = class + rpcs[class._name] = class + end +{{end}} + + return { consts = consts, enums = enums, beans = beans, protos = protos, rpcs = rpcs } + end + +return { InitTypes = InitTypes} + + +"); + return template.Render(new { Consts = consts, Enums = enums, Beans = beans, Protos = protos, Rpcs = rpcs }); + } + } +} diff --git a/src/Luban.Job.Proto/Source/GenerateProto.cs b/src/Luban.Job.Proto/Source/GenerateProto.cs new file mode 100644 index 0000000..bdfc84d --- /dev/null +++ b/src/Luban.Job.Proto/Source/GenerateProto.cs @@ -0,0 +1,56 @@ +//using Bright.Time; +//using Gen.Proto.Common.RawDefs; +//using Luban.Job.Common.Utils; + +//namespace Luban.Job.Proto.Client +//{ +// class GenerateProto +// { +// public bool Handle(CommandLineOptions options) +// { +// var timer = new ProfileTimer(); +// timer.StartPhase("所有阶段"); + +// timer.StartPhase("加载定义"); +// var protoLoader = new ProtoDefLoader(); +// protoLoader.Load(options.DefineFile); +// long defEndTime = TimeUtil.NowMillis; +// timer.EndPhaseAndLog(); + + +// timer.StartPhase("发起 GenProto"); +// string outputDir = options.OutputCodeDir; + +// var defines = protoLoader.BuildDefines(); + + +// defines.Target = options.Target; +// defines.Language = options.Languange; +// var rpc = new GenProto(); +// var res = rpc.Call(GenClient.Ins.Session, new GenProtoArg() +// { +// Define = defines, +// OutputCodeRelatePath = outputDir, +// }).Result; +// timer.EndPhaseAndLog(); + + +// if (res.OK) +// { +// timer.StartPhase("获取生成文件"); + +// DownloadFileUtil.DownloadGeneratedFiles(outputDir, res.NewCodeFiles).Wait(); + +// timer.EndPhaseAndLog(); + +// timer.EndPhaseAndLog(); +// return true; +// } +// else +// { +// timer.EndPhaseAndLog(); +// return false; +// } +// } +// } +//} diff --git a/src/Luban.Job.Proto/Source/JobController.cs b/src/Luban.Job.Proto/Source/JobController.cs new file mode 100644 index 0000000..d53e3e7 --- /dev/null +++ b/src/Luban.Job.Proto/Source/JobController.cs @@ -0,0 +1,16 @@ +using Luban.Common.Protos; +using Luban.Server.Common; +using System; +using System.Threading.Tasks; + +namespace Luban.Job.Proto +{ + [Controller("proto")] + public class JobController : IJobController + { + public Task GenAsync(RemoteAgent agent, GenJob rpc) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Luban.Job.Proto/Source/RawDefs/Defines.cs b/src/Luban.Job.Proto/Source/RawDefs/Defines.cs new file mode 100644 index 0000000..34bfe46 --- /dev/null +++ b/src/Luban.Job.Proto/Source/RawDefs/Defines.cs @@ -0,0 +1,26 @@ +using Luban.Job.Common.RawDefs; +using System.Collections.Generic; + +namespace Luban.Job.Proto.RawDefs +{ + public class Defines + { + public string Target { get; set; } = "*"; + + public string Language { get; set; } = "cs"; + + public string TopModule { get; set; } = ""; + + public List ProtoServices { get; set; } = new List(); + + public List Beans { get; set; } = new List(); + + public List Consts { get; set; } = new List(); + + public List Enums { get; set; } = new List(); + + public List Protos { get; set; } = new List(); + + public List Rpcs { get; set; } = new List(); + } +} diff --git a/src/Luban.Job.Proto/Source/RawDefs/PProto.cs b/src/Luban.Job.Proto/Source/RawDefs/PProto.cs new file mode 100644 index 0000000..fd4f12c --- /dev/null +++ b/src/Luban.Job.Proto/Source/RawDefs/PProto.cs @@ -0,0 +1,17 @@ +using Luban.Job.Common.RawDefs; +using System.Collections.Generic; + +namespace Luban.Job.Proto.RawDefs +{ + + public class PProto + { + public string Namespace { get; set; } + + public string Name { get; set; } + + public int Id { get; set; } + + public List Fields { get; set; } = new List(); + } +} diff --git a/src/Luban.Job.Proto/Source/RawDefs/PRpc.cs b/src/Luban.Job.Proto/Source/RawDefs/PRpc.cs new file mode 100644 index 0000000..9ff2375 --- /dev/null +++ b/src/Luban.Job.Proto/Source/RawDefs/PRpc.cs @@ -0,0 +1,16 @@ +namespace Luban.Job.Proto.RawDefs +{ + + public class PRpc + { + public string Namespace { get; set; } + + public string Name { get; set; } + + public int Id { get; set; } + + public string ArgType { get; set; } + + public string ResType { get; set; } + } +} diff --git a/src/Luban.Job.Proto/Source/RawDefs/Service.cs b/src/Luban.Job.Proto/Source/RawDefs/Service.cs new file mode 100644 index 0000000..2276b7f --- /dev/null +++ b/src/Luban.Job.Proto/Source/RawDefs/Service.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Luban.Job.Proto.RawDefs +{ + + public class Service + { + public List Prefixs { get; set; } = new List(); + + public List FullNames { get; set; } = new List(); + } +} diff --git a/src/Luban.Job.Proto/Source/RpcController.cs b/src/Luban.Job.Proto/Source/RpcController.cs new file mode 100644 index 0000000..c8acc9e --- /dev/null +++ b/src/Luban.Job.Proto/Source/RpcController.cs @@ -0,0 +1,623 @@ +namespace Luban.Job.Proto.Server.Net +{ + class RpcController + { + + //private void LogException(IContext ctx, Exception e) + //{ + // if (e is AggregateException ae) + // { + // foreach (var ie in ae.InnerExceptions) + // { + // LogException(ctx, ie); + // } + // } + // else + // { + + // s_logger.Error(e, "发生异常"); + // ctx.Error(e, " {0} \n ", e.StackTrace); + // } + //} + + //private bool ValidateDataType(string outputDataType) + //{ + // switch (outputDataType) + // { + // case "bin": + // case "cbin": + // case "json": return true; + // default: return false; + // } + //} + + //private void OnGenDb(Session session, GenDb proto) + //{ + // var timer = new ProfileTimer(); + + // timer.StartPhase("生成代码"); + + // var res = new GenDbRes(); + + // string relatePath = proto.Arg.OutputCodeRelatePath; + + // var ass = new DefAssembly(); + // var ctx = new SessionContext(session, proto.Arg.Verbose); + // try + // { + // var genCodeTasks = new List(); + // var outputFiles = new ConcurrentBag(); + + // ass.Load(EJobType.DB, proto.Arg.Define, ctx); + // var render = new Generate.Db.CsRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = "Tables"; + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTables(name, module, ass.Types.Values.Where(t => t is BTable).ToList()), "cs"); + // var file = FileUtil.GetCsDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // Task.WhenAll(genCodeTasks).Wait(); + // ctx.Info(timer.EndPhaseAndLogToString()); + + // res.NewCodeFiles = outputFiles.ToList(); + // res.OK = true; + // } + // catch (Exception e) + // { + // res.OK = false; + // LogException(ctx, e); + // } + + // proto.ReturnResult(session, res); + //} + + //private ICsCodeRender CreateCsCodeRender(string outputDataType) + //{ + // switch (outputDataType) + // { + // case "bin": return new AppCsBinCodeRender(); + // case "cbin": return new AppCsCompatibleBinCodeRender(); + // case "json": return new AppCsJsonCodeRender(); + // default: throw new ArgumentException($"not support output data type:{outputDataType}"); + // } + //} + + //private void OnGenCfg(Session session, GenCfg proto) + //{ + // var res = new GenCfgRes(); + + // string lan = proto.Arg.Define.Language; + + // DefAssembly ass = new DefAssembly(); + + // var ctx = new SessionContext(session, proto.Arg.Verbose); + + + // var allJobs = new List(); + + + // try + // { + // string outputDataType = proto.Arg.OutputDataType; + // if (!ValidateDataType(outputDataType)) + // { + // throw new ArgumentException($"unknown outputdatatype:{outputDataType}"); + // } + + // bool exportTestData = proto.Arg.ExportTestData; + + // long genStartTime = TimeUtil.NowMillis; + // var genCodeTasks = new List(); + // var outputCodeFiles = new ConcurrentBag(); + + // ass.Load(EJobType.CONFIG, proto.Arg.Define, ctx); + // EGenTypes genTypes = proto.Arg.GenTypes; + // var targetService = ass.CfgTargetService; + + // List exportTables = ass.Types.Values.Where(t => t is CTable ct && ct.NeedExport).Select(t => (CTable)t).ToList(); + + // if (genTypes.HasFlag(EGenTypes.APP_CODE)) + // { + // var refTypes = new Dictionary(); + // long genCodeStartTime = TimeUtil.NowMillis; + + // foreach (var refType in targetService.Refs) + // { + // if (!ass.Types.ContainsKey(refType)) + // { + // throw new Exception($"service:{targetService.Name} ref:{refType} 类型不存在"); + // } + // if (!refTypes.TryAdd(refType, ass.Types[refType])) + // { + // throw new Exception($"service:{targetService.Name} ref:{refType} 重复引用"); + // } + // } + + // foreach (var table in exportTables) + // { + // refTypes[table.FullName] = table; + // table.ValueTType.Apply(RefTypeVisitor.Ins, refTypes); + // } + + // foreach (var type in ass.Types) + // { + // if (type.Value is DefConst || type.Value is DefEnum) + // { + // refTypes[type.Key] = type.Value; + // } + // } + + // List exportTypes = refTypes.Values.ToList(); + + // switch (lan) + // { + // case "cs": + // { + // ICsCodeRender render = CreateCsCodeRender(outputDataType); + // foreach (var c in exportTypes) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = targetService.Manager; + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderService(name, module, exportTables), "cs"); + // var file = FileUtil.GetCsDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + + // break; + // } + // case "go": + // { + // // + // // TODO? + // // 由于 go 语言不支持类型继承 + // // go 不支持 table.value_type 为多态的表 + // // + // // + // var render = new AppGoCodeRender(); + + + // foreach (var c in exportTypes) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "go"); + // var file = FileUtil.GetGoDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = targetService.Manager; + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderService(name, module, exportTables), "go"); + // var file = FileUtil.GetGoDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + + // break; + // } + // case "lua": + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var render = new Generate.Cfg.LuaRender(); + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAll(exportTypes.ToList()), "lua"); + // var file = "CfgTypes.lua"; + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // case "editor_cs": + // { + // var render = new EditorCsRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // break; + // } + // case "editor_cpp": + // { + // var render = new EditorCppRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // break; + // } + // case "editor_ue_cpp": + // { + // var render = new UE4EditorCppRender(); + + // var renderTypes = ass.Types.Values.Where(c => c is DefEnum || c is DefBean).ToList(); + + // foreach (var c in renderTypes) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp"); + // var file = c.UeEditorHeaderFileName; + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + // int TYPE_PER_STUB_FILE = 200; + + // for (int i = 0, n = (renderTypes.Count + TYPE_PER_STUB_FILE - 1) / TYPE_PER_STUB_FILE; i < n; i++) + // { + // int index = i; + // genCodeTasks.Add(Task.Run(() => + // { + // int startIndex = index * TYPE_PER_STUB_FILE; + // var content = RenderUtils.ConcatAutoGenerationHeader( + // render.RenderStub(renderTypes.GetRange(startIndex, Math.Min(TYPE_PER_STUB_FILE, renderTypes.Count - startIndex))), + // "cpp"); + // var file = $"Stub_{index}.cpp"; + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // break; + // } + // case "ue_bp_cpp": + // { + // var render = new UE4BpCppRender(); + // foreach (var c in exportTypes) + // { + // if (c is DefConst || c is CTable) + // { + // continue; + // } + + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp"); + // var file = c.UeBpHeaderFileName; + // var md5 = GenMd5AndAddCache(file, content); + // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + // //{ + // // var module = ass.TopModule; + // // var name = targetService.Manager; + // // var content = render.RenderService(name, module, exportTables); + // // var file = FileUtil.GetCppDefTypeCppFilePath(name); + // // var md5 = GenMd5AndAddCache(file, content); + // // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // //} + // break; + // } + // default: + // { + // throw new Exception($"unknown language:{lan}"); + // } + // } + + + // allJobs.Add(Task.Run(async () => + // { + // await Task.WhenAll(genCodeTasks); + // res.NewAppCodeFiles = outputCodeFiles.ToList(); + // long genCodeEndTime = TimeUtil.NowMillis; + // ctx.Info("====== 生成代码 总共耗时 {0} ms ======", (genCodeEndTime - genCodeStartTime)); + // })); + // } + + // if ((genTypes & (EGenTypes.APP_DATA | EGenTypes.APP_RESOURCE_LIST)) != 0) + // { + // var genDataTasks = new List(); + // var outputDataFiles = new ConcurrentBag(); + // var render = new AppBinaryDataRender(); + // long genDataStartTime = TimeUtil.NowMillis; + + // foreach (CTable c in exportTables) + // { + // genDataTasks.Add(Task.Run(async () => + // { + // long beginTime = TimeUtil.NowMillis; + // await c.Load(session, exportTestData); + // long endTime = TimeUtil.NowMillis; + // if (endTime - beginTime > 100) + // { + // ctx.Info("====== 配置表 {0} 加载耗时 {1} ms ======", c.FullName, (endTime - beginTime)); + // } + // })); + // } + // Task.WaitAll(genDataTasks.ToArray()); + // } + + + // if (genTypes.HasFlag(EGenTypes.APP_DATA)) + // { + // var genDataTasks = new List(); + // var outputDataFiles = new ConcurrentBag(); + // var render = new AppBinaryDataRender(); + // long genDataStartTime = TimeUtil.NowMillis; + + // foreach (CTable c in exportTables) + // { + // genDataTasks.Add(Task.Run(() => + // { + // var content = c.ToOutputData(outputDataType); + // var file = c.OutputDataFile; + // var md5 = GenMd5AndAddCache(file, content); + // outputDataFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + + // allJobs.Add(Task.Run(async () => + // { + // await Task.WhenAll(genDataTasks); + // long genDataEndTime = TimeUtil.NowMillis; + // ctx.Info("====== 生成配置数据 总共耗时 {0} ms ======", (genDataEndTime - genDataStartTime)); + // res.NewAppDataFiles = outputDataFiles.ToList(); + + // long verifyStartTime = TimeUtil.NowMillis; + // render.VerifyTables(exportTables); + // res.PathQueries = ass.GetPathQueries(); + + // long verifyEndTime = TimeUtil.NowMillis; + // ctx.Info("====== 校验配置 总共耗时 {0} ms ======", (verifyEndTime - verifyStartTime)); + // })); + // } + + // if (genTypes.HasFlag(EGenTypes.APP_RESOURCE_LIST)) + // { + // var genDataTasks = new List>>(); + // var render = new AppBinaryDataRender(); + // long genDataStartTime = TimeUtil.NowMillis; + + // foreach (CTable c in exportTables) + // { + // genDataTasks.Add(Task.Run(() => + // { + // return c.ExportResourceList(); + // })); + // } + + // allJobs.Add(Task.Run(async () => + // { + // var ress = new HashSet<(string, string)>(10000); + // foreach (var task in genDataTasks) + // { + // foreach (var ri in await task) + // { + // if (ress.Add((ri.Resource, ri.Tag))) + // { + // res.ResourceList.Add(ri); + // } + // } + // } + // long genDataEndTime = TimeUtil.NowMillis; + // ctx.Info("====== 生成导出资源列表 总共耗时 {0} ms ======", (genDataEndTime - genDataStartTime)); + // })); + // } + + // Task.WhenAll(allJobs).Wait(); + + // long genEndTime = TimeUtil.NowMillis; + // ctx.Info("======== 服务器端 总共耗时 {0} ms =======", (genEndTime - genStartTime)); + + // res.OK = true; + // } + // catch (Exception e) + // { + // res.OK = false; + // LogException(ctx, e); + // } + + // proto.ReturnResult(session, res); + //} + + //private void OnGenProto(Session session, GenProto proto) + //{ + // var timer = new ProfileTimer(); + + // timer.StartPhase("服务器生成代码"); + + // var res = new GenProtoRes(); + + // string relatePath = proto.Arg.OutputCodeRelatePath; + + // DefAssembly ass = new DefAssembly(); + // var ctx = new SessionContext(session, proto.Arg.Verbose); + // try + // { + // var genCodeTasks = new List(); + // var outputFiles = new ConcurrentBag(); + + // ass.Load(EJobType.PROTO, proto.Arg.Define, ctx); + // var outputSyncFiles = new ConcurrentBag(); + + // switch (proto.Arg.Define.Language) + // { + // case "cs": + // { + // var render = new CsRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = "ProtocolStub"; + // var content = RenderUtils.ConcatAutoGenerationHeader( + // render.RenderStubs(name, module, + // ass.Types.Values.Where(t => t is PProto).ToList(), + // ass.Types.Values.Where(t => t is PRpc).ToList()), + // "cs"); + // var file = FileUtil.GetCsDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // case "lua": + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var render = new Generate.Proto.LuaRender(); + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTypes(ass.Types.Values.ToList()), "lua"); + // var file = "ProtoTypes.lua"; + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // default: + // { + // throw new Exception($"unknown lan:{proto.Arg.Define.Language}"); + // } + // } + + // Task.WhenAll(genCodeTasks).Wait(); + // res.NewCodeFiles = outputFiles.ToList(); + + // ctx.Info(timer.EndPhaseAndLogToString()); + + // res.OK = true; + // } + // catch (Exception e) + // { + // res.OK = false; + // LogException(ctx, e); + // } + + // proto.ReturnResult(session, res); + //} + + //private void OnGenRep(Session session, GenRep proto) + //{ + // var timer = new ProfileTimer(); + + // timer.StartPhase("服务器生成代码"); + + // var res = new GenRepRes(); + + // string relatePath = proto.Arg.OutputCodeRelatePath; + + // DefAssembly ass = new DefAssembly(); + // var ctx = new SessionContext(session, proto.Arg.Verbose); + // try + // { + // var genCodeTasks = new List(); + // var outputFiles = new ConcurrentBag(); + + // ass.Load(EJobType.REP, proto.Arg.Define, ctx); + // var outputSyncFiles = new ConcurrentBag(); + + // switch (proto.Arg.Define.Language) + // { + // case "cs": + // { + // var render = new Generate.Rep.CsRender(); + // foreach (var c in ass.Types.Values) + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs"); + // var file = FileUtil.GetCsDefTypePath(c.FullName); + // var md5 = GenMd5AndAddCache(file, content); + + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // } + // genCodeTasks.Add(Task.Run(() => + // { + // var module = ass.TopModule; + // var name = "RepStub"; + // var content = RenderUtils.ConcatAutoGenerationHeader( + // render.RenderStubs(name, module, ass.Types.Values.Where(t => (t is DefActor) || (t is DefComponent)).ToList()), + // "cs"); + // var file = FileUtil.GetCsDefTypePath(name); + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // case "lua": + // { + // genCodeTasks.Add(Task.Run(() => + // { + // var render = new Generate.Rep.LuaRender(); + // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTypes(ass.Types.Values.ToList()), "lua"); + // var file = "RepTypes.lua"; + // var md5 = GenMd5AndAddCache(file, content); + // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 }); + // })); + // break; + // } + // default: + // { + // throw new Exception($"unknown lan:{proto.Arg.Define.Language}"); + // } + // } + + // Task.WhenAll(genCodeTasks).Wait(); + // res.NewCodeFiles = outputFiles.ToList(); + + // ctx.Info(timer.EndPhaseAndLogToString()); + + // res.OK = true; + // } + // catch (Exception e) + // { + // res.OK = false; + // LogException(ctx, e); + // } + + // proto.ReturnResult(session, res); + //} + } +} diff --git a/src/Luban.Server/Luban.Server.csproj b/src/Luban.Server/Luban.Server.csproj index e344b9b..9b280be 100644 --- a/src/Luban.Server/Luban.Server.csproj +++ b/src/Luban.Server/Luban.Server.csproj @@ -30,6 +30,8 @@ + + diff --git a/src/Luban.Server/Source/Program.cs b/src/Luban.Server/Source/Program.cs index 498b694..7e7d487 100644 --- a/src/Luban.Server/Source/Program.cs +++ b/src/Luban.Server/Source/Program.cs @@ -47,6 +47,8 @@ namespace Luban.Server #if EMBED_CFG GenServer.Ins.RegisterJob("cfg", new Luban.Job.Cfg.JobController()); #endif + GenServer.Ins.RegisterJob("proto", new Luban.Job.Proto.JobController()); + GenServer.Ins.RegisterJob("db", new Luban.Job.Db.JobController()); int processorCount = System.Environment.ProcessorCount; ThreadPool.SetMinThreads(Math.Max(4, processorCount), 5); ThreadPool.SetMaxThreads(Math.Max(16, processorCount * 4), 10); diff --git a/src/Luban.sln b/src/Luban.sln index e94de77..d1ea460 100644 --- a/src/Luban.sln +++ b/src/Luban.sln @@ -15,6 +15,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Server.Common", "Luba EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Server", "Luban.Server\Luban.Server.csproj", "{714B78D2-A3BE-4845-AF0E-0A5076B8E77E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Job.Proto", "Luban.Job.Proto\Luban.Job.Proto.csproj", "{845D3933-EA3F-4A7D-97A3-77E696A2D261}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Job.Db", "Luban.Job.Db\Luban.Job.Db.csproj", "{7467AC15-C61F-4C56-942F-18EAEA902C58}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,6 +49,14 @@ Global {714B78D2-A3BE-4845-AF0E-0A5076B8E77E}.Debug|Any CPU.Build.0 = Debug|Any CPU {714B78D2-A3BE-4845-AF0E-0A5076B8E77E}.Release|Any CPU.ActiveCfg = Release|Any CPU {714B78D2-A3BE-4845-AF0E-0A5076B8E77E}.Release|Any CPU.Build.0 = Release|Any CPU + {845D3933-EA3F-4A7D-97A3-77E696A2D261}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {845D3933-EA3F-4A7D-97A3-77E696A2D261}.Debug|Any CPU.Build.0 = Debug|Any CPU + {845D3933-EA3F-4A7D-97A3-77E696A2D261}.Release|Any CPU.ActiveCfg = Release|Any CPU + {845D3933-EA3F-4A7D-97A3-77E696A2D261}.Release|Any CPU.Build.0 = Release|Any CPU + {7467AC15-C61F-4C56-942F-18EAEA902C58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7467AC15-C61F-4C56-942F-18EAEA902C58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7467AC15-C61F-4C56-942F-18EAEA902C58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7467AC15-C61F-4C56-942F-18EAEA902C58}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE