Browse Source

Merge branch 'TechEmpower:master' into master

Jeremy Kuhn 7 months ago
parent
commit
65fe69f136
100 changed files with 7443 additions and 3066 deletions
  1. 133 0
      CODE_OF_CONDUCT.md
  2. 15 14
      Dockerfile
  3. 1 0
      frameworks/C++/libsniper/libs/core
  4. 80 9
      frameworks/C++/paozhu/paozhu.dockerfile
  5. 147 43
      frameworks/C++/paozhu/paozhu_benchmark/CMakeLists.txt
  6. 10 0
      frameworks/C++/paozhu/paozhu_benchmark/common/autocontrolmethod.hpp
  7. 40 0
      frameworks/C++/paozhu/paozhu_benchmark/common/autorestfulpaths.hpp
  8. 9 0
      frameworks/C++/paozhu/paozhu_benchmark/common/cost_define.h
  9. 39 0
      frameworks/C++/paozhu/paozhu_benchmark/common/httphook.cpp
  10. 19 0
      frameworks/C++/paozhu/paozhu_benchmark/common/json_reflect_headers.h
  11. 8 2
      frameworks/C++/paozhu/paozhu_benchmark/conf/server.conf
  12. 189 189
      frameworks/C++/paozhu/paozhu_benchmark/controller/src/techempower.cpp
  13. 1 0
      frameworks/C++/paozhu/paozhu_benchmark/libs/types/techempower_json.h
  14. 16 0
      frameworks/C++/paozhu/paozhu_benchmark/models/Fortune.cpp
  15. 16 0
      frameworks/C++/paozhu/paozhu_benchmark/models/World.cpp
  16. 16 0
      frameworks/C++/paozhu/paozhu_benchmark/models/include/Fortune.h
  17. 16 0
      frameworks/C++/paozhu/paozhu_benchmark/models/include/World.h
  18. 2687 0
      frameworks/C++/paozhu/paozhu_benchmark/orm/include/fortunebase.h
  19. 2509 0
      frameworks/C++/paozhu/paozhu_benchmark/orm/include/worldbase.h
  20. 4 0
      frameworks/C++/paozhu/paozhu_benchmark/orm/orm.h
  21. 5 0
      frameworks/C++/paozhu/paozhu_benchmark/view/techempower/fortunes.html
  22. 26 0
      frameworks/C++/paozhu/paozhu_benchmark/viewsrc/include/regviewmethod.hpp
  23. 26 0
      frameworks/C++/paozhu/paozhu_benchmark/viewsrc/include/viewsrc.h
  24. 50 0
      frameworks/C++/paozhu/paozhu_benchmark/viewsrc/view/techempower/fortunes.cpp
  25. 66 0
      frameworks/C++/paozhu/paozhu_benchmark/websockets/include/loopwebsockets.hpp
  26. 83 0
      frameworks/C++/paozhu/paozhu_benchmark/websockets/include/mywebsockets.hpp
  27. 15 0
      frameworks/C++/poco/README.md
  28. 10 1
      frameworks/C++/poco/benchmark.cpp
  29. 6 6
      frameworks/C++/poco/poco.dockerfile
  30. 0 19
      frameworks/C++/silicon/CMakeLists.txt
  31. 0 8
      frameworks/C++/silicon/README.md
  32. 0 28
      frameworks/C++/silicon/benchmark_config.json
  33. 0 47
      frameworks/C++/silicon/build/symbols.hh
  34. 0 102
      frameworks/C++/silicon/build/techempower.hh
  35. 0 41
      frameworks/C++/silicon/build/techempower_lwan.cc
  36. 0 48
      frameworks/C++/silicon/build/techempower_microhttpd.cc
  37. 0 39
      frameworks/C++/silicon/silicon.dockerfile
  38. 5 4
      frameworks/C++/userver/README.md
  39. 0 24
      frameworks/C++/userver/benchmark_config.json
  40. 0 18
      frameworks/C++/userver/config.toml
  41. 0 29
      frameworks/C++/userver/userver-bare.dockerfile
  42. 3 3
      frameworks/C++/userver/userver.dockerfile
  43. 2 17
      frameworks/C++/userver/userver_benchmark/userver_techempower.cpp
  44. 2 5
      frameworks/C++/userver/userver_configs/static_config.yaml
  45. 0 29
      frameworks/C/duda/README.md
  46. 0 24
      frameworks/C/duda/benchmark_config.json
  47. 0 13
      frameworks/C/duda/duda.dockerfile
  48. 0 7
      frameworks/C/duda/webservice/Makefile.in
  49. 0 81
      frameworks/C/duda/webservice/main.c
  50. 1 0
      frameworks/C/h2o/benchmark_config.json
  51. 28 18
      frameworks/C/h2o/h2o.dockerfile
  52. 126 83
      frameworks/C/h2o/src/database.c
  53. 3 3
      frameworks/C/h2o/src/database.h
  54. 29 0
      frameworks/C/h2o/src/event_loop.c
  55. 5 0
      frameworks/C/h2o/src/event_loop.h
  56. 123 65
      frameworks/C/h2o/src/handlers/world.c
  57. 0 17
      frameworks/CSharp/appmpower/appmpower-ado-pg.dockerfile
  58. 53 0
      frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile
  59. 14 4
      frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile
  60. 8 2
      frameworks/CSharp/appmpower/appmpower.dockerfile
  61. 4 4
      frameworks/CSharp/appmpower/benchmark_config.json
  62. 2 2
      frameworks/CSharp/appmpower/config.toml
  63. 10 0
      frameworks/CSharp/appmpower/odbcinst.ini
  64. 0 15
      frameworks/CSharp/appmpower/src/CachedWorldSerializer.cs
  65. 0 200
      frameworks/CSharp/appmpower/src/Data/DbConnection.cs
  66. 0 67
      frameworks/CSharp/appmpower/src/Data/DbConnections.cs
  67. 0 17
      frameworks/CSharp/appmpower/src/Data/DbProviderFactory.cs
  68. 0 16
      frameworks/CSharp/appmpower/src/Data/InternalConnection.cs
  69. 0 117
      frameworks/CSharp/appmpower/src/HttpApplication.cs
  70. 0 7
      frameworks/CSharp/appmpower/src/JsonMessage.cs
  71. 0 58
      frameworks/CSharp/appmpower/src/Kestrel/Json.cs
  72. 0 38
      frameworks/CSharp/appmpower/src/Kestrel/PlainText.cs
  73. 0 25
      frameworks/CSharp/appmpower/src/Kestrel/ServiceProvider.cs
  74. 0 257
      frameworks/CSharp/appmpower/src/Memory/CacheEntry.cs
  75. 0 32
      frameworks/CSharp/appmpower/src/Memory/CacheEntryHelper.cs
  76. 0 62
      frameworks/CSharp/appmpower/src/Memory/CacheEntryState.cs
  77. 0 140
      frameworks/CSharp/appmpower/src/Memory/CacheEntryTokens.cs
  78. 0 520
      frameworks/CSharp/appmpower/src/Memory/MemoryCache.cs
  79. 0 67
      frameworks/CSharp/appmpower/src/Memory/MemoryCacheOptions.cs
  80. 0 24
      frameworks/CSharp/appmpower/src/Microsoft/CachKey.cs
  81. 0 59
      frameworks/CSharp/appmpower/src/Microsoft/StringBuilderCache.cs
  82. 0 42
      frameworks/CSharp/appmpower/src/Program.cs
  83. 10 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Constants.cs
  84. 40 63
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbCommand.cs
  85. 174 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs
  86. 61 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs
  87. 61 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnectionsKeyed.cs
  88. 8 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProvider.cs
  89. 21 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProviderFactory.cs
  90. 9 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Data/Dbms.cs
  91. 66 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/DotnetMethods.cs
  92. 4 17
      frameworks/CSharp/appmpower/src/appMpower.Orm/FortunesView.cs
  93. 19 37
      frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/BatchUpdateString.cs
  94. 0 2
      frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/ConcurrentRandom.cs
  95. 54 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/StringBuilderCache.cs
  96. 203 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs
  97. 1 1
      frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/CachedWorld.cs
  98. 1 3
      frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/Fortune.cs
  99. 1 1
      frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/World.cs
  100. 50 131
      frameworks/CSharp/appmpower/src/appMpower.Orm/RawDb.cs

+ 133 - 0
CODE_OF_CONDUCT.md

@@ -0,0 +1,133 @@
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+  community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+  any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+  without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official email address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
[email protected].
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations

+ 15 - 14
Dockerfile

@@ -1,4 +1,4 @@
-FROM ubuntu:22.04
+FROM ubuntu:24.04
 
 
 ARG DEBIAN_FRONTEND=noninteractive
 ARG DEBIAN_FRONTEND=noninteractive
 # WARNING: DON'T PUT A SPACE AFTER ANY BACKSLASH OR APT WILL BREAK
 # WARNING: DON'T PUT A SPACE AFTER ANY BACKSLASH OR APT WILL BREAK
@@ -18,24 +18,25 @@ RUN apt-get -yqq update && \
       libpq-dev \
       libpq-dev \
       pkg-config \
       pkg-config \
       python3 \
       python3 \
+      python3-colorama \
       python3-dev \
       python3-dev \
+      python3-dnspython \
+      python3-packaging \
       python3-pip \
       python3-pip \
+      python3-psutil \
+      python3-psycopg2 \
+      python3-requests \
       siege \
       siege \
-      software-properties-common
-
-RUN pip3 install \
-      colorama==0.3.1 \
-      docker==4.0.2 \
-      mysqlclient \
-      psutil \
-      psycopg2-binary \
-      pymongo==3.13.0 \
-      # urllib3 incompatibility:
-      # https://github.com/docker/docker-py/issues/3113#issuecomment-1525500104
-      requests==2.28.1
+      software-properties-common && \
+    # Ubuntu's equivalent packages are too old and/or broken.
+    pip3 install \
+      --break-system-packages \
+      docker==7.0.0 \
+      mysqlclient==2.2.4 \
+      pymongo==4.7.2
 
 
 # Collect resource usage statistics
 # Collect resource usage statistics
-ARG DOOL_VERSION=v1.2.0
+ARG DOOL_VERSION=v1.3.1
 
 
 WORKDIR /tmp
 WORKDIR /tmp
 RUN curl -LSs "https://github.com/scottchiefbaker/dool/archive/${DOOL_VERSION}.tar.gz" | \
 RUN curl -LSs "https://github.com/scottchiefbaker/dool/archive/${DOOL_VERSION}.tar.gz" | \

+ 1 - 0
frameworks/C++/libsniper/libs/core

@@ -0,0 +1 @@
+Subproject commit a792ecfebb02f98bbdd8db232fba69f3f92907b3

+ 80 - 9
frameworks/C++/paozhu/paozhu.dockerfile

@@ -1,4 +1,4 @@
-FROM ubuntu:22.04
+FROM ubuntu:24.04
 RUN apt-get update -yqq && apt-get install -yqq apt-utils software-properties-common wget unzip cmake git
 RUN apt-get update -yqq && apt-get install -yqq apt-utils software-properties-common wget unzip cmake git
 RUN apt-get install -yqq gcc g++ openssl libssl-dev zlib1g-dev build-essential locales
 RUN apt-get install -yqq gcc g++ openssl libssl-dev zlib1g-dev build-essential locales
 
 
@@ -18,24 +18,95 @@ WORKDIR /
 # RUN wget https://github.com/hggq/paozhu/releases/download/v1.5.8/benchmark.zip
 # RUN wget https://github.com/hggq/paozhu/releases/download/v1.5.8/benchmark.zip
 RUN git clone https://github.com/hggq/paozhu
 RUN git clone https://github.com/hggq/paozhu
 # RUN unzip benchmark.zip
 # RUN unzip benchmark.zip
-RUN rm -Rf ./paozhu/controller
- 
-COPY ./paozhu_benchmark/controller ./paozhu/
-COPY ./paozhu_benchmark/common/autocontrolmethod.hpp ./paozhu/common/
-COPY ./paozhu_benchmark/common/reghttpmethod_pre.hpp ./paozhu/common/
-COPY ./paozhu_benchmark/common/reghttpmethod.hpp ./paozhu/common/
+# RUN rm -Rf ./paozhu/controller
+# RUN rm -Rf ./paozhu/libs
+# RUN rm -Rf ./paozhu/view
+# RUN rm -Rf ./paozhu/viewsrc
+# RUN rm -Rf ./paozhu/orm
+# RUN rm -Rf ./paozhu/models
+# RUN rm -Rf ./paozhu/common
+
+
+
+# COPY ./paozhu_benchmark/controller ./paozhu/
+# COPY ./paozhu_benchmark/libs ./paozhu/
+# COPY ./paozhu_benchmark/view ./paozhu/
+# COPY ./paozhu_benchmark/viewsrc ./paozhu/
+
+# COPY ./paozhu_benchmark/orm ./paozhu/
+# COPY ./paozhu_benchmark/models ./paozhu/
+# COPY ./paozhu_benchmark/common ./paozhu/
+
+# RUN ls -l ./paozhu
+# RUN pwd
+# RUN mkdir ./paozhu/common
+# RUN mkdir ./paozhu/libs
+# RUN mkdir ./paozhu/libs/types
+# COPY ./paozhu_benchmark/libs/types/techempower_json.h ./paozhu/libs/types/
+# COPY ./paozhu_benchmark/libs/types/techempower_json_jsonreflect.cpp ./paozhu/libs/types/
+
+# RUN mkdir ./paozhu/controller
+# RUN mkdir ./paozhu/controller/include
+# RUN mkdir ./paozhu/controller/src
+
+# COPY ./paozhu_benchmark/controller/include/techempower.h ./paozhu/controller/include/
+# COPY ./paozhu_benchmark/controller/src/techempower.cpp ./paozhu/controller/src/
+
+
+# COPY ./paozhu_benchmark/common/autocontrolmethod.hpp ./paozhu/common/
+# COPY ./paozhu_benchmark/common/reghttpmethod_pre.hpp ./paozhu/common/
+# COPY ./paozhu_benchmark/common/reghttpmethod.hpp ./paozhu/common/
+# COPY ./paozhu_benchmark/common/json_reflect_headers.h ./paozhu/common/
+
+# COPY ./paozhu_benchmark/common/cost_define.h ./paozhu/common/
+# COPY ./paozhu_benchmark/common/autorestfulpaths.hpp ./paozhu/common/
+# COPY ./paozhu_benchmark/common/websockets_method_reg.hpp ./paozhu/common/
+# COPY ./paozhu_benchmark/common/httphook.cpp ./paozhu/common/
 
 
 COPY ./paozhu_benchmark/conf/server.conf ./paozhu/conf/server.conf
 COPY ./paozhu_benchmark/conf/server.conf ./paozhu/conf/server.conf
 COPY ./paozhu_benchmark/conf/orm.conf ./paozhu/conf/orm.conf
 COPY ./paozhu_benchmark/conf/orm.conf ./paozhu/conf/orm.conf
+
+# must use testbenchmark.cpp to test benchmark
 COPY ./paozhu_benchmark/CMakeLists.txt ./paozhu/CMakeLists.txt
 COPY ./paozhu_benchmark/CMakeLists.txt ./paozhu/CMakeLists.txt
 
 
+# RUN mkdir ./paozhu/view
+# RUN mkdir ./paozhu/view/techempower
+
+# COPY ./paozhu_benchmark/view/techempower/fortunes.html ./paozhu/view/techempower/
+
+# RUN mkdir ./paozhu/viewsrc
+# RUN mkdir ./paozhu/viewsrc/include
+# RUN mkdir ./paozhu/viewsrc/view
+# RUN mkdir ./paozhu/viewsrc/view/techempower
+
+# COPY ./paozhu_benchmark/viewsrc/view/techempower/fortunes.cpp ./paozhu/viewsrc/view/techempower/
+# COPY ./paozhu_benchmark/viewsrc/include/viewsrc.h ./paozhu/viewsrc/include/
+# COPY ./paozhu_benchmark/viewsrc/include/regviewmethod.hpp ./paozhu/viewsrc/include/
+
+
+
+# RUN mkdir ./paozhu/orm
+# RUN mkdir ./paozhu/orm/include
+
+
+# COPY ./paozhu_benchmark/orm/orm.h ./paozhu/orm/
+# COPY ./paozhu_benchmark/orm/include/fortunebase.h ./paozhu/orm/include/
+# COPY ./paozhu_benchmark/orm/include/worldbase.h ./paozhu/orm/include/
+
+# RUN mkdir ./paozhu/models
+# RUN mkdir ./paozhu/models/include
+
+# COPY ./paozhu_benchmark/models/include/Fortune.h ./paozhu/models/include/
+# COPY ./paozhu_benchmark/models/include/World.h ./paozhu/models/include/
+# COPY ./paozhu_benchmark/models/World.cpp ./paozhu/models/
+# COPY ./paozhu_benchmark/models/Fortune.cpp ./paozhu/models/
+
 WORKDIR /paozhu
 WORKDIR /paozhu
 RUN unzip asio.zip
 RUN unzip asio.zip
 
 
 RUN cmake . -B build -DCMAKE_BUILD_TYPE=Release 
 RUN cmake . -B build -DCMAKE_BUILD_TYPE=Release 
 RUN cmake --build build
 RUN cmake --build build
 
 
-
 EXPOSE 8888
 EXPOSE 8888
 
 
-CMD ./bin/paozhu 
+CMD ./bin/paozhu

+ 147 - 43
frameworks/C++/paozhu/paozhu_benchmark/CMakeLists.txt

@@ -7,21 +7,27 @@ set(ENABLE_BOOST OFF CACHE BOOL "choose ON to enable")
 set(ENABLE_GD OFF CACHE BOOL "choose ON to enable")
 set(ENABLE_GD OFF CACHE BOOL "choose ON to enable")
 set(ENABLE_WIN_VCPKG OFF CACHE BOOL "choose ON to enable")
 set(ENABLE_WIN_VCPKG OFF CACHE BOOL "choose ON to enable")
 
 
-if (ENABLE_GD STREQUAL "ON")
-    list(FIND VCPKG_MANIFEST_FEATURES "gd" index)
-    if (index EQUAL -1)
-        message(STATUS "Auto append features: gd")
-        list(APPEND VCPKG_MANIFEST_FEATURES "gd")
-    endif ()
-endif ()
+if(ENABLE_VCPKG)
+    set(vcpkg_root $ENV{VCPKG_ROOT})
+    if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND vcpkg_root)
+        set(CMAKE_TOOLCHAIN_FILE "${vcpkg_root}/scripts/buildsystems/vcpkg.cmake")
+    endif()
+endif()
 
 
-if (ENABLE_BOOST STREQUAL "ON")
-    list(FIND VCPKG_MANIFEST_FEATURES "boost" index)
-    if (index EQUAL -1)
-        message(STATUS "Auto append features: boost")
-        list(APPEND VCPKG_MANIFEST_FEATURES "boost")
-    endif ()
-endif ()
+macro(auto_enable_vcpkg_feature opt feature)
+    if(${opt})
+        list(FIND VCPKG_MANIFEST_FEATURES ${feature} index)
+        if(index EQUAL -1)
+            message(STATUS "Auto append features: ${feature}")
+            list(APPEND VCPKG_MANIFEST_FEATURES ${feature})
+        endif()
+    endif()
+endmacro()
+
+if(ENABLE_VCPKG)
+  auto_enable_vcpkg_feature(ENABLE_GD "gd")
+  auto_enable_vcpkg_feature(ENABLE_BOOST "boost")
+endif()
 
 
 PROJECT(Paozhu_web_framework)
 PROJECT(Paozhu_web_framework)
 set(CMAKE_CXX_STANDARD 20)
 set(CMAKE_CXX_STANDARD 20)
@@ -59,7 +65,7 @@ endif ()
 if(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
 if(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
 
 
     if(CMAKE_SYSTEM_NAME MATCHES "Windows")
     if(CMAKE_SYSTEM_NAME MATCHES "Windows")
-        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASIO_STANDALONE -DDEBUG ${BOOST_OPEN} ${GD_OPEN}")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASIO_STANDALONE -DBENCHMARK -DDEBUG ${BOOST_OPEN} ${GD_OPEN}")
         if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
         if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
             set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
             set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
         elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
         elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
@@ -67,20 +73,20 @@ if(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
         endif ()
         endif ()
     else()
     else()
         set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra")
         set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra")
-        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread -g -fsanitize=address -DASIO_STANDALONE -DDEBUG ${BOOST_OPEN} ${GD_OPEN} -I/usr/local/include -I/usr/local/mysql/include   -I/usr/include -I/usr/include/mysql " )
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread -g -fsanitize=address -DASIO_STANDALONE -DBENCHMARK -DDEBUG ${BOOST_OPEN} ${GD_OPEN} -I/usr/local/include -I/usr/local/mysql/include   -I/usr/include -I/usr/include/mysql " )
     endif ()
     endif ()
     message("Debug mode:${CMAKE_CXX_FLAGS_DEBUG}")
     message("Debug mode:${CMAKE_CXX_FLAGS_DEBUG}")
 
 
 elseif(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Release"))
 elseif(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Release"))
 
 
     if (CMAKE_SYSTEM_NAME MATCHES "Windows")
     if (CMAKE_SYSTEM_NAME MATCHES "Windows")
-        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASIO_STANDALONE ${BOOST_OPEN} ${GD_OPEN} -O3")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DASIO_STANDALONE ${BOOST_OPEN} ${GD_OPEN} -DBENCHMARK  -O3")
         if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
         if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
             set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread")
             set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread")
         endif ()
         endif ()
     else ()
     else ()
         set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -Wextra -O3")
         set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -Wextra -O3")
-        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread  -DASIO_STANDALONE ${BOOST_OPEN} ${GD_OPEN}  -I/usr/local/include -I/usr/local/mysql/include -I/usr/include -I/usr/include/mysql  " )
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread  -DASIO_STANDALONE ${BOOST_OPEN} ${GD_OPEN} -DBENCHMARK -I/usr/local/include -I/usr/local/mysql/include -I/usr/include -I/usr/include/mysql  " )
         file(MAKE_DIRECTORY /usr/local/etc/paozhu)
         file(MAKE_DIRECTORY /usr/local/etc/paozhu)
         file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/conf/ DESTINATION /usr/local/etc/paozhu/)
         file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/conf/ DESTINATION /usr/local/etc/paozhu/)
     endif ()
     endif ()
@@ -89,7 +95,7 @@ elseif(${mode} AND (CMAKE_BUILD_TYPE STREQUAL "Release"))
 else()
 else()
     set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra")
     set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra")
     message("Debug mode:${CMAKE_CXX_FLAGS_DEBUG}")
     message("Debug mode:${CMAKE_CXX_FLAGS_DEBUG}")
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread  -g -fsanitize=address  -DASIO_STANDALONE -DDEBUG ${BOOST_OPEN} ${GD_OPEN} -I/usr/local/include -I/usr/local/mysql/include   -I/usr/include  -I/usr/include/mysql  " )
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread  -g -fsanitize=address  -DASIO_STANDALONE -DBENCHMARK -DDEBUG ${BOOST_OPEN} ${GD_OPEN} -I/usr/local/include -I/usr/local/mysql/include   -I/usr/include  -I/usr/include/mysql  " )
 
 
     if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
     if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
@@ -117,13 +123,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/viewsrc/include)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/websockets/include)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/websockets/include)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
 
 
-if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_empty)
-  file(REMOVE_RECURSE ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_empty)
-endif ()
-#EXECUTE_PROCESS(COMMAND rm ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_empty)
+if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_pre)
+  file(REMOVE_RECURSE ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_pre)
+endif()
 set(PAOZHU_PRE paozhu_pre)
 set(PAOZHU_PRE paozhu_pre)
 add_executable(${PAOZHU_PRE} ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli/autopickmethod.cpp ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpserver/src/md5.cpp)
 add_executable(${PAOZHU_PRE} ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli/autopickmethod.cpp ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpserver/src/md5.cpp)
-add_executable(paozhu_empty ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli/autoemptymethod.cpp)
 
 
 
 
 
 
@@ -138,6 +142,22 @@ file(GLOB_RECURSE src_list ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
 
 
 foreach(cppfile IN LISTS controller_list)
 foreach(cppfile IN LISTS controller_list)
   string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/controller/src/" "" cppfilename ${cppfile})
   string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/controller/src/" "" cppfilename ${cppfile})
+  string(FIND ${cppfilename} "/" strpos)
+  if(${strpos} GREATER_EQUAL "0" )
+      string(REGEX MATCHALL "([A-Za-z0-9._-]+)/" npaths ${cppfilename} )
+      set(fullpaths "")
+      string(APPEND fullpaths "${CMAKE_CURRENT_SOURCE_DIR}/controller/include/")
+      foreach(onepathname ${npaths})
+            string(REPLACE "/" "" toucpath ${onepathname})
+            string(APPEND fullpaths ${toucpath})
+            if (IS_DIRECTORY "${fullpaths}") 
+            else()
+                  message("mkdir ${fullpaths}") 
+                  file(MAKE_DIRECTORY "${fullpaths}")
+            endif()
+            string(APPEND fullpaths "/")
+      endforeach()
+  endif()
   string(REGEX REPLACE ".cpp" "" cppbasename ${cppfilename})
   string(REGEX REPLACE ".cpp" "" cppbasename ${cppfilename})
 #  message(${cppbasename})
 #  message(${cppbasename})
   if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/controller/include/${cppbasename}.h")
   if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/controller/include/${cppbasename}.h")
@@ -169,6 +189,7 @@ include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/models)
 include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/controller/include)
 include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/controller/include)
 include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/libs)
 include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/libs)
 include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/include)
 include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/include)
+include_sub_directories_recursively(${CMAKE_CURRENT_SOURCE_DIR}/common)
 
 
 add_executable(paozhu_cli ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli/http_cli.cpp)
 add_executable(paozhu_cli ${CMAKE_CURRENT_SOURCE_DIR}/vendor/httpcli/http_cli.cpp)
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
@@ -181,15 +202,12 @@ else()
 endif()
 endif()
 
 
 if (ENABLE_WIN_VCPKG STREQUAL "ON")
 if (ENABLE_WIN_VCPKG STREQUAL "ON")
-else ()
+else()
 add_custom_command(
 add_custom_command(
-    TARGET paozhu_empty paozhu
-    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_pre
-    PRE_BUILD
+    TARGET paozhu_pre POST_BUILD
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
     COMMAND echo "-- controls method --"
     COMMAND echo "-- controls method --"
     COMMAND ${PAOZHU_PRE} ${CMAKE_CURRENT_SOURCE_DIR}/
     COMMAND ${PAOZHU_PRE} ${CMAKE_CURRENT_SOURCE_DIR}/
-    COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_SOURCE_DIR}/bin/paozhu_empty
     )
     )
 endif()
 endif()
 
 
@@ -265,7 +283,7 @@ else ()
 
 
 if(USE_STANDALONE_ASIO)
 if(USE_STANDALONE_ASIO)
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
-set(ASIO_PATH "/usr/local/opt/asio/include" "/usr/local/include")
+set(ASIO_PATH "/usr/local/opt/asio/include" "/usr/local/include" "/opt/homebrew/opt/asio" ${CMAKE_CURRENT_SOURCE_DIR}/asio)
 else()
 else()
 set(ASIO_PATH ${CMAKE_CURRENT_SOURCE_DIR}/asio "/usr/include")
 set(ASIO_PATH ${CMAKE_CURRENT_SOURCE_DIR}/asio "/usr/include")
 endif()
 endif()
@@ -324,19 +342,54 @@ if(ZLIB_FOUND)
   target_link_libraries(paozhu z)
   target_link_libraries(paozhu z)
 endif()
 endif()
 
 
-find_path(MYSQL_ROOT_DIR mysql)
+
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+  if (IS_DIRECTORY "/usr/local/mysql/include")
+  MESSAGE( STATUS "/usr/local/mysql")
+      set(MYSQL_INCLUDE_DIR "/usr/local/mysql/include")
+      include_sub_directories_recursively(/usr/local/mysql/include)
+  endif()
+ 
+  if (IS_DIRECTORY "/usr/local/opt/mysql-client")
+        MESSAGE( STATUS "/usr/local/opt/mysql-client")
+      set(MYSQL_INCLUDE_DIR "/usr/local/opt/mysql-client/include")
+      include_sub_directories_recursively(/usr/local/opt/mysql-client/include)
+  endif()
+  
+  if (IS_DIRECTORY "/opt/homebrew/opt/mysql")
+        MESSAGE( STATUS "/opt/homebrew/opt/mysql")
+      set(MYSQL_INCLUDE_DIR "/opt/homebrew/opt/mysql/include")
+      include_sub_directories_recursively(/opt/homebrew/opt/mysql/include)
+  endif()
+  
+  
+  if (IS_DIRECTORY "/opt/homebrew/opt/mysql-client")
+        MESSAGE( STATUS "/opt/homebrew/opt/mysql-client")
+      set(MYSQL_INCLUDE_DIR "/opt/homebrew/opt/mysql-client/include")
+      include_sub_directories_recursively(/opt/homebrew/opt/mysql-client/include)
+  endif()
+  MESSAGE( STATUS "MYSQL_ROOT_DIR = ${MYSQL_ROOT_DIR} ")
+else()  
+ find_path(MYSQL_ROOT_DIR mysql)
+endif()
+
+
+FIND_PATH(MYSQL_INCLUDE_DIR NAMES mysql.h
+  PATHS /usr/local/include/mysql /usr/include/mysql /opt/homebrew/opt/mysql/include /usr/local/opt/mysql-client/include /opt/homebrew/opt/mysql-client/include
+)
+
 MESSAGE( STATUS "MYSQL_ROOT_DIR = ${MYSQL_ROOT_DIR} ")
 MESSAGE( STATUS "MYSQL_ROOT_DIR = ${MYSQL_ROOT_DIR} ")
 find_package_handle_standard_args(mysql REQUIRED_VARS MYSQL_ROOT_DIR)
 find_package_handle_standard_args(mysql REQUIRED_VARS MYSQL_ROOT_DIR)
 
 
-FIND_PATH(MYSQL_INCLUDE_DIR mysql.h
-  /usr/local/include/mysql
-  /usr/include/mysql
-  /usr/local/mysql/include
-)
+
+if(NOT MYSQL_INCLUDE_DIR)
+  message(STATUS "Could not find \"mysql.h\" from searching ")
+endif()
+
 SET(MYSQL_NAMES mysqlclient)
 SET(MYSQL_NAMES mysqlclient)
 FIND_LIBRARY(MYSQL_LIBRARY
 FIND_LIBRARY(MYSQL_LIBRARY
   NAMES ${MYSQL_NAMES}
   NAMES ${MYSQL_NAMES}
-  PATHS /usr/lib /usr/local/lib /usr/local/mysql/lib
+  PATHS /usr/lib /usr/local/lib /usr/local/mysql/lib /usr/local/opt/mysql/lib /opt/homebrew/opt/mysql/lib /opt/homebrew/opt/mysql-client/lib
   PATH_SUFFIXES mysql
   PATH_SUFFIXES mysql
 )
 )
 
 
@@ -371,7 +424,17 @@ if(ENABLE_GD STREQUAL "ON")
 message("---ENABLE_GD-----")
 message("---ENABLE_GD-----")
 
 
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
-  set(GD_ROOT_DIR "/usr/local/opt/gd/lib")
+  
+  if (IS_DIRECTORY "/usr/local/opt/gd/lib")
+        MESSAGE( STATUS "/usr/local/opt/gd/lib")
+      set(GD_ROOT_DIR "/usr/local/opt/gd/lib")
+      include_sub_directories_recursively(/usr/local/opt/gd/include)
+  endif()
+  if (IS_DIRECTORY "/opt/homebrew/opt/gd/lib")
+        MESSAGE( STATUS "/opt/homebrew/opt/gd/lib")
+      set(GD_ROOT_DIR "/opt/homebrew/opt/gd/lib")
+      include_sub_directories_recursively(/opt/homebrew/opt/gd/include)
+  endif()
 else()
 else()
   set(GD_ROOT_DIR "${sys_so_path}")
   set(GD_ROOT_DIR "${sys_so_path}")
 endif()
 endif()
@@ -393,7 +456,18 @@ endif()
 message(STATUS "GD Graphics Library  at: ${GD_LIB_DIR}")
 message(STATUS "GD Graphics Library  at: ${GD_LIB_DIR}")
 
 
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
-set(QR_ROOT_DIR "/usr/local/opt/qrencode/lib")
+
+  if (IS_DIRECTORY "/usr/local/opt/qrencode/lib")
+        MESSAGE( STATUS "/usr/local/opt/qrencode/lib")
+      set(QR_ROOT_DIR "/usr/local/opt/qrencode/lib")
+      include_sub_directories_recursively(/usr/local/opt/qrencode/include)
+  endif()
+  if (IS_DIRECTORY "/opt/homebrew/opt/qrencode/lib")
+        MESSAGE( STATUS "/opt/homebrew/opt/qrencode/lib")
+      set(QR_ROOT_DIR "/opt/homebrew/opt/qrencode/lib")
+      include_sub_directories_recursively(/opt/homebrew/opt/qrencode/include)
+  endif()
+  
 else()
 else()
 set(QR_ROOT_DIR "${sys_so_path}")
 set(QR_ROOT_DIR "${sys_so_path}")
 endif()
 endif()
@@ -422,7 +496,18 @@ target_link_libraries(paozhu ${GD_LIB_DIR})
 target_link_libraries(paozhu ${QR_LIB_DIR})
 target_link_libraries(paozhu ${QR_LIB_DIR})
 
 
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
-set(PNG_ROOT_DIR "/usr/local/opt/libpng/lib")
+
+  if (IS_DIRECTORY "/usr/local/opt/libpng/lib")
+        MESSAGE( STATUS "/usr/local/opt/libpng/lib")
+      set(PNG_ROOT_DIR "/usr/local/opt/libpng/lib")
+      include_sub_directories_recursively(/usr/local/opt/libpng/include)
+  endif()
+  if (IS_DIRECTORY "/opt/homebrew/opt/libpng/lib")
+        MESSAGE( STATUS "/opt/homebrew/opt/libpng/lib")
+      set(PNG_ROOT_DIR "/opt/homebrew/opt/libpng/lib")
+      include_sub_directories_recursively(/opt/homebrew/opt/libpng/include)
+  endif()
+  
 else()
 else()
 set(PNG_ROOT_DIR "${sys_so_path}")
 set(PNG_ROOT_DIR "${sys_so_path}")
 endif()
 endif()
@@ -435,7 +520,18 @@ find_library(PNG_LIB_DIR
 target_link_libraries(paozhu ${PNG_LIB_DIR})
 target_link_libraries(paozhu ${PNG_LIB_DIR})
 
 
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
-  set(FREETYPE_ROOT_DIR "/usr/local/opt/freetype/lib")
+  
+    if (IS_DIRECTORY "/usr/local/opt/freetype/lib")
+        MESSAGE( STATUS "/usr/local/opt/freetype/lib")
+      set(FREETYPE_ROOT_DIR "/usr/local/opt/freetype/lib")
+      include_sub_directories_recursively(/usr/local/opt/freetype/include)
+  endif()
+  if (IS_DIRECTORY "/opt/homebrew/opt/freetype/lib")
+        MESSAGE( STATUS "/opt/homebrew/opt/freetype/lib")
+      set(FREETYPE_ROOT_DIR "/opt/homebrew/opt/freetype/lib")
+      include_sub_directories_recursively(/opt/homebrew/opt/freetype/include)
+  endif()
+  
 else()
 else()
   set(FREETYPE_ROOT_DIR "${sys_so_path}")
   set(FREETYPE_ROOT_DIR "${sys_so_path}")
 endif()
 endif()
@@ -450,7 +546,15 @@ target_link_libraries(paozhu ${FREETYPE_LIB_DIR})
 endif()
 endif()
 
 
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
 if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
-  set(BROTLI_ROOT_DIR "/usr/local/opt/brotli/lib")
+  if (IS_DIRECTORY "/usr/local/opt/brotli/lib")
+      set(BROTLI_ROOT_DIR "/usr/local/opt/brotli/lib")
+      INCLUDE_DIRECTORIES("/usr/local/opt/brotli/include")
+  endif()
+#  set(BROTLI_ROOT_DIR "/usr/local/opt/brotli/lib")
+  if (IS_DIRECTORY "/opt/homebrew/opt/brotli/lib")
+      set(BROTLI_ROOT_DIR "/opt/homebrew/opt/brotli/lib")
+      INCLUDE_DIRECTORIES("/opt/homebrew/opt/brotli/include")
+  endif()
 else()
 else()
   set(BROTLI_ROOT_DIR "${sys_so_path}")
   set(BROTLI_ROOT_DIR "${sys_so_path}")
 endif()
 endif()
@@ -505,4 +609,4 @@ endif ()
 if (CMAKE_SYSTEM_NAME MATCHES "Windows")
 if (CMAKE_SYSTEM_NAME MATCHES "Windows")
    target_link_libraries(paozhu ws2_32)
    target_link_libraries(paozhu ws2_32)
    target_link_libraries(paozhu_cli ws2_32)
    target_link_libraries(paozhu_cli ws2_32)
-endif ()
+endif ()

+ 10 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/autocontrolmethod.hpp

@@ -44,6 +44,16 @@ namespace http
 
 
 
 
     }
     }
+    
+    void _initauto_domain_httpmethodregto(std::map<std::string, std::map<std::string, regmethold_t>> &domain_methodcallback)
+    {
+        struct regmethold_t temp;
+        std::map<std::string, regmethold_t> methodcallback;
+        std::map<std::string, std::map<std::string, regmethold_t>>::iterator domain_iterator;
+    
+
+    }
+    
 }
 }
 
 
 #endif
 #endif

+ 40 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/autorestfulpaths.hpp

@@ -0,0 +1,40 @@
+
+#ifndef __HTTP_AUTO_REG_CONTROL_HTTPRESTFUL_HPP
+#define __HTTP_AUTO_REG_CONTROL_HTTPRESTFUL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "httppeer.h" 
+
+
+
+namespace http
+{
+  void _initauto_control_httprestful_paths(std::map<std::string, std::vector<std::string>>  &restfulmethod)
+  {
+    
+
+        if(restfulmethod.size())
+        {}
+        
+
+  }
+    
+    void _initauto_domain_httprestful_paths(std::map<std::string,std::map<std::string, std::vector<std::string>>>  &restfulmethod)
+    {
+        std::map<std::string, std::vector<std::string>> temp_path;
+        std::map<std::string,std::map<std::string, std::vector<std::string>>>::iterator domain_iterator;  
+
+        domain_iterator=restfulmethod.begin();
+        temp_path.clear();
+        
+
+    }
+    
+}
+
+#endif
+
+    

+ 9 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/cost_define.h

@@ -0,0 +1,9 @@
+#pragma once
+#ifndef _CONST_DEFINE_FUNC_H
+#define _CONST_DEFINE_FUNC_H
+
+#define CONST_MONEY_PART 1000000
+#define CONST_HTTP_HEADER_BODY_SIZE 16384
+#define CONST_PHP_BODY_POST_SIZE 16777216
+
+#endif

+ 39 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/httphook.cpp

@@ -0,0 +1,39 @@
+#include <iostream>
+#include <list>
+#include <map>
+#include <mutex>
+#include <queue>
+#include <string>
+#include <thread>
+#include <memory>
+#include <string_view>
+#include "httppeer.h"
+namespace http
+{
+std::map<std::string, bool> _block_ip_tables;
+std::map<std::string, bool> _block_host_tables;
+bool check_blockip(const std::string &client_ip)
+{
+    if (client_ip.size() > 0)
+    {
+        return false;
+    }
+    return false;
+}
+bool hook_host_http1(std::shared_ptr<httppeer> peer)
+{
+    if (peer->host.size() > 0)
+    {
+        return false;
+    }
+    return false;
+}
+bool hook_host_http2(std::shared_ptr<httppeer> peer)
+{
+    if (peer->host.size() > 0)
+    {
+        return false;
+    }
+    return false;
+}
+}// namespace http

+ 19 - 0
frameworks/C++/paozhu/paozhu_benchmark/common/json_reflect_headers.h

@@ -0,0 +1,19 @@
+#pragma once
+#include <map>
+#include "httppeer.h"
+#include "websockets.h"
+#include "mywebsockets.hpp"
+#include "websockets_callback.h"
+namespace http
+{
+void _initwebsocketmethodregto(WEBSOCKET_REG &methodcallback)
+{
+
+    methodcallback.emplace("wstest", [](std::weak_ptr<httppeer> p) -> std::shared_ptr<websockets_api>
+                           { return http::mywebsockets::create(p); });
+    //    methodcallback.emplace("looptest",[](std::weak_ptr<clientpeer> p)->std::shared_ptr<websockets_api>{
+    //      return http::loopwebsockets::create(p);
+    //   });
+}
+
+}// namespace http

+ 8 - 2
frameworks/C++/paozhu/paozhu_benchmark/conf/server.conf

@@ -3,7 +3,7 @@ threadmax=1024
 threadmin=5
 threadmin=5
 httpport=8888
 httpport=8888
 httpsport=4430
 httpsport=4430
-cothreadnum=8 ;Coroutines run on thread num
+cothreadnum=16 ;Coroutines run on thread num
 
 
 http2_enable=0
 http2_enable=0
 debug_enable=1
 debug_enable=1
@@ -13,6 +13,9 @@ certificate_chain_file=localhost.pem
 private_key_file=localhost.key
 private_key_file=localhost.key
 tmp_dh_file=dh4096.pem
 tmp_dh_file=dh4096.pem
 reboot_password=e10adc3949ba59abbe56e057f20f883e ;md5(md5("123456")+"rand_char"+md5("123456"))
 reboot_password=e10adc3949ba59abbe56e057f20f883e ;md5(md5("123456")+"rand_char"+md5("123456"))
+reboot_cron =w1h5 ;MDSW+Hhours reboot process M month D day S season (1 4 7 10) W week  
+clean_cron  =m5t600 ;5-minute interval clean 600 seconds ago inactive connection
+links_restart_process =n9998877ts1te5 ;More than 15000 connections, restart the process from 1:00 am to 5:00 am
 session_type=1 ;session save type 0.file 1.memory 2.redis 3.memcache 4.reserve
 session_type=1 ;session save type 0.file 1.memory 2.redis 3.memcache 4.reserve
 static_file_compress_cache=1 ;1 enable, Cache static file compress(gzip,br) content to cache directory 
 static_file_compress_cache=1 ;1 enable, Cache static file compress(gzip,br) content to cache directory 
 modelspath=/root/benchmark/models
 modelspath=/root/benchmark/models
@@ -39,4 +42,7 @@ method_after=
 show_visitinfo=0
 show_visitinfo=0
 upload_max_size=16777216
 upload_max_size=16777216
 
 
-
+siteid=0
+groupid=0
+alias_domain=
+init_func=

+ 189 - 189
frameworks/C++/paozhu/paozhu_benchmark/controller/src/techempower.cpp

@@ -6,236 +6,236 @@
 #include <chrono>
 #include <chrono>
 #include "httppeer.h"
 #include "httppeer.h"
 #include "techempower.h"
 #include "techempower.h"
-#include "techempower_json.h"
 #include "datetime.h"
 #include "datetime.h"
 #include "func.h"
 #include "func.h"
 #include "pzcache.h"
 #include "pzcache.h"
 #include "json_reflect_headers.h"
 #include "json_reflect_headers.h"
+#include "techempower_json.h"
 namespace http
 namespace http
 {
 {
-//@urlpath(null,plaintext)
-std::string techempowerplaintext(std::shared_ptr<httppeer> peer)
-{
-    peer->type("text/plain; charset=UTF-8");
-    peer->set_header("Date", get_gmttime());
-    peer->output = "Hello, World!";
-    return "";
-}
-
-//@urlpath(null,json)
-std::string techempowerjson(std::shared_ptr<httppeer> peer)
-{
-    peer->type("application/json; charset=UTF-8");
-    peer->set_header("Date", get_gmttime());
-    struct techempower_outjson_t a;
-    a.message    = "Hello, World!";
-    peer->output = json_encode(a);
-    return "";
-}
-
-//@urlpath(null,db)
-std::string techempowerdb(std::shared_ptr<httppeer> peer)
-{
-    peer->type("application/json; charset=UTF-8");
-    peer->set_header("Date", get_gmttime());
-    auto myworld        = orm::World();
-    unsigned int rd_num = rand_range(1, 10000);
-    myworld.get_one(rd_num);
-
-    peer->output = myworld.data_tojson();
-    return "";
-}
-
-//@urlpath(null,queries)
-std::string techempowerqueries(std::shared_ptr<httppeer> peer)
-{
-    peer->type("application/json; charset=UTF-8");
-    peer->set_header("Date", get_gmttime());
-
-    unsigned int get_num = peer->get["queries"].to_int();
-    if (get_num == 0)
+    //@urlpath(null,plaintext)
+    std::string techempowerplaintext(std::shared_ptr<httppeer> peer)
     {
     {
-        get_num = 1;
+        peer->type("text/plain; charset=UTF-8");
+        peer->set_header("Date", get_gmttime());
+        peer->output = "Hello, World!";
+        return "";
     }
     }
-    else if (get_num > 500)
+
+    //@urlpath(null,json)
+    std::string techempowerjson(std::shared_ptr<httppeer> peer)
     {
     {
-        get_num = 500;
+        peer->type("application/json; charset=UTF-8");
+        peer->set_header("Date", get_gmttime());
+        struct techempower_outjson_t a;
+        a.message = "Hello, World!";
+        peer->output = json_encode(a);
+        return "";
     }
     }
-    auto myworld = orm::World();
-    myworld.record.reserve(get_num);
-    for (unsigned int i = 0; i < get_num; i++)
+
+    //@urlpath(null,db)
+    std::string techempowerdb(std::shared_ptr<httppeer> peer)
     {
     {
-        myworld.wheresql.clear();
+        peer->type("application/json; charset=UTF-8");
+        peer->set_header("Date", get_gmttime());
+        auto myworld = orm::World();
         unsigned int rd_num = rand_range(1, 10000);
         unsigned int rd_num = rand_range(1, 10000);
-        myworld.where("id", rd_num).fetch_append();
-    }
-
-    peer->output = myworld.to_json();
-    return "";
-}
+        myworld.get_one(rd_num);
 
 
-//@urlpath(null,fortunes)
-std::string techempowerfortunes(std::shared_ptr<httppeer> peer)
-{
-    peer->type("text/html; charset=UTF-8");
-    peer->set_header("Date", get_gmttime());
-
-    auto myfortune = orm::Fortune();
-    myfortune.fetch();
-    myfortune.data.id      = 0;
-    myfortune.data.message = "Additional fortune added at request time.";
-    myfortune.record.push_back(myfortune.data);
-
-    std::sort(myfortune.record.begin(), myfortune.record.end(), [](const auto &lhs, const auto &rhs)
-              { return lhs.message < rhs.message; });
-    peer->val["list"].set_array();
-    OBJ_ARRAY item;
-    for (unsigned int i = 0; i < myfortune.record.size(); i++)
-    {
-        item["id"]      = myfortune.record[i].id;
-        item["message"] = html_encode(myfortune.record[i].message);
-        peer->val["list"].push(item);
+        peer->output = myworld.data_tojson();
+        return "";
     }
     }
 
 
-    peer->view("techempower/fortunes");
-    return "";
-}
+    //@urlpath(null,queries)
+    std::string techempowerqueries(std::shared_ptr<httppeer> peer)
+    {
+        peer->type("application/json; charset=UTF-8");
+        peer->set_header("Date", get_gmttime());
 
 
-//@urlpath(null,updates)
-std::string techempowerupdates(std::shared_ptr<httppeer> peer)
-{
-    peer->type("application/json; charset=UTF-8");
-    peer->set_header("Date", get_gmttime());
-    unsigned int get_num = peer->get["queries"].to_int();
+        unsigned int get_num = peer->get["queries"].to_int();
+        if (get_num == 0)
+        {
+            get_num = 1;
+        }
+        else if (get_num > 500)
+        {
+            get_num = 500;
+        }
+        auto myworld = orm::World();
+        myworld.record.reserve(get_num);
+        for (unsigned int i = 0; i < get_num; i++)
+        {
+            myworld.wheresql.clear();
+            unsigned int rd_num = rand_range(1, 10000);
+            myworld.where("id", rd_num).fetch_append();
+        }
 
 
-    if (get_num == 0)
-    {
-        get_num = 1;
-    }
-    else if (get_num > 500)
-    {
-        get_num = 500;
+        peer->output = myworld.to_json();
+        return "";
     }
     }
-    auto myworld = orm::World();
-    myworld.record.clear();
-    myworld.record.reserve(get_num);
-    for (unsigned int i = 0; i < get_num; i++)
+
+    //@urlpath(null,fortunes)
+    std::string techempowerfortunes(std::shared_ptr<httppeer> peer)
     {
     {
-        myworld.wheresql.clear();
-        myworld.where("id", rand_range(1, 10000)).fetch_append();
-        if (myworld.effect() > 0)
+        peer->type("text/html; charset=UTF-8");
+        peer->set_header("Date", get_gmttime());
+
+        auto myfortune = orm::Fortune();
+        myfortune.fetch();
+        myfortune.data.id = 0;
+        myfortune.data.message = "Additional fortune added at request time.";
+        myfortune.record.push_back(myfortune.data);
+
+        std::sort(myfortune.record.begin(), myfortune.record.end(), [](const auto &lhs, const auto &rhs)
+                  { return lhs.message < rhs.message; });
+        peer->val["list"].set_array();
+        OBJ_ARRAY item;
+        for (unsigned int i = 0; i < myfortune.record.size(); i++)
         {
         {
-            unsigned int j                 = myworld.record.size() - 1;
-            myworld.data.randomnumber      = rand_range(1, 10000);
-            myworld.record[j].randomnumber = myworld.data.randomnumber;
-            myworld.update("randomnumber");
+            item["id"] = myfortune.record[i].id;
+            item["message"] = html_encode(myfortune.record[i].message);
+            peer->val["list"].push(item);
         }
         }
-    }
-    peer->output = myworld.to_json();
-    return "";
-}
 
 
-//@urlpath(null,cached-queries)
-std::string techempowercached_queries(std::shared_ptr<httppeer> peer)
-{
-    peer->type("application/json; charset=UTF-8");
-    peer->set_header("Date", get_gmttime());
+        peer->view("techempower/fortunes");
+        return "";
+    }
 
 
-    unsigned int get_num = peer->get["count"].to_int();
-    if (get_num == 0)
+    //@urlpath(null,updates)
+    std::string techempowerupdates(std::shared_ptr<httppeer> peer)
     {
     {
-        get_num = 1;
+        peer->type("application/json; charset=UTF-8");
+        peer->set_header("Date", get_gmttime());
+        unsigned int get_num = peer->get["queries"].to_int();
+
+        if (get_num == 0)
+        {
+            get_num = 1;
+        }
+        else if (get_num > 500)
+        {
+            get_num = 500;
+        }
+        auto myworld = orm::World();
+        myworld.record.clear();
+        myworld.record.reserve(get_num);
+        for (unsigned int i = 0; i < get_num; i++)
+        {
+            myworld.wheresql.clear();
+            myworld.where("id", rand_range(1, 10000)).fetch_append();
+            if (myworld.effect() > 0)
+            {
+                unsigned int j = myworld.record.size() - 1;
+                myworld.data.randomnumber = rand_range(1, 10000);
+                myworld.record[j].randomnumber = myworld.data.randomnumber;
+                myworld.update("randomnumber");
+            }
+        }
+        peer->output = myworld.to_json();
+        return "";
     }
     }
-    else if (get_num > 500)
+
+    //@urlpath(null,cached-queries)
+    std::string techempowercached_queries(std::shared_ptr<httppeer> peer)
     {
     {
-        get_num = 500;
-    }
-    auto myworld          = orm::World();
-    std::string mycacheid = "alldatacache";
+        peer->type("application/json; charset=UTF-8");
+        peer->set_header("Date", get_gmttime());
 
 
-    pzcache<std::vector<orm::worldbase::meta>> &temp_cache = pzcache<std::vector<orm::worldbase::meta>>::conn();
+        unsigned int get_num = peer->get["count"].to_int();
+        if (get_num == 0)
+        {
+            get_num = 1;
+        }
+        else if (get_num > 500)
+        {
+            get_num = 500;
+        }
+        auto myworld = orm::World();
+        std::string mycacheid = "alldatacache";
 
 
-    std::vector<orm::worldbase::meta> allcachedata_array;
-    allcachedata_array.reserve(10000);
-    //create rand data to cache
-    if (temp_cache.check(mycacheid) > -1)
-    {
-        allcachedata_array = temp_cache.get(mycacheid);
-    }
-    else
-    {
-        allcachedata_array.resize(10000);
-        for (unsigned int i = 0; i < 10000; i++)
+        pzcache<std::vector<orm::worldbase::meta>> &temp_cache = pzcache<std::vector<orm::worldbase::meta>>::conn();
+
+        std::vector<orm::worldbase::meta> allcachedata_array;
+        allcachedata_array.reserve(10000);
+        // create rand data to cache
+        if (temp_cache.check(mycacheid) > -1)
         {
         {
-            allcachedata_array[i].id           = i + 1;
-            allcachedata_array[i].randomnumber = rand_range(1, 10000);
+            allcachedata_array = temp_cache.get(mycacheid);
         }
         }
-        temp_cache.save(mycacheid, allcachedata_array, 120);
-    }
-    //get rand data from cache
-    mycacheid = "my" + std::to_string(get_num);
-    myworld.record.reserve(get_num);
-    if (temp_cache.check(mycacheid) > -1)
-    {
-        myworld.record = temp_cache.get(mycacheid);
-    }
-    else
-    {
-        if (allcachedata_array.size() == 10000)
+        else
         {
         {
-            for (unsigned int i = 0; i < get_num; i++)
+            allcachedata_array.resize(10000);
+            for (unsigned int i = 0; i < 10000; i++)
             {
             {
-                unsigned int temp_rid = rand_range(0, 9999);
-                myworld.record.push_back(allcachedata_array[temp_rid]);
+                allcachedata_array[i].id = i + 1;
+                allcachedata_array[i].randomnumber = rand_range(1, 10000);
             }
             }
+            temp_cache.save(mycacheid, allcachedata_array, 120);
+        }
+        // get rand data from cache
+        mycacheid = "my" + std::to_string(get_num);
+        myworld.record.reserve(get_num);
+        if (temp_cache.check(mycacheid) > -1)
+        {
+            myworld.record = temp_cache.get(mycacheid);
+        }
+        else
+        {
+            if (allcachedata_array.size() == 10000)
+            {
+                for (unsigned int i = 0; i < get_num; i++)
+                {
+                    unsigned int temp_rid = rand_range(0, 9999);
+                    myworld.record.push_back(allcachedata_array[temp_rid]);
+                }
+            }
+            temp_cache.save(mycacheid, myworld.record, 120);
         }
         }
-        temp_cache.save(mycacheid, myworld.record, 120);
-    }
-
-    peer->output = myworld.to_json();
-    return "";
-}
 
 
-//@urlpath(null,cached-db)
-std::string techempowercached_db(std::shared_ptr<httppeer> peer)
-{
-    peer->type("application/json; charset=UTF-8");
-    peer->set_header("Date", get_gmttime());
-    //this test from database to cache
-    unsigned int get_num = peer->get["count"].to_int();
-    if (get_num == 0)
-    {
-        get_num = 1;
+        peer->output = myworld.to_json();
+        return "";
     }
     }
-    else if (get_num > 500)
+
+    //@urlpath(null,cached-db)
+    std::string techempowercached_db(std::shared_ptr<httppeer> peer)
     {
     {
-        get_num = 500;
-    }
-    auto myworld          = orm::World();
-    std::string mycacheid = "my" + std::to_string(get_num);
+        peer->type("application/json; charset=UTF-8");
+        peer->set_header("Date", get_gmttime());
+        // this test from database to cache
+        unsigned int get_num = peer->get["count"].to_int();
+        if (get_num == 0)
+        {
+            get_num = 1;
+        }
+        else if (get_num > 500)
+        {
+            get_num = 500;
+        }
+        auto myworld = orm::World();
+        std::string mycacheid = "my" + std::to_string(get_num);
 
 
-    pzcache<std::vector<orm::worldbase::meta>> &temp_cache = pzcache<std::vector<orm::worldbase::meta>>::conn();
+        pzcache<std::vector<orm::worldbase::meta>> &temp_cache = pzcache<std::vector<orm::worldbase::meta>>::conn();
 
 
-    myworld.record.reserve(get_num);
-    if (temp_cache.check(mycacheid) > -1)
-    {
-        myworld.record = temp_cache.get(mycacheid);
-    }
-    else
-    {
-        std::vector<unsigned int> cacheid;
-        for (unsigned int i = 0; i < get_num; i++)
+        myworld.record.reserve(get_num);
+        if (temp_cache.check(mycacheid) > -1)
+        {
+            myworld.record = temp_cache.get(mycacheid);
+        }
+        else
         {
         {
-            cacheid.push_back(rand_range(1, 10000));
+            std::vector<unsigned int> cacheid;
+            for (unsigned int i = 0; i < get_num; i++)
+            {
+                cacheid.push_back(rand_range(1, 10000));
+            }
+
+            std::string sqlstr = array_to_sql(cacheid);
+            myworld.whereIn("id", sqlstr).fetch();
+            temp_cache.save(mycacheid, myworld.record, 120);
         }
         }
 
 
-        std::string sqlstr = array_to_sql(cacheid);
-        myworld.whereIn("id", sqlstr).fetch();
-        temp_cache.save(mycacheid, myworld.record, 120);
+        peer->output = myworld.to_json();
+        return "";
     }
     }
 
 
-    peer->output = myworld.to_json();
-    return "";
-}
-
-}// namespace http
+} // namespace http

+ 1 - 0
frameworks/C++/paozhu/paozhu_benchmark/libs/types/techempower_json.h

@@ -6,6 +6,7 @@
 #include "json_reflect_headers.h"
 #include "json_reflect_headers.h"
 #include "unicode.h"
 #include "unicode.h"
 #include "func.h"
 #include "func.h"
+//This file is automatically created, do not edit it
 
 
 namespace http
 namespace http
 {
 {

+ 16 - 0
frameworks/C++/paozhu/paozhu_benchmark/models/Fortune.cpp

@@ -0,0 +1,16 @@
+#include "mysqlmodel.hpp" 
+#include "fortunebase.h"
+#include "Fortune.h"
+
+/* 如果此文件存在不会自动覆盖,没有则会自动生成。
+*If this file exists, it will not be overwritten automatically. If not, it will be generated automatically. */
+
+	 
+ namespace orm{
+ 
+
+			 Fortune::Fortune(std::string dbtag):mysqlclientDB(dbtag){}
+			 Fortune::Fortune():mysqlclientDB(){}
+
+
+	  }

+ 16 - 0
frameworks/C++/paozhu/paozhu_benchmark/models/World.cpp

@@ -0,0 +1,16 @@
+#include "mysqlmodel.hpp" 
+#include "worldbase.h"
+#include "World.h"
+
+/* 如果此文件存在不会自动覆盖,没有则会自动生成。
+*If this file exists, it will not be overwritten automatically. If not, it will be generated automatically. */
+
+	 
+ namespace orm{
+ 
+
+			 World::World(std::string dbtag):mysqlclientDB(dbtag){}
+			 World::World():mysqlclientDB(){}
+
+
+	  }

+ 16 - 0
frameworks/C++/paozhu/paozhu_benchmark/models/include/Fortune.h

@@ -0,0 +1,16 @@
+#ifndef ORM_DEFAULT_FORTUNE_H
+#define ORM_DEFAULT_FORTUNE_H
+#include "mysqlmodel.hpp" 
+#include "fortunebase.h"
+
+/* 如果此文件存在不会自动覆盖,没有则会自动生成。
+*If this file exists, it will not be overwritten automatically. If not, it will be generated automatically. */
+
+ namespace orm {
+		class Fortune : public mysqlclientDB<Fortune,fortunebase>{
+		 public:
+		 Fortune(std::string dbtag);
+		 Fortune();
+		};
+};
+#endif

+ 16 - 0
frameworks/C++/paozhu/paozhu_benchmark/models/include/World.h

@@ -0,0 +1,16 @@
+#ifndef ORM_DEFAULT_WORLD_H
+#define ORM_DEFAULT_WORLD_H
+#include "mysqlmodel.hpp" 
+#include "worldbase.h"
+
+/* 如果此文件存在不会自动覆盖,没有则会自动生成。
+*If this file exists, it will not be overwritten automatically. If not, it will be generated automatically. */
+
+ namespace orm {
+		class World : public mysqlclientDB<World,worldbase>{
+		 public:
+		 World(std::string dbtag);
+		 World();
+		};
+};
+#endif

+ 2687 - 0
frameworks/C++/paozhu/paozhu_benchmark/orm/include/fortunebase.h

@@ -0,0 +1,2687 @@
+#ifndef ORM_DEFAULT_FORTUNEBASEMATA_H
+#define ORM_DEFAULT_FORTUNEBASEMATA_H
+/*
+*This file is auto create from cli
+*本文件为自动生成 Fri, 26 Jan 2024 02:59:30 GMT
+***/
+#include <iostream>
+#include <cstdio>
+#include <sstream>
+#include <array>
+#include <map> 
+#include <string_view> 
+#include <string> 
+#include <vector>
+#include <ctime>
+#include <array>
+#include "mysql.h"
+namespace orm { 
+   
+    
+struct fortunebase
+{
+    struct meta{
+    unsigned  int id= 0; //
+ std::string message=""; //
+ } data;
+ std::vector<fortunebase::meta> record;
+std::string _rmstag="default";//this value must be default or tag value, tag in mysqlconnect config file .
+std::vector<unsigned char> _keypos{0x00};
+MYSQL_ROW _row;
+std::vector<fortunebase::meta>::iterator begin(){     return record.begin(); }
+std::vector<fortunebase::meta>::iterator end(){     return record.end(); }
+std::vector<fortunebase::meta>::const_iterator begin() const{     return record.begin(); }
+std::vector<fortunebase::meta>::const_iterator end() const{     return record.end(); }
+const std::array<std::string,2> colnames={"id","message"};
+const std::array<unsigned char,2> colnamestype= {3,253};
+std::string tablename="fortune";
+std::string modelname="Fortune";
+
+	  unsigned char findcolpos(const std::string &coln){
+            if(coln.size()==0)
+            {
+                return 255;
+            }
+		    unsigned char  bi=coln[0];
+         
+
+	         if(bi<91&&bi>64){
+				bi+=32;
+			}
+            switch(coln[0]){
+
+
+         case 'i':
+   	 return 0;
+break;
+case 'm':
+   	 return 1;
+break;
+
+             }
+             return 255;
+           }
+         
+    int size(){ return record.size(); }   
+
+    std::string getPKname(){ 
+       return "id";
+}
+
+      void record_reset()
+      {
+            record.clear();     
+      }
+      void data_reset(){
+     fortunebase::meta metatemp;    
+            data = metatemp; 
+      }
+      
+      std::string soft_remove_sql([[maybe_unused]] const std::string &fieldsql){
+          std::string temp;
+     
+         return temp;
+     }
+     void _setColnamevalue()
+      {
+        for(unsigned char i=0;i<_keypos.size();i++)
+        {
+            switch(_keypos[i]){
+        	case 0:
+		 try{
+			data.id=std::stoul(_row[i]);
+		}catch (...) { 
+			data.id=0;
+			 }
+			break;
+	case 1:
+		 try{
+			data.message.append((_row[i]==NULL?"":_row[i]));
+		}catch (...) { 
+			data.message.clear();
+			 }
+			break;
+	default:
+		 { }
+			
+
+                 }
+
+                 if(i>210){
+                     break;
+                 }
+          }
+   } 
+         void _addnewrowvalue(){
+           fortunebase::meta metatemp;   
+
+          for(unsigned char i=0;i<_keypos.size();i++){
+ 
+                 switch(_keypos[i]){
+
+        	case 0:
+		 try{
+			metatemp.id=std::stoul(_row[i]);
+		}catch (...) { 
+			metatemp.id=0;
+			 }
+			break;
+	case 1:
+		 try{
+			metatemp.message.append((_row[i]==NULL?"":_row[i]));
+		}catch (...) { 
+			metatemp.message.clear();
+			 }
+			break;
+	default:
+		 { }
+			
+
+                  }
+                 if(i>210){
+                     break;
+                 }
+          }
+           record.emplace_back(std::move(metatemp)); 
+   } 
+
+  inline  std::string stringaddslash(std::string &content){
+        std::string temp;
+        for(unsigned int i=0;i<content.size();i++){
+            if(content[i]=='\''){
+                temp.append("\\'");
+                continue;
+            }else if(content[i]=='"'){
+                temp.append("\\\"");
+                continue;
+            }else if(content[i]=='\\'){
+                temp.append("\\\\");
+                continue;
+            }
+            temp.push_back(content[i]);
+        }
+        return temp;
+   }  
+  inline  std::string jsonaddslash(std::string &content){
+        std::string temp;
+        for(unsigned int i=0;i<content.size();i++){
+            if(content[i]=='"'){
+                temp.append("\\\"");
+                continue;
+            }
+            else if(content[i]=='\\'){
+                temp.append("\\\\");
+                continue;
+            }
+            temp.push_back(content[i]);
+        }
+        return temp;
+   }  
+
+   std::string _makeinsertsql(){
+      unsigned int j=0;
+                std::ostringstream tempsql;
+                tempsql<<"INSERT INTO ";
+                    tempsql<<tablename;
+                   tempsql<<" (";
+                    for(;j<colnames.size();j++){
+                            if(j>0){
+                                tempsql<<"`,`";
+                            }else{
+                                tempsql<<"`";
+                            }
+                            tempsql<<colnames[j];
+                    }
+                    if(j>0){
+                        tempsql<<"`";
+                    }
+            tempsql<<") VALUES (";
+
+        if(data.id==0){
+tempsql<<"null";
+ }else{ 
+	tempsql<<std::to_string(data.id);
+}
+tempsql<<",'"<<stringaddslash(data.message)<<"'";
+tempsql<<")";
+
+     
+       return tempsql.str();
+   } 
+      
+      std::string _makerecordinsertsql( meta &insert_data){
+      unsigned int j=0;
+                std::ostringstream tempsql;
+                tempsql<<"INSERT INTO ";
+                    tempsql<<tablename;
+                   tempsql<<" (";
+                    for(;j<colnames.size();j++){
+                            if(j>0){
+                                tempsql<<"`,`";
+                            }else{
+                                tempsql<<"`";
+                            }
+                            tempsql<<colnames[j];
+                    }
+                    if(j>0){
+                        tempsql<<"`";
+                    }
+            tempsql<<") VALUES (";
+
+        if(insert_data.id==0){
+tempsql<<"null";
+ }else{ 
+	tempsql<<std::to_string(insert_data.id);
+}
+tempsql<<",'"<<stringaddslash(insert_data.message)<<"'";
+tempsql<<")";
+
+     
+       return tempsql.str();
+   } 
+       
+      std::string _makerecordinsertsql( std::vector<meta> &insert_data){
+      unsigned int j=0;
+                std::ostringstream tempsql;
+                tempsql<<"INSERT INTO ";
+                    tempsql<<tablename;
+                   tempsql<<" (";
+                    for(;j<colnames.size();j++){
+                            if(j>0){
+                                tempsql<<"`,`";
+                            }else{
+                                tempsql<<"`";
+                            }
+                            tempsql<<colnames[j];
+                    }
+                    if(j>0){
+                        tempsql<<"`";
+                    }
+            tempsql<<") VALUES ";
+
+    for(unsigned int i=0;i<insert_data.size();i++)
+    {
+		if(i>0)
+		{
+			tempsql<<",";	
+		}
+		tempsql<<"(";
+
+
+        	if(insert_data[i].id==0){
+	tempsql<<"null";
+	 }else{ 
+	tempsql<<std::to_string(insert_data[i].id);
+	}
+		tempsql<<",'"<<stringaddslash(insert_data[i].message)<<"'";
+		tempsql<<")";
+	 } 
+
+     
+       return tempsql.str();
+   } 
+       
+    std::string _makeupdatesql(const std::string &fileld){
+       //int j=0;
+            std::ostringstream tempsql;
+                 tempsql<<"UPDATE ";
+                 tempsql<<tablename;
+                 tempsql<<" SET ";
+
+            bool isall=false;
+            if(fileld.empty()){
+                isall=true;
+            }
+            if(isall){
+
+        if(data.id==0){
+	tempsql<<"`id`=0";
+ }else{ 
+	tempsql<<"`id`="<<std::to_string(data.id);
+}
+tempsql<<",`message`='"<<stringaddslash(data.message)<<"'";
+ }else{ 
+
+     
+  unsigned int jj=0;
+                  std::string keyname;
+                  std::vector<unsigned char> keypos;
+                  for(;jj<fileld.size();jj++){
+                        if(fileld[jj]==','){
+                                unsigned char bpos_i=findcolpos(keyname);
+                               keypos.emplace_back(bpos_i); 
+#ifdef DEBUG
+                    if (bpos_i == 254)
+                    {
+                        std::cout << "\033[1m\033[31m-----------\n"
+                                  << keyname << " not in " << tablename << " table Field.\n-----------\033[0m"
+                                  << std::endl;
+                    }
+#endif                               
+                               keyname.clear();
+                             continue;   
+                        }
+                        if(fileld[jj]==0x20){
+
+                             continue;   
+                        }
+                        keyname.push_back(fileld[jj]);
+
+                  }  
+                 if(keyname.size()>0){
+                                unsigned char bpos_i=findcolpos(keyname);
+ #ifdef DEBUG
+                    if (bpos_i == 254)
+                    {
+                        std::cout << "\033[1m\033[31m-----------\n"
+                                  << keyname << " not in " << tablename << " table Field.\n-----------\033[0m"
+                                  << std::endl;
+                    }
+#endif                                       
+                                keypos.emplace_back(bpos_i); 
+                                keyname.clear();
+                 }
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+
+         case 0:
+ if(jj>0){ tempsql<<","; } 
+if(data.id==0){
+	tempsql<<"`id`=0";
+ }else{ 
+	tempsql<<"`id`="<<std::to_string(data.id);
+}
+ break;
+ case 1:
+ if(jj>0){ tempsql<<","; } 
+tempsql<<"`message`='"<<stringaddslash(data.message)<<"'";
+ break;
+
+     
+                  default:
+                                ;
+                     }
+                 }   
+
+            }        
+
+        return tempsql.str();
+   } 
+   
+    std::string _make_replace_into_sql()
+    {
+        unsigned int j = 0;
+        std::ostringstream tempsql;
+        tempsql << "REPLACE INTO ";
+        tempsql << tablename;
+        tempsql << " (";
+        for (; j < colnames.size(); j++)
+        {
+            if (j > 0)
+            {
+                tempsql << "`,`";
+            }
+            else
+            {
+                tempsql << "`";
+            }
+            tempsql << colnames[j];
+        }
+        if (j > 0)
+        {
+            tempsql << "`";
+        }
+        tempsql << ") VALUES ";
+
+        for (unsigned int i = 0; i < record.size(); i++)
+        {
+            if (i > 0)
+            {
+                tempsql << ",\n";
+            }
+            tempsql << "(";
+            	if(record[i].id==0){
+	tempsql<<"null";
+	 }else{ 
+	tempsql<<std::to_string(record[i].id);
+	}
+	tempsql<<",'"<<stringaddslash(record[i].message)<<"'";
+	tempsql<<")";
+
+ }
+ return tempsql.str();
+}
+
+    std::string _make_insert_into_sql(const std::string &fileld)
+    {
+        unsigned int j = 0;
+        std::ostringstream tempsql;
+        tempsql << "INSERT INTO ";
+        tempsql << tablename;
+        tempsql << " (";
+        for (; j < colnames.size(); j++)
+        {
+            if (j > 0)
+            {
+                tempsql << "`,`";
+            }
+            else
+            {
+                tempsql << "`";
+            }
+            tempsql << colnames[j];
+        }
+        if (j > 0)
+        {
+            tempsql << "`";
+        }
+        tempsql << ") VALUES ";
+
+        for (unsigned int i = 0; i < record.size(); i++)
+        {
+            if (i > 0)
+            {
+                tempsql << ",\n";
+            }
+            tempsql << "(";
+            	if(record[i].id==0){
+	tempsql<<"null";
+	 }else{ 
+	tempsql<<std::to_string(record[i].id);
+	}
+	tempsql<<",'"<<stringaddslash(record[i].message)<<"'";
+	tempsql<<")";
+	 }
+	 tempsql<<" as new ON DUPLICATE KEY UPDATE ";
+
+     
+    std::string keyname;
+    unsigned char jj=0;
+    j=0;
+     if(fileld.size()>0){
+            for(;jj<fileld.size();jj++){
+                    if(fileld[jj]==','){
+                        if(findcolpos(keyname)<255)
+                        {
+                            if(j>0)
+                            {
+                                tempsql<<",";
+                            }
+                            tempsql<<keyname;
+                            tempsql<<"=new.";
+                            tempsql<<keyname;
+                             
+                        }
+                        continue;   
+                    }
+                    if(fileld[jj]==0x20){
+
+                        continue;   
+                    }
+                    keyname.push_back(fileld[jj]);
+
+            }  
+            if(keyname.size()>0){
+                if(findcolpos(keyname)<255)
+                {
+                    if(j>0)
+                    {
+                        tempsql<<",";
+                    }
+                    tempsql<<keyname;
+                    tempsql<<"=new.";
+                    tempsql<<keyname;
+                    
+                }
+            }
+        } 
+ 
+ return tempsql.str();
+}
+
+   std::vector<std::string> data_toarray(std::string fileld=""){
+        std::vector<std::string> temparray;
+        std::string keyname;
+        unsigned char jj=0;
+        std::vector<unsigned char> keypos;
+        if(fileld.size()>1){
+            for(;jj<fileld.size();jj++){
+                    if(fileld[jj]==','){
+                        keypos.emplace_back(findcolpos(keyname)); 
+                        keyname.clear();
+                        continue;   
+                    }
+                    if(fileld[jj]==0x20){
+
+                        continue;   
+                    }
+                    keyname.push_back(fileld[jj]);
+
+            }  
+            if(keyname.size()>0){
+                            keypos.emplace_back(findcolpos(keyname)); 
+                            keyname.clear();
+            }
+        }else{
+            for(jj=0;jj<colnames.size();jj++){
+                keypos.emplace_back(jj); 
+            }
+        }
+               
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+         case 0:
+if(data.id==0){
+	temparray.push_back("0");
+ }else{ 
+	temparray.push_back(std::to_string(data.id));
+}
+ break;
+ case 1:
+	temparray.push_back(data.message);
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+   
+     return temparray;             
+   }   
+   
+   std::map<std::string,std::string> data_tomap(std::string fileld=""){
+       std::map<std::string,std::string> tempsql;
+            std::string keyname;
+            unsigned char jj=0;
+                  std::vector<unsigned char> keypos;
+                  if(fileld.size()>1){
+                    for(;jj<fileld.size();jj++){
+                            if(fileld[jj]==','){
+                                keypos.emplace_back(findcolpos(keyname)); 
+                                keyname.clear();
+                                continue;   
+                            }
+                            if(fileld[jj]==0x20){
+
+                                continue;   
+                            }
+                            keyname.push_back(fileld[jj]);
+
+                    }  
+                    if(keyname.size()>0){
+                                    keypos.emplace_back(findcolpos(keyname)); 
+                                    keyname.clear();
+                    }
+                 }else{
+                     for(jj=0;jj<colnames.size();jj++){
+                         keypos.emplace_back(jj); 
+                     }
+                 }
+                
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+         case 0:
+if(data.id==0){
+	tempsql.insert({"id","0"});
+ }else{ 
+	tempsql.insert({"id",std::to_string(data.id)});
+}
+ break;
+ case 1:
+	tempsql.insert({"message",data.message});
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+    
+     return tempsql;             
+   }   
+   
+   std::string data_tojson(){
+       std::ostringstream tempsql;
+
+        tempsql<<"{";
+if(data.id==0){
+	tempsql<<"\"id\":0";
+ }else{ 
+	tempsql<<"\"id\":"<<std::to_string(data.id);
+}
+tempsql<<",\"message\":\""<<http::utf8_to_jsonstring(data.message);
+tempsql<<"\"";
+tempsql<<"}";
+
+     
+     return tempsql.str();             
+   }   
+   
+   std::string data_tojson(std::string fileld){
+       std::ostringstream tempsql;
+            std::string keyname;
+            unsigned char jj=0;
+                  std::vector<unsigned char> keypos;
+                  if(fileld.size()>0){
+                    for(;jj<fileld.size();jj++){
+                            if(fileld[jj]==','){
+                                keypos.emplace_back(findcolpos(keyname)); 
+                                keyname.clear();
+                                continue;   
+                            }
+                            if(fileld[jj]==0x20){
+
+                                continue;   
+                            }
+                            keyname.push_back(fileld[jj]);
+
+                    }  
+                    if(keyname.size()>0){
+                                    keypos.emplace_back(findcolpos(keyname)); 
+                                    keyname.clear();
+                    }
+                 }else{
+                     for(jj=0;jj<colnames.size();jj++){
+                         keypos.emplace_back(jj); 
+                     }
+                 }
+                 tempsql<<"{";
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+         case 0:
+ if(jj>0){ tempsql<<","; } 
+if(data.id==0){
+	tempsql<<"\"id\":0";
+ }else{ 
+	tempsql<<"\"id\":"<<std::to_string(data.id);
+}
+ break;
+ case 1:
+ if(jj>0){ tempsql<<","; } 
+tempsql<<"\"message\":\""<<http::utf8_to_jsonstring(data.message)<<"\"";
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+      tempsql<<"}";  
+     return tempsql.str();             
+   }   
+   
+    void from_json(const std::string &json_content)
+   {
+        record.clear();
+        fortunebase::meta metatemp; 
+        data=metatemp;
+        unsigned int json_offset=0;
+        bool isarray=false;
+        //std::vector<std::string> list_content;
+        for(;json_offset<json_content.size();json_offset++)
+        {
+            if(json_content[json_offset]=='{')
+            {
+                break;
+            }
+            if(json_content[json_offset]=='[')
+            {
+                isarray=true;
+                break;
+            }
+        }
+        if(isarray)
+        {
+            json_offset+=1; 
+            std::string json_key_name,json_value_name; 
+            for(;json_offset<json_content.size();json_offset++)
+            {
+                for(;json_offset<json_content.size();json_offset++)
+                {
+                    if(json_content[json_offset]=='{')
+                    {
+                        json_offset+=1;
+                        break;
+                    }
+                }
+                if(record.size()>0)
+                {
+                    data=metatemp;
+                }
+                if(json_offset>=json_content.size())
+                {
+                    break;
+                }
+                for(;json_offset<json_content.size();json_offset++)
+                {
+    
+                            if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                            {
+                                continue;
+                            }
+                            else
+                            {
+                                if(json_content[json_offset]==0x22)
+                                {
+                                    unsigned int temp_offset=json_offset;
+                                    json_key_name=http::jsonstring_to_utf8(&json_content[json_offset],json_content.size()-json_offset,temp_offset);
+                                    json_offset=temp_offset;
+                                    if(json_content[json_offset]==0x22)
+                                    {
+                                        json_offset+=1;
+                                    }
+                                    for(;json_offset<json_content.size();json_offset++)
+                                    {
+                                    
+                                        if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                        {
+                                            continue;
+                                        }
+                                        break;
+                                    }       
+                                    if(json_content[json_offset]!=':')
+                                    {
+                                        break;
+                                    }
+                                    for(;json_offset<json_content.size();json_offset++)
+                                    {
+                                        if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                        {
+                                            continue;
+                                        }
+                                        break;
+                                    } 
+                                    json_offset+=1;
+                                    if(json_offset>=json_content.size())
+                                    {
+                                        break;
+                                    }
+                                    json_value_name.clear();
+                                    if(json_content[json_offset]==0x22)
+                                    {
+                                        
+                                        temp_offset=json_offset;
+                                        json_value_name=http::jsonstring_to_utf8(&json_content[json_offset],json_content.size()-json_offset,temp_offset);
+                                        json_offset=temp_offset;
+                                        if(json_content[json_offset]==0x22)
+                                        {
+                                            json_offset+=1;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        if(json_content[json_offset]!='{'&&json_content[json_offset]!=']')
+                                        {
+                                            for(;json_offset<json_content.size();json_offset++)
+                                            {
+                                                if(json_content[json_offset]==0x5D||json_content[json_offset]==0x7D||json_content[json_offset]==0x22||json_content[json_offset]==0x2C||json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                                {
+                                                    if(json_content[json_offset]==0x7D)
+                                                    {
+                                                        json_offset-=1;
+                                                    } 
+                                                    break;
+                                                }
+                                                json_value_name.push_back(json_content[json_offset]);
+                                            }   
+                                        }
+                                    }
+                                    //////////////////////////
+                                    set_val(json_key_name,json_value_name);
+                                    continue;
+                                }
+                                else
+                                {
+                                    break;
+                                }
+                            }
+    
+                }
+                record.emplace_back(data);
+                
+                json_offset+=1;
+            }
+            if(record.size()>1)
+            {
+                data=record[0];
+            }
+        }
+        else
+        {
+           if(json_content[json_offset]=='{')
+            {
+                json_offset+=1; 
+                std::string json_key_name,json_value_name; 
+                 
+                
+                for(;json_offset<json_content.size();json_offset++)
+                {
+ 
+                        if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                        {
+                            continue;
+                        }
+                        else
+                        {
+                            if(json_content[json_offset]==0x22)
+                            {
+                                 unsigned int temp_offset=json_offset;
+                                 json_key_name=http::jsonstring_to_utf8(&json_content[json_offset],json_content.size()-json_offset,temp_offset);
+                                 json_offset=temp_offset;
+                                 if(json_content[json_offset]==0x22)
+                                 {
+                                    json_offset+=1;
+                                 }
+                                for(;json_offset<json_content.size();json_offset++)
+                                {
+                                
+                                    if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                    {
+                                        continue;
+                                    }
+                                    break;
+                                }       
+                                if(json_content[json_offset]!=':')
+                                {
+                                    break;
+                                }
+                                for(;json_offset<json_content.size();json_offset++)
+                                {
+                                    if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                    {
+                                        continue;
+                                    }
+                                    break;
+                                } 
+                                json_offset+=1;
+                                if(json_offset>=json_content.size())
+                                {
+                                    break;
+                                }
+                                json_value_name.clear();
+                                if(json_content[json_offset]==0x22)
+                                {
+                                    
+                                    temp_offset=json_offset;
+                                    json_value_name=http::jsonstring_to_utf8(&json_content[json_offset],json_content.size()-json_offset,temp_offset);
+                                    json_offset=temp_offset;
+                                    if(json_content[json_offset]==0x22)
+                                    {
+                                        json_offset+=1;
+                                    }
+                                }
+                                else
+                                {
+                                    if(json_content[json_offset]!='{'&&json_content[json_offset]!=']')
+                                    {
+                                        for(;json_offset<json_content.size();json_offset++)
+                                        {
+                                            if(json_content[json_offset]==0x5D||json_content[json_offset]==0x7D||json_content[json_offset]==0x22||json_content[json_offset]==0x2C||json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                            {
+                                               if(json_content[json_offset]==0x7D)
+                                               {
+                                                   json_offset-=1;
+                                               } 
+                                               break;
+                                            }
+                                            json_value_name.push_back(json_content[json_offset]);
+                                        }   
+                                    }
+                                }
+                                //////////////////////////
+                                set_val(json_key_name,json_value_name);
+                                continue;
+                            }
+                            else
+                            {
+                                break;
+                            }
+                        }
+ 
+                }
+                record.emplace_back(data);
+            } 
+        }
+   }   
+    
+    void set_val(const std::string& set_key_name,const std::string& set_value_name)
+    {
+        switch(findcolpos(set_key_name))
+        {
+    		case 0:
+		 try{
+			data.id=std::stoul(set_value_name);
+		}catch (...) { 
+			data.id=0;
+			 }
+			break;
+		case 1:
+		 try{
+			data.message.append(set_value_name);
+		}catch (...) { 
+			data.message.clear();
+			 }
+			break;
+	default:
+		 { }
+			
+
+
+        }
+   } 
+    
+    void set_val(const std::string& set_key_name,const long long set_value_name)
+    {
+        switch(findcolpos(set_key_name))
+        {
+    		case 0:
+		 try{
+			data.id=set_value_name;
+		}catch (...) { 
+			data.id=0;
+			 }
+			break;
+		case 1:
+		 try{
+			data.message=std::to_string(set_value_name);
+		}catch (...) { 
+			data.message.clear();
+			 }
+			break;
+	default:
+		 { }
+			
+
+
+        }
+   } 
+    
+    void set_val(const std::string& set_key_name,const double set_value_name)
+    {
+        switch(findcolpos(set_key_name))
+        {
+    		case 0:
+		 try{
+			data.id=(unsigned int)set_value_name;
+		}catch (...) { 
+			data.id=0;
+			 }
+			break;
+		case 1:
+		 try{
+			data.message=std::to_string(set_value_name);
+		}catch (...) { 
+			data.message.clear();
+			 }
+			break;
+	default:
+		 { }
+			
+
+
+        }
+   } 
+    
+   std::string to_json(std::string fileld=""){
+       std::ostringstream tempsql;
+            std::string keyname;
+            unsigned char jj=0;
+                  std::vector<unsigned char> keypos;
+                  if(fileld.size()>0){
+                    for(;jj<fileld.size();jj++){
+                            if(fileld[jj]==','){
+                                keypos.emplace_back(findcolpos(keyname)); 
+                                keyname.clear();
+                                continue;   
+                            }
+                            if(fileld[jj]==0x20){
+
+                                continue;   
+                            }
+                            keyname.push_back(fileld[jj]);
+
+                    }  
+                    if(keyname.size()>0){
+                                    keypos.emplace_back(findcolpos(keyname)); 
+                                    keyname.clear();
+                    }
+                 }else{
+                     for(jj=0;jj<colnames.size();jj++){
+                         keypos.emplace_back(jj); 
+                     }
+                 }
+                tempsql<<"[";
+              for(size_t n=0;n<record.size();n++){
+                  if(n>0){
+                      tempsql<<",{";
+                  }else{
+                      tempsql<<"{";
+                  }  
+                 
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+         case 0:
+ if(jj>0){ tempsql<<","; } 
+if(record[n].id==0){
+	tempsql<<"\"id\":0";
+ }else{ 
+	tempsql<<"\"id\":"<<std::to_string(record[n].id);
+}
+ break;
+ case 1:
+ if(jj>0){ tempsql<<","; } 
+tempsql<<"\"message\":\""<<http::utf8_to_jsonstring(record[n].message)<<"\"";
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+      tempsql<<"}";  
+            }
+      tempsql<<"]";
+     return tempsql.str();             
+   }   
+   
+   std::string to_json(std::function<bool(std::string&,meta&)> func,std::string fileld=""){
+       std::ostringstream tempsql;
+            std::string keyname;
+            unsigned char jj=0;
+                  std::vector<unsigned char> keypos;
+                  if(fileld.size()>0){
+                    for(;jj<fileld.size();jj++){
+                            if(fileld[jj]==','){
+                                keypos.emplace_back(findcolpos(keyname)); 
+                                keyname.clear();
+                                continue;   
+                            }
+                            if(fileld[jj]==0x20){
+
+                                continue;   
+                            }
+                            keyname.push_back(fileld[jj]);
+
+                    }  
+                    if(keyname.size()>0){
+                                    keypos.emplace_back(findcolpos(keyname)); 
+                                    keyname.clear();
+                    }
+                 }else{
+                     for(jj=0;jj<colnames.size();jj++){
+                         keypos.emplace_back(jj); 
+                     }
+                 }
+                tempsql<<"[";
+              for(size_t n=0;n<record.size();n++){
+                 keyname.clear();
+                 if(func(keyname,record[n])){ 
+                            if(n>0){
+                                tempsql<<",{";
+                            }else{
+                                tempsql<<"{";
+                            } 
+                            tempsql<<keyname;
+                 }else{
+                    continue;
+                 } 
+                  
+                 for(jj=0;jj<keypos.size();jj++){
+                        
+                       switch(keypos[jj]){
+         case 0:
+ if(jj>0){ tempsql<<","; } 
+if(record[n].id==0){
+	tempsql<<"\"id\":0";
+ }else{ 
+	tempsql<<"\"id\":"<<std::to_string(record[n].id);
+}
+ break;
+ case 1:
+ if(jj>0){ tempsql<<","; } 
+tempsql<<"\"message\":\""<<http::utf8_to_jsonstring(record[n].message)<<"\"";
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+      tempsql<<"}";  
+            }
+      tempsql<<"]";
+     return tempsql.str();             
+   }   
+   long long getPK(){  return data.id; } 
+ void setPK(long long val){  data.id=val;} 
+unsigned  int  getId(){  return data.id; } 
+ void setId(unsigned  int  val){  data.id=val;} 
+
+std::string getMessage(){  return data.message; } 
+std::string& getRefMessage(){  return std::ref(data.message); } 
+ void setMessage(std::string &val){  data.message=val;} 
+ void setMessage(std::string_view val){  data.message=val;} 
+
+fortunebase::meta getnewData(){
+ 	 struct meta newdata;
+	 return newdata; 
+} 
+fortunebase::meta getData(){
+ 	 return data; 
+} 
+std::vector<fortunebase::meta> getRecord(){
+ 	 return record; 
+} 
+
+
+    template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true>
+    T& ref_meta([[maybe_unused]] std::string key_name)
+    {
+   		 if(key_name=="message")
+		{
+			return data.message;
+		}
+		return nullptr; 
+	}
+
+
+    template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true>
+    T& ref_meta([[maybe_unused]] std::string key_name)
+    {
+   		 if(key_name=="id")
+		{
+			return data.id;
+		}
+		return nullptr; 
+	}
+
+
+    template<typename T, typename std::enable_if<std::is_floating_point_v<T>,bool>::type = true >
+    T& ref_meta([[maybe_unused]] std::string key_name)
+    {
+   		return nullptr; 
+	}
+
+            template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true >  
+            std::vector<T> getCol([[maybe_unused]] std::string keyname)
+            {
+                std::vector<T> a;
+                
+   
+                unsigned char kpos;
+                kpos=findcolpos(keyname);               
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+   			case 0: 
+ 				 a.emplace_back(iter.id);
+				 break;
+
+                    }
+                }
+    
+                return a;
+            }
+    
+            template<typename T, typename std::enable_if<std::is_floating_point_v<T>,bool>::type = true >    
+			std::vector<T> getCol([[maybe_unused]] std::string keyname)
+			{
+				std::vector<T> a;
+				
+
+                return a;
+            }
+    
+            template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true >   
+            T getVal([[maybe_unused]] std::string keyname)
+            {
+   
+                    unsigned char kpos;
+                    kpos=findcolpos(keyname);                   
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 return data.id;
+				 break;
+			}
+                return 0;
+            }  
+    
+        template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true > 
+        T getVal([[maybe_unused]] fortunebase::meta & iter,[[maybe_unused]] std::string keyname)
+        {
+
+          
+            unsigned char kpos;
+            kpos=findcolpos(keyname);   
+            switch(kpos)
+            {
+   			case 0: 
+ 				 return iter.id;
+				 break;
+
+			}
+
+            return 0;
+        }  
+    
+            template<typename T, typename std::enable_if<std::is_floating_point_v<T>,bool>::type = true > 
+            T getVal(std::string keyname)
+            {
+                unsigned char kpos;
+                kpos=findcolpos(keyname);
+            
+                switch(kpos)
+                {
+
+    
+                    }
+                   
+    
+                    return 0.0;
+            }  
+    
+            template<typename T, typename std::enable_if<std::is_floating_point_v<T>,bool>::type = true > 
+            T getVal([[maybe_unused]] fortunebase::meta & iter,std::string keyname)
+            {
+                unsigned char kpos;
+                kpos=findcolpos(keyname);
+                switch(kpos)
+                {
+   
+                }
+                 
+    
+            
+                return 0.0;
+            }  
+    
+            template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true > 
+            std::string getVal(std::string keyname)
+            {
+                unsigned char kpos;
+                kpos=findcolpos(keyname);
+        
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 return data.message;
+				 break;
+
+                }
+                return "";
+            }  
+   
+            template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true > 
+            std::string getVal([[maybe_unused]] fortunebase::meta & iter,std::string keyname)
+            {
+         
+                unsigned char kpos;
+                kpos=findcolpos(keyname);
+       
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 return iter.message;
+				 break;
+
+                }
+                
+    
+                 
+                return "";
+            }  
+     
+            template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true >   
+            std::vector<std::string> getCol([[maybe_unused]] std::string keyname)
+            {
+                std::vector<std::string> a;
+
+           
+                unsigned char kpos;
+                kpos=findcolpos(keyname);                    
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+    			case 1: 
+ 				 a.emplace_back(iter.message);
+					 break;
+					}
+				}
+
+        return a;
+    }
+     
+        std::string getstrCol(std::string keyname,[[maybe_unused]] bool isyinhao=false)
+        {
+            std::ostringstream a;
+    
+            unsigned char kpos;
+            kpos=findcolpos(keyname);   
+            int j=0;
+            if(isyinhao&&record.size()>0)
+            {
+                a<<'"';
+            }
+            for(auto &iter:record)
+            {
+                    if(j>0)
+                    {
+                        if(isyinhao)
+                        {
+                            a<<"\",\"";
+                        }else{
+                            a<<',';    
+                        }
+                    }
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 a<<std::to_string(iter.id);
+				 break;
+			case 1: 
+ 				 if(isyinhao){ a<<jsonaddslash(iter.message); 
+				 }else{
+				 a<<iter.message;
+				 }
+				 break;
+
+                    }
+                    j++;
+            } 
+            if(isyinhao&&j>0){
+                a<<'"';
+            }      
+    
+                return a.str();
+        }
+    
+    template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>     
+    std::map<std::string,std::string> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+    {
+        std::map<std::string,std::string> a;
+    
+        unsigned char kpos,vpos;
+        kpos=findcolpos(keyname);
+        vpos=findcolpos(valname);        
+         std::string ktemp,vtemp;
+         for(auto &iter:record)
+         {
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+				 } 
+			switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+
+                }
+                if(ktemp.size()>0)
+                {
+                    a.emplace(ktemp,vtemp);
+                }
+            }       
+
+        
+            return a;
+        } 
+    
+
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>    
+        std::map<std::string,U> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::map<std::string,U> a;
+      
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);            
+                std::string ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {    
+                    switch(kpos)
+                    {
+ 
+       			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			 } 
+		 switch(vpos){
+
+                    }
+                    if(ktemp.size()>0)
+                    {
+                        a.emplace(ktemp,vtemp);
+                    }
+                }       
+        
+            return a;
+        } 
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>       
+        std::map<T,U> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,U> a;
+       
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);        
+            T ktemp;
+            U vtemp;
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+ 
+       case 0: 
+ 	 ktemp=iter.id;
+	 break;
+	 } 
+ 		  switch(vpos){
+
+                }
+                if(ktemp.size()>0)
+                {
+                    a.emplace(ktemp,vtemp);
+                }
+            }       
+     
+        return a;
+    }  
+            template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>      
+            std::map<T,std::string> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+            {
+                std::map<T,std::string> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);         
+                T ktemp;
+                std::string vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+ 			switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+
+                    }
+                    if(ktemp.size()>0)
+                    {
+                        a.emplace(ktemp,vtemp);
+                    }
+                } 
+         
+                return a;
+            }     
+        
+        template<typename T,typename U, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>       
+        std::map<std::string,U> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<std::string,U> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);            
+            std::string  ktemp;
+            U  vtemp;
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			  }
+ 			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+
+                }
+                if(ktemp.size()>0)
+                {
+                    a.emplace(ktemp,vtemp);
+                }
+            }       
+      
+        return a;
+    }  
+    
+        template<typename T,typename U, typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>   
+        std::map<T,U> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,U> a;
+    
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);            
+            T ktemp;
+            U vtemp;
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+ 			switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+
+                }
+                if(ktemp.size()>0)
+                {
+                    a.emplace(ktemp,vtemp);
+                }
+            }       
+    
+            return a;
+        }   
+    
+        template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true >         
+        std::map<T,meta> getmapRows([[maybe_unused]] std::string keyname)
+        {
+            std::map<T,meta> a;
+    
+            unsigned char kpos;
+            kpos=findcolpos(keyname);                        
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 a.emplace(iter.id,iter);
+				 break;
+
+                }
+            }       
+     
+            return a;
+        }     
+    
+        template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true >    
+        std::map<std::string,meta> getmapRows([[maybe_unused]] std::string keyname)
+        {
+            std::map<std::string,meta> a;
+
+    
+            unsigned char kpos;
+            kpos=findcolpos(keyname);            
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 a.emplace(iter.message,iter);
+			 break;
+
+                }
+                //a.emplace(ktemp,iter);
+            }       
+    
+
+        return a;
+    }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>  
+        std::vector<std::pair<std::string,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::vector<std::pair<std::string,U>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);                   
+            std::string ktemp;
+            U vtemp;
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+	 		 }
+ 			switch(vpos){
+
+                   }
+
+                 a.emplace_back(ktemp,vtemp);
+            }       
+
+     
+
+            return a;
+        }   
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>    
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+			 break;
+			  }
+			 switch(vpos){
+
+                   }
+
+                   a.emplace_back(ktemp,vtemp);
+                }       
+
+    
+
+            return a;
+        }   
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+ 			switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+
+                   }
+
+                    a.emplace_back(ktemp,vtemp);
+                }       
+    
+            return a;
+        }  
+    
+        template<typename T,typename U, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>     
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);                
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    
+                    switch(kpos)
+                    {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			  }
+ 			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+
+                   }
+                    a.emplace_back(ktemp,vtemp);
+                }       
+    
+            return a;
+        }  
+    
+        template<typename T,typename U, typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+
+                   }
+                    a.emplace_back(ktemp,vtemp);
+                }       
+      
+            return a;
+        }   
+    
+        template<typename T,typename U, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true>     
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   case 1: 
+ 	 ktemp=iter.message;
+	 break;
+	  }
+ switch(vpos){
+case 1: 
+ 	 vtemp=iter.message;
+	 break;
+
+                   }
+
+                    a.emplace_back(ktemp,vtemp);
+                }       
+    
+            return a;
+        }  
+    
+        template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true >   
+        std::vector<std::pair<T,meta>> getvecRows([[maybe_unused]] std::string keyname)
+        {
+            std::vector<std::pair<T,meta>> a;
+     
+            unsigned char kpos;
+            kpos=findcolpos(keyname);                  
+            for(auto &iter:record)
+            { 
+                switch(kpos)
+                {
+
+   case 0: 
+ 	 a.emplace_back(iter.id,iter);
+	 break;
+
+                }
+            }       
+    
+        return a;
+    }
+        template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true >  
+        std::vector<std::pair<std::string,meta>> getvecRows([[maybe_unused]] std::string keyname)
+        {
+            std::vector<std::pair<std::string,meta>> a;
+      
+            unsigned char kpos;
+            kpos=findcolpos(keyname);                     
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   case 1: 
+ 	 a.emplace_back(iter.message,iter);
+	 break;
+
+                }
+            }       
+    
+
+        return a;
+    }
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_floating_point<D>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+    
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);      
+            T ktemp;
+            U vtemp;
+            for(auto &iter:record)
+            { 
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			  }
+
+			 switch(dpos){
+
+                }
+            }       
+
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_integral_v<D>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+    
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);          
+            T ktemp;
+            U vtemp;
+            //D vtemp;
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			  }
+
+			 switch(dpos){
+			case 0: 
+ 				 a[ktemp][vtemp].emplace_back(iter.id);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_same<D,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);       
+            T ktemp;
+            U vtemp;
+            // D dtemp;
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+				  }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			 }
+
+			 switch(dpos){
+			case 1: 
+ 				 a[ktemp][vtemp].emplace_back(iter.message);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_floating_point<D>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+                std::map<T,std::map<U,std::vector<D>>> a;
+   
+                unsigned char kpos,vpos,dpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                dpos=findcolpos(dataname);
+                T ktemp;
+                U vtemp;
+            // D dtemp;
+
+                for(auto &iter:record)
+                {
+                    
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+			  }
+
+			 switch(dpos){
+
+                   }
+                }       
+    
+            return a;
+        }
+    
+    template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_integral_v<D>,bool>::type = true>    
+    std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+    {
+        std::map<T,std::map<U,std::vector<D>>> a;
+
+   
+        unsigned char kpos,vpos,dpos;
+        kpos=findcolpos(keyname);
+        vpos=findcolpos(valname);
+        dpos=findcolpos(dataname);             
+        T ktemp;
+        U vtemp;
+       // D dtemp;
+
+         for(auto &iter:record)
+         {
+            switch(kpos)
+            {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+			 }
+
+			 switch(dpos){
+			case 0: 
+ 				 a[ktemp][vtemp].emplace_back(iter.id);
+				 break;
+
+            }
+         }       
+    
+        return a;
+    }
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<D,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);
+            T ktemp;
+            U vtemp;
+            // D dtemp;
+
+            for(auto &iter:record)
+            { 
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+			  }
+
+			 switch(dpos){
+			case 1: 
+ 				 a[ktemp][vtemp].emplace_back(iter.message);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_floating_point<D>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+                std::map<T,std::map<U,std::vector<D>>> a;
+   
+                unsigned char kpos,vpos,dpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                dpos=findcolpos(dataname);               
+                T ktemp;
+                U vtemp;
+                //D vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			  }
+
+			 switch(dpos){
+
+                    }
+                }       
+    
+
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_integral_v<D>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);            
+            T ktemp;
+            U vtemp;
+            //D vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			 }
+
+			 switch(dpos){
+			case 0: 
+ 				 a[ktemp][vtemp].emplace_back(iter.id);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+    template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_same<D,std::string>::value,bool>::type = true>    
+    std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+    {
+        std::map<T,std::map<U,std::vector<D>>> a;
+
+   
+        unsigned char kpos,vpos,dpos;
+        kpos=findcolpos(keyname);
+        vpos=findcolpos(valname);
+        dpos=findcolpos(dataname);
+        T ktemp;
+        U vtemp;
+        // D dtemp;
+
+         for(auto &iter:record)
+         {
+             
+            switch(kpos)
+            {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			 }
+
+			switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			 }
+
+			switch(dpos){
+			case 1: 
+ 				 a[ktemp][vtemp].emplace_back(iter.message);
+				 break;
+
+            }
+         }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_floating_point<D>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);        
+            T ktemp;
+            U vtemp;
+            // D dtemp;
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+			  }
+
+			 switch(dpos){
+
+                }
+            }       
+
+    
+            return a;
+        }
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_integral_v<D>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);
+            T ktemp;
+            U vtemp;
+            // D dtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+			 }
+
+			 switch(dpos){
+			case 0: 
+ 				 a[ktemp][vtemp].emplace_back(iter.id);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<D,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);        
+            T ktemp;
+            U vtemp;
+            // D dtemp;
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 1: 
+ 				 vtemp=iter.message;
+				 break;
+			  }
+
+			 switch(dpos){
+			case 1: 
+ 				 a[ktemp][vtemp].emplace_back(iter.message);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 1: 
+ 				 a[ktemp].emplace_back(iter.message);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			 }
+
+			 switch(vpos){
+
+                }
+            }       
+
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 0: 
+ 				 a[ktemp].emplace_back(iter.id);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 1: 
+ 				 a[ktemp].emplace_back(iter.message);
+				 break;
+
+                }
+            }       
+
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+               
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+
+			 switch(vpos){
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 0: 
+ 				 a[ktemp].emplace_back(iter.id);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename std::enable_if<std::is_integral_v<T>,bool>::type = true>    
+        std::map<T,std::vector<meta>> getgroupRows([[maybe_unused]] std::string keyname)
+        {
+            std::map<T,std::vector<meta>> a;
+   
+            unsigned char kpos;
+            kpos=findcolpos(keyname);
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 a[iter.id].emplace_back(iter);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true>    
+        std::map<T,std::vector<meta>> getgroupRows([[maybe_unused]] std::string keyname)
+        {
+            std::map<T,std::vector<meta>> a;
+   
+            unsigned char kpos;
+            kpos=findcolpos(keyname);
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 a[iter.message].emplace_back(iter);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<meta>>> getgroupRows([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::map<U,std::vector<meta>>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 1: 
+ 				 a[ktemp][iter.message].emplace_back(iter);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<meta>>> getgroupRows([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::map<U,std::vector<meta>>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);            
+            T ktemp;
+            
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 1: 
+ 				 ktemp=iter.message;
+				 break;
+	  }
+
+ switch(vpos){
+			case 0: 
+ 				 a[ktemp][iter.id].emplace_back(iter);
+				 break;
+
+                }
+            }       
+
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<U>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<meta>>> getgroupRows([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::map<U,std::vector<meta>>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);        
+        T ktemp;
+        
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 0: 
+ 				 a[ktemp][iter.id].emplace_back(iter);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<meta>>> getgroupRows([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::map<U,std::vector<meta>>> a;
+
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);            
+            T ktemp;
+            
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 1: 
+ 				 a[ktemp][iter.message].emplace_back(iter);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+  };
+    
+
+}
+#endif
+   

+ 2509 - 0
frameworks/C++/paozhu/paozhu_benchmark/orm/include/worldbase.h

@@ -0,0 +1,2509 @@
+#ifndef ORM_DEFAULT_WORLDBASEMATA_H
+#define ORM_DEFAULT_WORLDBASEMATA_H
+/*
+*This file is auto create from cli
+*本文件为自动生成 Fri, 26 Jan 2024 02:59:30 GMT
+***/
+#include <iostream>
+#include <cstdio>
+#include <sstream>
+#include <array>
+#include <map> 
+#include <string_view> 
+#include <string> 
+#include <vector>
+#include <ctime>
+#include <array>
+#include "mysql.h"
+namespace orm { 
+   
+    
+struct worldbase
+{
+    struct meta{
+    unsigned  int id= 0; //
+ int randomnumber= 0; //
+ } data;
+ std::vector<worldbase::meta> record;
+std::string _rmstag="default";//this value must be default or tag value, tag in mysqlconnect config file .
+std::vector<unsigned char> _keypos{0x00};
+MYSQL_ROW _row;
+std::vector<worldbase::meta>::iterator begin(){     return record.begin(); }
+std::vector<worldbase::meta>::iterator end(){     return record.end(); }
+std::vector<worldbase::meta>::const_iterator begin() const{     return record.begin(); }
+std::vector<worldbase::meta>::const_iterator end() const{     return record.end(); }
+const std::array<std::string,2> colnames={"id","randomnumber"};
+const std::array<unsigned char,2> colnamestype= {3,3};
+std::string tablename="world";
+std::string modelname="World";
+
+	  unsigned char findcolpos(const std::string &coln){
+            if(coln.size()==0)
+            {
+                return 255;
+            }
+		    unsigned char  bi=coln[0];
+         
+
+	         if(bi<91&&bi>64){
+				bi+=32;
+			}
+            switch(coln[0]){
+
+
+         case 'i':
+   	 return 0;
+break;
+case 'r':
+   	 return 1;
+break;
+
+             }
+             return 255;
+           }
+         
+    int size(){ return record.size(); }   
+
+    std::string getPKname(){ 
+       return "id";
+}
+
+      void record_reset()
+      {
+            record.clear();     
+      }
+      void data_reset(){
+     worldbase::meta metatemp;    
+            data = metatemp; 
+      }
+      
+      std::string soft_remove_sql([[maybe_unused]] const std::string &fieldsql){
+          std::string temp;
+     
+         return temp;
+     }
+     void _setColnamevalue()
+      {
+        for(unsigned char i=0;i<_keypos.size();i++)
+        {
+            switch(_keypos[i]){
+        	case 0:
+		 try{
+			data.id=std::stoul(_row[i]);
+		}catch (...) { 
+			data.id=0;
+			 }
+			break;
+	case 1:
+		 try{
+			data.randomnumber=std::stoi(_row[i]);
+		}catch (...) { 
+			data.randomnumber=0;
+			 }
+			break;
+	default:
+		 { }
+			
+
+                 }
+
+                 if(i>210){
+                     break;
+                 }
+          }
+   } 
+         void _addnewrowvalue(){
+           worldbase::meta metatemp;   
+
+          for(unsigned char i=0;i<_keypos.size();i++){
+ 
+                 switch(_keypos[i]){
+
+        	case 0:
+		 try{
+			metatemp.id=std::stoul(_row[i]);
+		}catch (...) { 
+			metatemp.id=0;
+			 }
+			break;
+	case 1:
+		 try{
+			metatemp.randomnumber=std::stoi(_row[i]);
+		}catch (...) { 
+			metatemp.randomnumber=0;
+			 }
+			break;
+	default:
+		 { }
+			
+
+                  }
+                 if(i>210){
+                     break;
+                 }
+          }
+           record.emplace_back(std::move(metatemp)); 
+   } 
+
+  inline  std::string stringaddslash(std::string &content){
+        std::string temp;
+        for(unsigned int i=0;i<content.size();i++){
+            if(content[i]=='\''){
+                temp.append("\\'");
+                continue;
+            }else if(content[i]=='"'){
+                temp.append("\\\"");
+                continue;
+            }else if(content[i]=='\\'){
+                temp.append("\\\\");
+                continue;
+            }
+            temp.push_back(content[i]);
+        }
+        return temp;
+   }  
+  inline  std::string jsonaddslash(std::string &content){
+        std::string temp;
+        for(unsigned int i=0;i<content.size();i++){
+            if(content[i]=='"'){
+                temp.append("\\\"");
+                continue;
+            }
+            else if(content[i]=='\\'){
+                temp.append("\\\\");
+                continue;
+            }
+            temp.push_back(content[i]);
+        }
+        return temp;
+   }  
+
+   std::string _makeinsertsql(){
+      unsigned int j=0;
+                std::ostringstream tempsql;
+                tempsql<<"INSERT INTO ";
+                    tempsql<<tablename;
+                   tempsql<<" (";
+                    for(;j<colnames.size();j++){
+                            if(j>0){
+                                tempsql<<"`,`";
+                            }else{
+                                tempsql<<"`";
+                            }
+                            tempsql<<colnames[j];
+                    }
+                    if(j>0){
+                        tempsql<<"`";
+                    }
+            tempsql<<") VALUES (";
+
+        if(data.id==0){
+tempsql<<"null";
+ }else{ 
+	tempsql<<std::to_string(data.id);
+}
+if(data.randomnumber==0){
+	tempsql<<",0";
+ }else{ 
+	tempsql<<","<<std::to_string(data.randomnumber);
+}
+tempsql<<")";
+
+     
+       return tempsql.str();
+   } 
+      
+      std::string _makerecordinsertsql( meta &insert_data){
+      unsigned int j=0;
+                std::ostringstream tempsql;
+                tempsql<<"INSERT INTO ";
+                    tempsql<<tablename;
+                   tempsql<<" (";
+                    for(;j<colnames.size();j++){
+                            if(j>0){
+                                tempsql<<"`,`";
+                            }else{
+                                tempsql<<"`";
+                            }
+                            tempsql<<colnames[j];
+                    }
+                    if(j>0){
+                        tempsql<<"`";
+                    }
+            tempsql<<") VALUES (";
+
+        if(insert_data.id==0){
+tempsql<<"null";
+ }else{ 
+	tempsql<<std::to_string(insert_data.id);
+}
+if(insert_data.randomnumber==0){
+	tempsql<<",0";
+ }else{ 
+	tempsql<<","<<std::to_string(insert_data.randomnumber);
+}
+tempsql<<")";
+
+     
+       return tempsql.str();
+   } 
+       
+      std::string _makerecordinsertsql( std::vector<meta> &insert_data){
+      unsigned int j=0;
+                std::ostringstream tempsql;
+                tempsql<<"INSERT INTO ";
+                    tempsql<<tablename;
+                   tempsql<<" (";
+                    for(;j<colnames.size();j++){
+                            if(j>0){
+                                tempsql<<"`,`";
+                            }else{
+                                tempsql<<"`";
+                            }
+                            tempsql<<colnames[j];
+                    }
+                    if(j>0){
+                        tempsql<<"`";
+                    }
+            tempsql<<") VALUES ";
+
+    for(unsigned int i=0;i<insert_data.size();i++)
+    {
+		if(i>0)
+		{
+			tempsql<<",";	
+		}
+		tempsql<<"(";
+
+
+        	if(insert_data[i].id==0){
+	tempsql<<"null";
+	 }else{ 
+	tempsql<<std::to_string(insert_data[i].id);
+	}
+	if(insert_data[i].randomnumber==0){
+	tempsql<<",0";
+	 }else{ 
+	tempsql<<","<<std::to_string(insert_data[i].randomnumber);
+	}
+		tempsql<<")";
+	 } 
+
+     
+       return tempsql.str();
+   } 
+       
+    std::string _makeupdatesql(const std::string &fileld){
+       //int j=0;
+            std::ostringstream tempsql;
+                 tempsql<<"UPDATE ";
+                 tempsql<<tablename;
+                 tempsql<<" SET ";
+
+            bool isall=false;
+            if(fileld.empty()){
+                isall=true;
+            }
+            if(isall){
+
+        if(data.id==0){
+	tempsql<<"`id`=0";
+ }else{ 
+	tempsql<<"`id`="<<std::to_string(data.id);
+}
+if(data.randomnumber==0){
+	tempsql<<",`randomnumber`=0";
+ }else{ 
+	tempsql<<",`randomnumber`="<<std::to_string(data.randomnumber);
+}
+ }else{ 
+
+     
+  unsigned int jj=0;
+                  std::string keyname;
+                  std::vector<unsigned char> keypos;
+                  for(;jj<fileld.size();jj++){
+                        if(fileld[jj]==','){
+                                unsigned char bpos_i=findcolpos(keyname);
+                               keypos.emplace_back(bpos_i); 
+#ifdef DEBUG
+                    if (bpos_i == 254)
+                    {
+                        std::cout << "\033[1m\033[31m-----------\n"
+                                  << keyname << " not in " << tablename << " table Field.\n-----------\033[0m"
+                                  << std::endl;
+                    }
+#endif                               
+                               keyname.clear();
+                             continue;   
+                        }
+                        if(fileld[jj]==0x20){
+
+                             continue;   
+                        }
+                        keyname.push_back(fileld[jj]);
+
+                  }  
+                 if(keyname.size()>0){
+                                unsigned char bpos_i=findcolpos(keyname);
+ #ifdef DEBUG
+                    if (bpos_i == 254)
+                    {
+                        std::cout << "\033[1m\033[31m-----------\n"
+                                  << keyname << " not in " << tablename << " table Field.\n-----------\033[0m"
+                                  << std::endl;
+                    }
+#endif                                       
+                                keypos.emplace_back(bpos_i); 
+                                keyname.clear();
+                 }
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+
+         case 0:
+ if(jj>0){ tempsql<<","; } 
+if(data.id==0){
+	tempsql<<"`id`=0";
+ }else{ 
+	tempsql<<"`id`="<<std::to_string(data.id);
+}
+ break;
+ case 1:
+ if(jj>0){ tempsql<<","; } 
+if(data.randomnumber==0){
+	tempsql<<"`randomnumber`=0";
+ }else{ 
+	tempsql<<"`randomnumber`="<<std::to_string(data.randomnumber);
+}
+ break;
+
+     
+                  default:
+                                ;
+                     }
+                 }   
+
+            }        
+
+        return tempsql.str();
+   } 
+   
+    std::string _make_replace_into_sql()
+    {
+        unsigned int j = 0;
+        std::ostringstream tempsql;
+        tempsql << "REPLACE INTO ";
+        tempsql << tablename;
+        tempsql << " (";
+        for (; j < colnames.size(); j++)
+        {
+            if (j > 0)
+            {
+                tempsql << "`,`";
+            }
+            else
+            {
+                tempsql << "`";
+            }
+            tempsql << colnames[j];
+        }
+        if (j > 0)
+        {
+            tempsql << "`";
+        }
+        tempsql << ") VALUES ";
+
+        for (unsigned int i = 0; i < record.size(); i++)
+        {
+            if (i > 0)
+            {
+                tempsql << ",\n";
+            }
+            tempsql << "(";
+            	if(record[i].id==0){
+	tempsql<<"null";
+	 }else{ 
+	tempsql<<std::to_string(record[i].id);
+	}
+	if(record[i].randomnumber==0){
+	tempsql<<",0";
+	 }else{ 
+	tempsql<<","<<std::to_string(record[i].randomnumber);
+	}
+	tempsql<<")";
+
+ }
+ return tempsql.str();
+}
+
+    std::string _make_insert_into_sql(const std::string &fileld)
+    {
+        unsigned int j = 0;
+        std::ostringstream tempsql;
+        tempsql << "INSERT INTO ";
+        tempsql << tablename;
+        tempsql << " (";
+        for (; j < colnames.size(); j++)
+        {
+            if (j > 0)
+            {
+                tempsql << "`,`";
+            }
+            else
+            {
+                tempsql << "`";
+            }
+            tempsql << colnames[j];
+        }
+        if (j > 0)
+        {
+            tempsql << "`";
+        }
+        tempsql << ") VALUES ";
+
+        for (unsigned int i = 0; i < record.size(); i++)
+        {
+            if (i > 0)
+            {
+                tempsql << ",\n";
+            }
+            tempsql << "(";
+            	if(record[i].id==0){
+	tempsql<<"null";
+	 }else{ 
+	tempsql<<std::to_string(record[i].id);
+	}
+	if(record[i].randomnumber==0){
+	tempsql<<",0";
+	 }else{ 
+	tempsql<<","<<std::to_string(record[i].randomnumber);
+	}
+	tempsql<<")";
+	 }
+	 tempsql<<" as new ON DUPLICATE KEY UPDATE ";
+
+     
+    std::string keyname;
+    unsigned char jj=0;
+    j=0;
+     if(fileld.size()>0){
+            for(;jj<fileld.size();jj++){
+                    if(fileld[jj]==','){
+                        if(findcolpos(keyname)<255)
+                        {
+                            if(j>0)
+                            {
+                                tempsql<<",";
+                            }
+                            tempsql<<keyname;
+                            tempsql<<"=new.";
+                            tempsql<<keyname;
+                             
+                        }
+                        continue;   
+                    }
+                    if(fileld[jj]==0x20){
+
+                        continue;   
+                    }
+                    keyname.push_back(fileld[jj]);
+
+            }  
+            if(keyname.size()>0){
+                if(findcolpos(keyname)<255)
+                {
+                    if(j>0)
+                    {
+                        tempsql<<",";
+                    }
+                    tempsql<<keyname;
+                    tempsql<<"=new.";
+                    tempsql<<keyname;
+                    
+                }
+            }
+        } 
+ 
+ return tempsql.str();
+}
+
+   std::vector<std::string> data_toarray(std::string fileld=""){
+        std::vector<std::string> temparray;
+        std::string keyname;
+        unsigned char jj=0;
+        std::vector<unsigned char> keypos;
+        if(fileld.size()>1){
+            for(;jj<fileld.size();jj++){
+                    if(fileld[jj]==','){
+                        keypos.emplace_back(findcolpos(keyname)); 
+                        keyname.clear();
+                        continue;   
+                    }
+                    if(fileld[jj]==0x20){
+
+                        continue;   
+                    }
+                    keyname.push_back(fileld[jj]);
+
+            }  
+            if(keyname.size()>0){
+                            keypos.emplace_back(findcolpos(keyname)); 
+                            keyname.clear();
+            }
+        }else{
+            for(jj=0;jj<colnames.size();jj++){
+                keypos.emplace_back(jj); 
+            }
+        }
+               
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+         case 0:
+if(data.id==0){
+	temparray.push_back("0");
+ }else{ 
+	temparray.push_back(std::to_string(data.id));
+}
+ break;
+ case 1:
+if(data.randomnumber==0){
+	temparray.push_back("0");
+ }else{ 
+	temparray.push_back(std::to_string(data.randomnumber));
+}
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+   
+     return temparray;             
+   }   
+   
+   std::map<std::string,std::string> data_tomap(std::string fileld=""){
+       std::map<std::string,std::string> tempsql;
+            std::string keyname;
+            unsigned char jj=0;
+                  std::vector<unsigned char> keypos;
+                  if(fileld.size()>1){
+                    for(;jj<fileld.size();jj++){
+                            if(fileld[jj]==','){
+                                keypos.emplace_back(findcolpos(keyname)); 
+                                keyname.clear();
+                                continue;   
+                            }
+                            if(fileld[jj]==0x20){
+
+                                continue;   
+                            }
+                            keyname.push_back(fileld[jj]);
+
+                    }  
+                    if(keyname.size()>0){
+                                    keypos.emplace_back(findcolpos(keyname)); 
+                                    keyname.clear();
+                    }
+                 }else{
+                     for(jj=0;jj<colnames.size();jj++){
+                         keypos.emplace_back(jj); 
+                     }
+                 }
+                
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+         case 0:
+if(data.id==0){
+	tempsql.insert({"id","0"});
+ }else{ 
+	tempsql.insert({"id",std::to_string(data.id)});
+}
+ break;
+ case 1:
+if(data.randomnumber==0){
+	tempsql.insert({"randomnumber","0"});
+ }else{ 
+	tempsql.insert({"randomnumber",std::to_string(data.randomnumber)});
+}
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+    
+     return tempsql;             
+   }   
+   
+   std::string data_tojson(){
+       std::ostringstream tempsql;
+
+        tempsql<<"{";
+if(data.id==0){
+	tempsql<<"\"id\":0";
+ }else{ 
+	tempsql<<"\"id\":"<<std::to_string(data.id);
+}
+if(data.randomnumber==0){
+	tempsql<<",\"randomnumber\":0";
+ }else{ 
+	tempsql<<",\"randomnumber\":"<<std::to_string(data.randomnumber);
+}
+tempsql<<"}";
+
+     
+     return tempsql.str();             
+   }   
+   
+   std::string data_tojson(std::string fileld){
+       std::ostringstream tempsql;
+            std::string keyname;
+            unsigned char jj=0;
+                  std::vector<unsigned char> keypos;
+                  if(fileld.size()>0){
+                    for(;jj<fileld.size();jj++){
+                            if(fileld[jj]==','){
+                                keypos.emplace_back(findcolpos(keyname)); 
+                                keyname.clear();
+                                continue;   
+                            }
+                            if(fileld[jj]==0x20){
+
+                                continue;   
+                            }
+                            keyname.push_back(fileld[jj]);
+
+                    }  
+                    if(keyname.size()>0){
+                                    keypos.emplace_back(findcolpos(keyname)); 
+                                    keyname.clear();
+                    }
+                 }else{
+                     for(jj=0;jj<colnames.size();jj++){
+                         keypos.emplace_back(jj); 
+                     }
+                 }
+                 tempsql<<"{";
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+         case 0:
+ if(jj>0){ tempsql<<","; } 
+if(data.id==0){
+	tempsql<<"\"id\":0";
+ }else{ 
+	tempsql<<"\"id\":"<<std::to_string(data.id);
+}
+ break;
+ case 1:
+ if(jj>0){ tempsql<<","; } 
+if(data.randomnumber==0){
+	tempsql<<"\"randomnumber\":0";
+ }else{ 
+	tempsql<<"\"randomnumber\":"<<std::to_string(data.randomnumber);
+}
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+      tempsql<<"}";  
+     return tempsql.str();             
+   }   
+   
+    void from_json(const std::string &json_content)
+   {
+        record.clear();
+        worldbase::meta metatemp; 
+        data=metatemp;
+        unsigned int json_offset=0;
+        bool isarray=false;
+        //std::vector<std::string> list_content;
+        for(;json_offset<json_content.size();json_offset++)
+        {
+            if(json_content[json_offset]=='{')
+            {
+                break;
+            }
+            if(json_content[json_offset]=='[')
+            {
+                isarray=true;
+                break;
+            }
+        }
+        if(isarray)
+        {
+            json_offset+=1; 
+            std::string json_key_name,json_value_name; 
+            for(;json_offset<json_content.size();json_offset++)
+            {
+                for(;json_offset<json_content.size();json_offset++)
+                {
+                    if(json_content[json_offset]=='{')
+                    {
+                        json_offset+=1;
+                        break;
+                    }
+                }
+                if(record.size()>0)
+                {
+                    data=metatemp;
+                }
+                if(json_offset>=json_content.size())
+                {
+                    break;
+                }
+                for(;json_offset<json_content.size();json_offset++)
+                {
+    
+                            if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                            {
+                                continue;
+                            }
+                            else
+                            {
+                                if(json_content[json_offset]==0x22)
+                                {
+                                    unsigned int temp_offset=json_offset;
+                                    json_key_name=http::jsonstring_to_utf8(&json_content[json_offset],json_content.size()-json_offset,temp_offset);
+                                    json_offset=temp_offset;
+                                    if(json_content[json_offset]==0x22)
+                                    {
+                                        json_offset+=1;
+                                    }
+                                    for(;json_offset<json_content.size();json_offset++)
+                                    {
+                                    
+                                        if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                        {
+                                            continue;
+                                        }
+                                        break;
+                                    }       
+                                    if(json_content[json_offset]!=':')
+                                    {
+                                        break;
+                                    }
+                                    for(;json_offset<json_content.size();json_offset++)
+                                    {
+                                        if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                        {
+                                            continue;
+                                        }
+                                        break;
+                                    } 
+                                    json_offset+=1;
+                                    if(json_offset>=json_content.size())
+                                    {
+                                        break;
+                                    }
+                                    json_value_name.clear();
+                                    if(json_content[json_offset]==0x22)
+                                    {
+                                        
+                                        temp_offset=json_offset;
+                                        json_value_name=http::jsonstring_to_utf8(&json_content[json_offset],json_content.size()-json_offset,temp_offset);
+                                        json_offset=temp_offset;
+                                        if(json_content[json_offset]==0x22)
+                                        {
+                                            json_offset+=1;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        if(json_content[json_offset]!='{'&&json_content[json_offset]!=']')
+                                        {
+                                            for(;json_offset<json_content.size();json_offset++)
+                                            {
+                                                if(json_content[json_offset]==0x5D||json_content[json_offset]==0x7D||json_content[json_offset]==0x22||json_content[json_offset]==0x2C||json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                                {
+                                                    if(json_content[json_offset]==0x7D)
+                                                    {
+                                                        json_offset-=1;
+                                                    } 
+                                                    break;
+                                                }
+                                                json_value_name.push_back(json_content[json_offset]);
+                                            }   
+                                        }
+                                    }
+                                    //////////////////////////
+                                    set_val(json_key_name,json_value_name);
+                                    continue;
+                                }
+                                else
+                                {
+                                    break;
+                                }
+                            }
+    
+                }
+                record.emplace_back(data);
+                
+                json_offset+=1;
+            }
+            if(record.size()>1)
+            {
+                data=record[0];
+            }
+        }
+        else
+        {
+           if(json_content[json_offset]=='{')
+            {
+                json_offset+=1; 
+                std::string json_key_name,json_value_name; 
+                 
+                
+                for(;json_offset<json_content.size();json_offset++)
+                {
+ 
+                        if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                        {
+                            continue;
+                        }
+                        else
+                        {
+                            if(json_content[json_offset]==0x22)
+                            {
+                                 unsigned int temp_offset=json_offset;
+                                 json_key_name=http::jsonstring_to_utf8(&json_content[json_offset],json_content.size()-json_offset,temp_offset);
+                                 json_offset=temp_offset;
+                                 if(json_content[json_offset]==0x22)
+                                 {
+                                    json_offset+=1;
+                                 }
+                                for(;json_offset<json_content.size();json_offset++)
+                                {
+                                
+                                    if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                    {
+                                        continue;
+                                    }
+                                    break;
+                                }       
+                                if(json_content[json_offset]!=':')
+                                {
+                                    break;
+                                }
+                                for(;json_offset<json_content.size();json_offset++)
+                                {
+                                    if(json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                    {
+                                        continue;
+                                    }
+                                    break;
+                                } 
+                                json_offset+=1;
+                                if(json_offset>=json_content.size())
+                                {
+                                    break;
+                                }
+                                json_value_name.clear();
+                                if(json_content[json_offset]==0x22)
+                                {
+                                    
+                                    temp_offset=json_offset;
+                                    json_value_name=http::jsonstring_to_utf8(&json_content[json_offset],json_content.size()-json_offset,temp_offset);
+                                    json_offset=temp_offset;
+                                    if(json_content[json_offset]==0x22)
+                                    {
+                                        json_offset+=1;
+                                    }
+                                }
+                                else
+                                {
+                                    if(json_content[json_offset]!='{'&&json_content[json_offset]!=']')
+                                    {
+                                        for(;json_offset<json_content.size();json_offset++)
+                                        {
+                                            if(json_content[json_offset]==0x5D||json_content[json_offset]==0x7D||json_content[json_offset]==0x22||json_content[json_offset]==0x2C||json_content[json_offset]==0x20||json_content[json_offset]==0x0A||json_content[json_offset]==0x0D||json_content[json_offset]=='\t')
+                                            {
+                                               if(json_content[json_offset]==0x7D)
+                                               {
+                                                   json_offset-=1;
+                                               } 
+                                               break;
+                                            }
+                                            json_value_name.push_back(json_content[json_offset]);
+                                        }   
+                                    }
+                                }
+                                //////////////////////////
+                                set_val(json_key_name,json_value_name);
+                                continue;
+                            }
+                            else
+                            {
+                                break;
+                            }
+                        }
+ 
+                }
+                record.emplace_back(data);
+            } 
+        }
+   }   
+    
+    void set_val(const std::string& set_key_name,const std::string& set_value_name)
+    {
+        switch(findcolpos(set_key_name))
+        {
+    		case 0:
+		 try{
+			data.id=std::stoul(set_value_name);
+		}catch (...) { 
+			data.id=0;
+			 }
+			break;
+		case 1:
+		 try{
+			data.randomnumber=std::stoi(set_value_name);
+		}catch (...) { 
+			data.randomnumber=0;
+			 }
+			break;
+	default:
+		 { }
+			
+
+
+        }
+   } 
+    
+    void set_val(const std::string& set_key_name,const long long set_value_name)
+    {
+        switch(findcolpos(set_key_name))
+        {
+    		case 0:
+		 try{
+			data.id=set_value_name;
+		}catch (...) { 
+			data.id=0;
+			 }
+			break;
+		case 1:
+		 try{
+			data.randomnumber=set_value_name;
+		}catch (...) { 
+			data.randomnumber=0;
+			 }
+			break;
+	default:
+		 { }
+			
+
+
+        }
+   } 
+    
+    void set_val(const std::string& set_key_name,const double set_value_name)
+    {
+        switch(findcolpos(set_key_name))
+        {
+    		case 0:
+		 try{
+			data.id=(unsigned int)set_value_name;
+		}catch (...) { 
+			data.id=0;
+			 }
+			break;
+		case 1:
+		 try{
+			data.randomnumber=(int)set_value_name;
+		}catch (...) { 
+			data.randomnumber=0;
+			 }
+			break;
+	default:
+		 { }
+			
+
+
+        }
+   } 
+    
+   std::string to_json(std::string fileld=""){
+       std::ostringstream tempsql;
+            std::string keyname;
+            unsigned char jj=0;
+                  std::vector<unsigned char> keypos;
+                  if(fileld.size()>0){
+                    for(;jj<fileld.size();jj++){
+                            if(fileld[jj]==','){
+                                keypos.emplace_back(findcolpos(keyname)); 
+                                keyname.clear();
+                                continue;   
+                            }
+                            if(fileld[jj]==0x20){
+
+                                continue;   
+                            }
+                            keyname.push_back(fileld[jj]);
+
+                    }  
+                    if(keyname.size()>0){
+                                    keypos.emplace_back(findcolpos(keyname)); 
+                                    keyname.clear();
+                    }
+                 }else{
+                     for(jj=0;jj<colnames.size();jj++){
+                         keypos.emplace_back(jj); 
+                     }
+                 }
+                tempsql<<"[";
+              for(size_t n=0;n<record.size();n++){
+                  if(n>0){
+                      tempsql<<",{";
+                  }else{
+                      tempsql<<"{";
+                  }  
+                 
+                 for(jj=0;jj<keypos.size();jj++){
+                       switch(keypos[jj]){
+         case 0:
+ if(jj>0){ tempsql<<","; } 
+if(record[n].id==0){
+	tempsql<<"\"id\":0";
+ }else{ 
+	tempsql<<"\"id\":"<<std::to_string(record[n].id);
+}
+ break;
+ case 1:
+ if(jj>0){ tempsql<<","; } 
+if(record[n].randomnumber==0){
+	tempsql<<"\"randomnumber\":0";
+ }else{ 
+	tempsql<<"\"randomnumber\":"<<std::to_string(record[n].randomnumber);
+}
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+      tempsql<<"}";  
+            }
+      tempsql<<"]";
+     return tempsql.str();             
+   }   
+   
+   std::string to_json(std::function<bool(std::string&,meta&)> func,std::string fileld=""){
+       std::ostringstream tempsql;
+            std::string keyname;
+            unsigned char jj=0;
+                  std::vector<unsigned char> keypos;
+                  if(fileld.size()>0){
+                    for(;jj<fileld.size();jj++){
+                            if(fileld[jj]==','){
+                                keypos.emplace_back(findcolpos(keyname)); 
+                                keyname.clear();
+                                continue;   
+                            }
+                            if(fileld[jj]==0x20){
+
+                                continue;   
+                            }
+                            keyname.push_back(fileld[jj]);
+
+                    }  
+                    if(keyname.size()>0){
+                                    keypos.emplace_back(findcolpos(keyname)); 
+                                    keyname.clear();
+                    }
+                 }else{
+                     for(jj=0;jj<colnames.size();jj++){
+                         keypos.emplace_back(jj); 
+                     }
+                 }
+                tempsql<<"[";
+              for(size_t n=0;n<record.size();n++){
+                 keyname.clear();
+                 if(func(keyname,record[n])){ 
+                            if(n>0){
+                                tempsql<<",{";
+                            }else{
+                                tempsql<<"{";
+                            } 
+                            tempsql<<keyname;
+                 }else{
+                    continue;
+                 } 
+                  
+                 for(jj=0;jj<keypos.size();jj++){
+                        
+                       switch(keypos[jj]){
+         case 0:
+ if(jj>0){ tempsql<<","; } 
+if(record[n].id==0){
+	tempsql<<"\"id\":0";
+ }else{ 
+	tempsql<<"\"id\":"<<std::to_string(record[n].id);
+}
+ break;
+ case 1:
+ if(jj>0){ tempsql<<","; } 
+if(record[n].randomnumber==0){
+	tempsql<<"\"randomnumber\":0";
+ }else{ 
+	tempsql<<"\"randomnumber\":"<<std::to_string(record[n].randomnumber);
+}
+ break;
+
+                             default:
+                                ;
+                     }
+                 }   
+      tempsql<<"}";  
+            }
+      tempsql<<"]";
+     return tempsql.str();             
+   }   
+   long long getPK(){  return data.id; } 
+ void setPK(long long val){  data.id=val;} 
+unsigned  int  getId(){  return data.id; } 
+ void setId(unsigned  int  val){  data.id=val;} 
+
+ int  getRandomnumber(){  return data.randomnumber; } 
+ void setRandomnumber( int  val){  data.randomnumber=val;} 
+
+worldbase::meta getnewData(){
+ 	 struct meta newdata;
+	 return newdata; 
+} 
+worldbase::meta getData(){
+ 	 return data; 
+} 
+std::vector<worldbase::meta> getRecord(){
+ 	 return record; 
+} 
+
+
+    template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true>
+    T& ref_meta([[maybe_unused]] std::string key_name)
+    {
+   		return nullptr; 
+	}
+
+
+    template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true>
+    T& ref_meta([[maybe_unused]] std::string key_name)
+    {
+   		 if(key_name=="id")
+		{
+			return data.id;
+		}
+		 if(key_name=="randomnumber")
+		{
+			return data.randomnumber;
+		}
+		return nullptr; 
+	}
+
+
+    template<typename T, typename std::enable_if<std::is_floating_point_v<T>,bool>::type = true >
+    T& ref_meta([[maybe_unused]] std::string key_name)
+    {
+   		return nullptr; 
+	}
+
+            template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true >  
+            std::vector<T> getCol([[maybe_unused]] std::string keyname)
+            {
+                std::vector<T> a;
+                
+   
+                unsigned char kpos;
+                kpos=findcolpos(keyname);               
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+   			case 0: 
+ 				 a.emplace_back(iter.id);
+				 break;
+			case 1: 
+ 				 a.emplace_back(iter.randomnumber);
+				 break;
+
+                    }
+                }
+    
+                return a;
+            }
+    
+            template<typename T, typename std::enable_if<std::is_floating_point_v<T>,bool>::type = true >    
+			std::vector<T> getCol([[maybe_unused]] std::string keyname)
+			{
+				std::vector<T> a;
+				
+
+                return a;
+            }
+    
+            template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true >   
+            T getVal([[maybe_unused]] std::string keyname)
+            {
+   
+                    unsigned char kpos;
+                    kpos=findcolpos(keyname);                   
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 return data.id;
+				 break;
+			case 1: 
+ 				 return data.randomnumber;
+				 break;
+			}
+                return 0;
+            }  
+    
+        template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true > 
+        T getVal([[maybe_unused]] worldbase::meta & iter,[[maybe_unused]] std::string keyname)
+        {
+
+          
+            unsigned char kpos;
+            kpos=findcolpos(keyname);   
+            switch(kpos)
+            {
+   			case 0: 
+ 				 return iter.id;
+				 break;
+			case 1: 
+ 				 return iter.randomnumber;
+				 break;
+
+			}
+
+            return 0;
+        }  
+    
+            template<typename T, typename std::enable_if<std::is_floating_point_v<T>,bool>::type = true > 
+            T getVal(std::string keyname)
+            {
+                unsigned char kpos;
+                kpos=findcolpos(keyname);
+            
+                switch(kpos)
+                {
+
+    
+                    }
+                   
+    
+                    return 0.0;
+            }  
+    
+            template<typename T, typename std::enable_if<std::is_floating_point_v<T>,bool>::type = true > 
+            T getVal([[maybe_unused]] worldbase::meta & iter,std::string keyname)
+            {
+                unsigned char kpos;
+                kpos=findcolpos(keyname);
+                switch(kpos)
+                {
+   
+                }
+                 
+    
+            
+                return 0.0;
+            }  
+    
+            template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true > 
+            std::string getVal(std::string keyname)
+            {
+                unsigned char kpos;
+                kpos=findcolpos(keyname);
+        
+                switch(kpos)
+                {
+
+   
+                }
+                return "";
+            }  
+   
+            template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true > 
+            std::string getVal([[maybe_unused]] worldbase::meta & iter,std::string keyname)
+            {
+         
+                unsigned char kpos;
+                kpos=findcolpos(keyname);
+       
+                switch(kpos)
+                {
+
+   
+                }
+                
+    
+                 
+                return "";
+            }  
+     
+            template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true >   
+            std::vector<std::string> getCol([[maybe_unused]] std::string keyname)
+            {
+                std::vector<std::string> a;
+
+           
+
+        return a;
+    }
+     
+        std::string getstrCol(std::string keyname,[[maybe_unused]] bool isyinhao=false)
+        {
+            std::ostringstream a;
+    
+            unsigned char kpos;
+            kpos=findcolpos(keyname);   
+            int j=0;
+            if(isyinhao&&record.size()>0)
+            {
+                a<<'"';
+            }
+            for(auto &iter:record)
+            {
+                    if(j>0)
+                    {
+                        if(isyinhao)
+                        {
+                            a<<"\",\"";
+                        }else{
+                            a<<',';    
+                        }
+                    }
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 a<<std::to_string(iter.id);
+				 break;
+			case 1: 
+ 				 a<<std::to_string(iter.randomnumber);
+				 break;
+
+                    }
+                    j++;
+            } 
+            if(isyinhao&&j>0){
+                a<<'"';
+            }      
+    
+                return a.str();
+        }
+    
+    template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>     
+    std::map<std::string,std::string> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+    {
+        std::map<std::string,std::string> a;
+         
+            return a;
+        } 
+    
+
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>    
+        std::map<std::string,U> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::map<std::string,U> a;
+         
+            return a;
+        } 
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>       
+        std::map<T,U> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,U> a;
+       
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);        
+            T ktemp;
+            U vtemp;
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+ 
+       case 0: 
+ 	 ktemp=iter.id;
+	 break;
+case 1: 
+ 	 ktemp=iter.randomnumber;
+	 break;
+	 } 
+ 		  switch(vpos){
+
+                }
+                if(ktemp.size()>0)
+                {
+                    a.emplace(ktemp,vtemp);
+                }
+            }       
+     
+        return a;
+    }  
+            template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>      
+            std::map<T,std::string> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+            {
+                std::map<T,std::string> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);         
+                T ktemp;
+                std::string vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+ 			switch(vpos){
+
+                    }
+                    if(ktemp.size()>0)
+                    {
+                        a.emplace(ktemp,vtemp);
+                    }
+                } 
+         
+                return a;
+            }     
+        
+        template<typename T,typename U, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>       
+        std::map<std::string,U> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<std::string,U> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);            
+            std::string  ktemp;
+            U  vtemp;
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			  }
+ 			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+
+                }
+                if(ktemp.size()>0)
+                {
+                    a.emplace(ktemp,vtemp);
+                }
+            }       
+      
+        return a;
+    }  
+    
+        template<typename T,typename U, typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>   
+        std::map<T,U> getCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,U> a;
+    
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);            
+            T ktemp;
+            U vtemp;
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+ 			switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+
+                }
+                if(ktemp.size()>0)
+                {
+                    a.emplace(ktemp,vtemp);
+                }
+            }       
+    
+            return a;
+        }   
+    
+        template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true >         
+        std::map<T,meta> getmapRows([[maybe_unused]] std::string keyname)
+        {
+            std::map<T,meta> a;
+    
+            unsigned char kpos;
+            kpos=findcolpos(keyname);                        
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 a.emplace(iter.id,iter);
+				 break;
+			case 1: 
+ 				 a.emplace(iter.randomnumber,iter);
+				 break;
+
+                }
+            }       
+     
+            return a;
+        }     
+    
+        template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true >    
+        std::map<std::string,meta> getmapRows([[maybe_unused]] std::string keyname)
+        {
+            std::map<std::string,meta> a;
+
+    
+
+        return a;
+    }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>  
+        std::vector<std::pair<std::string,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::vector<std::pair<std::string,U>> a;
+   
+
+            return a;
+        }   
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>    
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+			 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+			 break;
+			  }
+			 switch(vpos){
+
+                   }
+
+                   a.emplace_back(ktemp,vtemp);
+                }       
+
+    
+
+            return a;
+        }   
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+ 			switch(vpos){
+
+                   }
+
+                    a.emplace_back(ktemp,vtemp);
+                }       
+    
+            return a;
+        }  
+    
+        template<typename T,typename U, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>     
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);                
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    
+                    switch(kpos)
+                    {
+
+   			  }
+ 			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+
+                   }
+                    a.emplace_back(ktemp,vtemp);
+                }       
+    
+            return a;
+        }  
+    
+        template<typename T,typename U, typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+   
+                unsigned char kpos,vpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                T ktemp;
+                U vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+
+                   }
+                    a.emplace_back(ktemp,vtemp);
+                }       
+      
+            return a;
+        }   
+    
+        template<typename T,typename U, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true>     
+        std::vector<std::pair<T,U>> getvecCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+                std::vector<std::pair<T,U>> a;
+   
+            return a;
+        }  
+    
+        template<typename T, typename std::enable_if<std::is_integral_v<T>,bool>::type = true >   
+        std::vector<std::pair<T,meta>> getvecRows([[maybe_unused]] std::string keyname)
+        {
+            std::vector<std::pair<T,meta>> a;
+     
+            unsigned char kpos;
+            kpos=findcolpos(keyname);                  
+            for(auto &iter:record)
+            { 
+                switch(kpos)
+                {
+
+   case 0: 
+ 	 a.emplace_back(iter.id,iter);
+	 break;
+case 1: 
+ 	 a.emplace_back(iter.randomnumber,iter);
+	 break;
+
+                }
+            }       
+    
+        return a;
+    }
+        template<typename T, typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true >  
+        std::vector<std::pair<std::string,meta>> getvecRows([[maybe_unused]] std::string keyname)
+        {
+            std::vector<std::pair<std::string,meta>> a;
+      
+
+        return a;
+    }
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_floating_point<D>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+    
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);      
+            T ktemp;
+            U vtemp;
+            for(auto &iter:record)
+            { 
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+			  }
+
+			 switch(dpos){
+
+                }
+            }       
+
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_integral_v<D>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+    
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);          
+            T ktemp;
+            U vtemp;
+            //D vtemp;
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+			  }
+
+			 switch(dpos){
+			case 0: 
+ 				 a[ktemp][vtemp].emplace_back(iter.id);
+				 break;
+			case 1: 
+ 				 a[ktemp][vtemp].emplace_back(iter.randomnumber);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_same<D,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);       
+            T ktemp;
+            U vtemp;
+            // D dtemp;
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+				  }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+			 }
+
+			 switch(dpos){
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_floating_point<D>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+                std::map<T,std::map<U,std::vector<D>>> a;
+   
+                unsigned char kpos,vpos,dpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                dpos=findcolpos(dataname);
+                T ktemp;
+                U vtemp;
+            // D dtemp;
+
+                for(auto &iter:record)
+                {
+                    
+                    switch(kpos)
+                    {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			 }
+
+			 switch(vpos){
+			  }
+
+			 switch(dpos){
+
+                   }
+                }       
+    
+            return a;
+        }
+    
+    template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_integral_v<D>,bool>::type = true>    
+    std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+    {
+        std::map<T,std::map<U,std::vector<D>>> a;
+
+   
+        unsigned char kpos,vpos,dpos;
+        kpos=findcolpos(keyname);
+        vpos=findcolpos(valname);
+        dpos=findcolpos(dataname);             
+        T ktemp;
+        U vtemp;
+       // D dtemp;
+
+         for(auto &iter:record)
+         {
+            switch(kpos)
+            {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			 }
+
+			 switch(vpos){
+			 }
+
+			 switch(dpos){
+			case 0: 
+ 				 a[ktemp][vtemp].emplace_back(iter.id);
+				 break;
+			case 1: 
+ 				 a[ktemp][vtemp].emplace_back(iter.randomnumber);
+				 break;
+
+            }
+         }       
+    
+        return a;
+    }
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<D,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);
+            T ktemp;
+            U vtemp;
+            // D dtemp;
+
+            for(auto &iter:record)
+            { 
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+
+			 switch(vpos){
+			  }
+
+			 switch(dpos){
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_floating_point<D>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+                std::map<T,std::map<U,std::vector<D>>> a;
+   
+                unsigned char kpos,vpos,dpos;
+                kpos=findcolpos(keyname);
+                vpos=findcolpos(valname);
+                dpos=findcolpos(dataname);               
+                T ktemp;
+                U vtemp;
+                //D vtemp;
+                for(auto &iter:record)
+                {
+                    switch(kpos)
+                    {
+
+   			 }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+			  }
+
+			 switch(dpos){
+
+                    }
+                }       
+    
+
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_integral_v<D>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);            
+            T ktemp;
+            U vtemp;
+            //D vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			  }
+
+			 switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+			 }
+
+			 switch(dpos){
+			case 0: 
+ 				 a[ktemp][vtemp].emplace_back(iter.id);
+				 break;
+			case 1: 
+ 				 a[ktemp][vtemp].emplace_back(iter.randomnumber);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+    template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true, typename std::enable_if<std::is_same<D,std::string>::value,bool>::type = true>    
+    std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+    {
+        std::map<T,std::map<U,std::vector<D>>> a;
+
+   
+        unsigned char kpos,vpos,dpos;
+        kpos=findcolpos(keyname);
+        vpos=findcolpos(valname);
+        dpos=findcolpos(dataname);
+        T ktemp;
+        U vtemp;
+        // D dtemp;
+
+         for(auto &iter:record)
+         {
+             
+            switch(kpos)
+            {
+
+   			 }
+
+			switch(vpos){
+			case 0: 
+ 				 vtemp=iter.id;
+				 break;
+			case 1: 
+ 				 vtemp=iter.randomnumber;
+				 break;
+			 }
+
+			switch(dpos){
+
+            }
+         }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_floating_point<D>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            return a;
+        }
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_integral_v<D>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            unsigned char kpos,vpos,dpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            dpos=findcolpos(dataname);
+            T ktemp;
+            U vtemp;
+            // D dtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			  }
+
+			 switch(vpos){
+			 }
+
+			 switch(dpos){
+			case 0: 
+ 				 a[ktemp][vtemp].emplace_back(iter.id);
+				 break;
+			case 1: 
+ 				 a[ktemp][vtemp].emplace_back(iter.randomnumber);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<D,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<D>>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname,[[maybe_unused]] std::string dataname)
+        {
+            std::map<T,std::map<U,std::vector<D>>> a;
+   
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+
+   
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+   
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			  }
+
+			 switch(vpos){
+			case 0: 
+ 				 a[ktemp].emplace_back(iter.id);
+				 break;
+			case 1: 
+ 				 a[ktemp].emplace_back(iter.randomnumber);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			 }
+
+			 switch(vpos){
+
+                }
+            }       
+
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_floating_point<U>::value,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+               
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+
+			 switch(vpos){
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::map<T,std::vector<U>> getgroupCols([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::vector<U>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);
+            T ktemp;
+            //U vtemp;
+
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 0: 
+ 				 a[ktemp].emplace_back(iter.id);
+				 break;
+			case 1: 
+ 				 a[ktemp].emplace_back(iter.randomnumber);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename std::enable_if<std::is_integral_v<T>,bool>::type = true>    
+        std::map<T,std::vector<meta>> getgroupRows([[maybe_unused]] std::string keyname)
+        {
+            std::map<T,std::vector<meta>> a;
+   
+            unsigned char kpos;
+            kpos=findcolpos(keyname);
+
+            for(auto &iter:record)
+            {
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 a[iter.id].emplace_back(iter);
+				 break;
+			case 1: 
+ 				 a[iter.randomnumber].emplace_back(iter);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true>    
+        std::map<T,std::vector<meta>> getgroupRows([[maybe_unused]] std::string keyname)
+        {
+            std::map<T,std::vector<meta>> a;
+   
+            return a;
+        }
+    
+        template<typename T,typename U,typename D,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true, typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<meta>>> getgroupRows([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::map<U,std::vector<meta>>> a;
+   
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_same<T,std::string>::value,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<meta>>> getgroupRows([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::map<U,std::vector<meta>>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);            
+            T ktemp;
+            
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   	  }
+
+ switch(vpos){
+			case 0: 
+ 				 a[ktemp][iter.id].emplace_back(iter);
+				 break;
+			case 1: 
+ 				 a[ktemp][iter.randomnumber].emplace_back(iter);
+				 break;
+
+                }
+            }       
+
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<U>,bool>::type = true,typename std::enable_if<std::is_integral_v<U>,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<meta>>> getgroupRows([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::map<U,std::vector<meta>>> a;
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);        
+        T ktemp;
+        
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			 }
+
+			 switch(vpos){
+			case 0: 
+ 				 a[ktemp][iter.id].emplace_back(iter);
+				 break;
+			case 1: 
+ 				 a[ktemp][iter.randomnumber].emplace_back(iter);
+				 break;
+
+                }
+            }       
+    
+            return a;
+        }
+    
+        template<typename T,typename U,typename std::enable_if<std::is_integral_v<T>,bool>::type = true,typename std::enable_if<std::is_same<U,std::string>::value,bool>::type = true>    
+        std::map<T,std::map<U,std::vector<meta>>> getgroupRows([[maybe_unused]] std::string keyname,[[maybe_unused]] std::string valname)
+        {
+            std::map<T,std::map<U,std::vector<meta>>> a;
+
+   
+            unsigned char kpos,vpos;
+            kpos=findcolpos(keyname);
+            vpos=findcolpos(valname);            
+            T ktemp;
+            
+            for(auto &iter:record)
+            {
+                
+                switch(kpos)
+                {
+
+   			case 0: 
+ 				 ktemp=iter.id;
+				 break;
+			case 1: 
+ 				 ktemp=iter.randomnumber;
+				 break;
+			  }
+
+			 switch(vpos){
+
+                }
+            }       
+    
+            return a;
+        }
+    
+  };
+    
+
+}
+#endif
+   

+ 4 - 0
frameworks/C++/paozhu/paozhu_benchmark/orm/orm.h

@@ -0,0 +1,4 @@
+/*build this file time Tue, 20 Dec 2022 11:40:56 GMT*/
+
+#include "Fortune.h"
+#include "World.h"

+ 5 - 0
frameworks/C++/paozhu/paozhu_benchmark/view/techempower/fortunes.html

@@ -0,0 +1,5 @@
+<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><%c
+    for(auto &a:obj["list"].as_array()){
+%><tr><td><%c echo<<a.second["id"].to_string(); %></td><td><%c echo<<a.second["message"].to_string(); %></td></tr><%c
+    }
+%></table></body></html>

+ 26 - 0
frameworks/C++/paozhu/paozhu_benchmark/viewsrc/include/regviewmethod.hpp

@@ -0,0 +1,26 @@
+#ifndef __HTTP_REG_VIEW_METHOD_HPP
+#define __HTTP_REG_VIEW_METHOD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include<string>
+#include<map>
+#include<functional>
+#include "request.h"
+#include "viewso_param.h"
+#include "viewmethold_reg.h"
+#include "viewsrc.h"
+
+namespace http
+{
+  void _initview_method_regto(VIEW_REG  &_viewmetholdreg)
+  {
+            	 //create time: Mon, 30 Dec 2024 15:45:45 GMT
+
+	_viewmetholdreg.emplace("techempower/fortunes",http::view::techempower::fortunes);
+
+	} 
+}
+#endif

+ 26 - 0
frameworks/C++/paozhu/paozhu_benchmark/viewsrc/include/viewsrc.h

@@ -0,0 +1,26 @@
+#ifndef __HTTP_VIEWSRC_ALL_METHOD_H
+#define __HTTP_VIEWSRC_ALL_METHOD_H
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include<string>
+#include<map>
+#include<functional>
+#include "request.h"
+#include "viewso_param.h"
+
+namespace http { 
+namespace view { 
+
+namespace techempower{ 
+
+	std::string fortunes(const struct view_param &vinfo,http::OBJ_VALUE &obj);
+}
+
+
+}
+
+}
+#endif

+ 50 - 0
frameworks/C++/paozhu/paozhu_benchmark/viewsrc/view/techempower/fortunes.cpp

@@ -0,0 +1,50 @@
+#include<iostream>
+#include <cstdio>
+#include <string>
+#include <sstream>
+#include <map> 
+#include <vector>
+#include <ctime>
+#include <array>
+#include <sys/stat.h>
+#include <cstdlib>
+#include "request.h"
+#include "datetime.h"
+#include "cookie.h"
+#include "urlcode.h"
+#include "loadviewso.h"
+#include "viewso_param.h"
+#include "http_so_common_api.h"
+#include "viewsrc.h"
+//g++ viewsrc/view/techempower/fortunes.cpp
+namespace http {
+
+namespace view {
+	namespace techempower{
+ 		 std::string fortunes([[maybe_unused]] const struct view_param &vinfo,[[maybe_unused]] http::OBJ_VALUE &obj)
+			{
+ 
+                     std::ostringstream echo;
+
+        
+ 			 echo<<"<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>";
+
+    for(auto &a:obj["list"].as_array()){
+
+ 			 echo<<"<tr><td>";
+ echo<<a.second["id"].to_string(); 
+ 			 echo<<"</td><td>";
+ echo<<a.second["message"].to_string(); 
+ 			 echo<<"</td></tr>";
+
+    }
+
+ 			 echo<<"</table></body></html>";
+
+                  return echo.str();
+             }
+
+         }
+        }
+       }
+    

+ 66 - 0
frameworks/C++/paozhu/paozhu_benchmark/websockets/include/loopwebsockets.hpp

@@ -0,0 +1,66 @@
+#include <iostream>
+#include <memory>
+#include <string_view>
+
+#include "orm.h"
+#include "httppeer.h"
+#include "websockets.h"
+
+namespace http
+{
+
+class loopwebsockets : public websockets_api
+{
+  public:
+    unsigned int outcount = 0;
+    loopwebsockets(std::weak_ptr<http::httppeer> p) : websockets_api(4, 0, p) {}
+    ~loopwebsockets() { std::cout << "~loopwebsockets" << std::endl; }
+
+  public:
+    void onopen() { std::cout << "onopen" << std::endl; }
+    void onclose() { std::cout << "onclose" << std::endl; }
+    void onpong() {}
+    void pushloop()
+    {
+        std::shared_ptr<http::httppeer> peer = weakpeer.lock();
+        if (peer)
+        {
+            std::cout << "timeloop:" << std::endl;
+            std::string aa = "looptests";
+            std::string outhello;
+            peer->ws->makeWSText(aa, outhello);
+            peer->send(outhello);
+
+            //   peer->send(aa);
+            if (outcount == 4)
+            {
+                timeloop_num = 0;
+                outcount     = 0;
+                return;
+            }
+            outcount++;
+        }
+        else
+        {
+            std::cout << "peer is die!" << std::endl;
+        }
+    }
+    void onfiles(std::string_view filename) { std::cout << "--------onfiles:--------" << filename << std::endl; }
+    void onmessage(std::string_view data)
+    {
+        std::cout << "onmessage:" << data << std::endl;
+        std::shared_ptr<http::httppeer> peer = weak_peer.lock();
+        if (peer)
+        {
+            std::string outhello;
+            peer->ws->makeWSText(data, outhello);
+            peer->send(outhello);
+        }
+    }
+    static std::shared_ptr<loopwebsockets> create(std::weak_ptr<http::httppeer> p)
+    {
+        return std::make_shared<loopwebsockets>(p);
+    }
+};
+
+}// namespace http

+ 83 - 0
frameworks/C++/paozhu/paozhu_benchmark/websockets/include/mywebsockets.hpp

@@ -0,0 +1,83 @@
+#include <iostream>
+#include <memory>
+#include <string_view>
+
+#include "orm.h"
+#include "httppeer.h"
+#include "websockets.h"
+#include "terminal_color.h"
+// g++ -shared -fPIC mywebsockets.cpp -o mywebsockets.so
+namespace http
+{
+
+class mywebsockets : public websockets_api
+{
+  public:
+    //    unsigned int timeloop_num;
+    //    unsigned char state;
+    unsigned int outcount = 0;
+    mywebsockets(std::weak_ptr<httppeer> p) : websockets_api(4, 0, p) {}
+    ~mywebsockets() { DEBUG_LOG(" ~mywebsockets "); }
+
+  public:
+    void onopen() { DEBUG_LOG(" onopen "); }
+    void onclose() { DEBUG_LOG(" onclose "); }
+    void onpong() {}
+    void pushloop()
+    {
+        std::shared_ptr<httppeer> peer = weak_peer.lock();
+        if (peer)
+        {
+            DEBUG_LOG(" timeloop ");
+            std::string aa = "This server push msg or subscribe msg";
+            std::string outhello;
+            peer->ws->makeWSText(aa.data(), aa.length(), outhello);
+            peer->send(outhello);
+
+            //   peer->send(aa);
+            if (outcount == 4)
+            {
+                timeloop_num = 0;
+                outcount     = 0;
+                return;
+            }
+            outcount++;
+        }
+        else
+        {
+            DEBUG_LOG(" peer is die! ");
+        }
+    }
+
+    void onfiles([[maybe_unused]] std::string_view filename) { DEBUG_LOG("onfiles %zu", filename.size()); }
+    void onmessage(std::string_view data)
+    {
+        std::ostringstream oss;
+        oss << std::this_thread::get_id();
+        oss << " onmessage:" << data << std::endl;
+        std::string temp = oss.str();
+        DEBUG_LOG("%s", temp.c_str());
+        std::shared_ptr<http::httppeer> peer = weak_peer.lock();
+        if (peer)
+        {
+            std::string outhello;
+            if(data=="html")
+            {
+               std::string html_data="<h3> Websocket test 测试h3 </h3>";
+               peer->ws->makeWSText(html_data, outhello); 
+            }
+            else
+            {
+                peer->ws->makeWSText(data, outhello);
+            }
+            
+            peer->send(outhello);
+        }
+    }
+    static std::shared_ptr<mywebsockets> create(std::weak_ptr<http::httppeer> p)
+    {
+        return std::make_shared<mywebsockets>(p);
+    }
+};
+
+}// namespace http

+ 15 - 0
frameworks/C++/poco/README.md

@@ -0,0 +1,15 @@
+# POCO C++ Libraries Benchmarking Test
+
+- [POCO Github Repository](https://github.com/pocoproject/poco)
+- [POCO Website](https://pocoproject.org/)
+
+## Software Versions
+
+- [buildpack-deps noble](https://hub.docker.com/_/buildpack-deps)
+- [g++ 14](https://gcc.gnu.org/gcc-14/)
+- [c++17](https://en.cppreference.com/w/cpp/17)
+- [POCO 1.13.1](https://pocoproject.org/releases/poco-1.13.1/poco-1.13.1-all.zip)
+ 
+## Test URLs
+
+- `PLAINTEXT` - [http://127.0.0.1:8080/plaintext](http://127.0.0.1:8080/plaintext) 

+ 10 - 1
frameworks/C++/poco/benchmark.cpp

@@ -6,6 +6,8 @@
 #include <Poco/Net/HTTPServerRequest.h>
 #include <Poco/Net/HTTPServerRequest.h>
 #include <Poco/Net/HTTPServerResponse.h>
 #include <Poco/Net/HTTPServerResponse.h>
 #include <Poco/Util/ServerApplication.h>
 #include <Poco/Util/ServerApplication.h>
+#include <Poco/Timespan.h>
+#include <Poco/Thread.h>
 
 
 #include <iostream>
 #include <iostream>
 #include <string>
 #include <string>
@@ -15,7 +17,9 @@
 #define PLAIN_CONTENT_TYPE   "text/plain"
 #define PLAIN_CONTENT_TYPE   "text/plain"
 #define RES_BODY             "Hello, World!"
 #define RES_BODY             "Hello, World!"
 #define SERVER_NAME          "poco"
 #define SERVER_NAME          "poco"
+#define MAX_CONNECTIONS      16384
 
 
+using namespace Poco;
 using namespace Poco::Net;
 using namespace Poco::Net;
 using namespace Poco::Util;
 using namespace Poco::Util;
 using namespace std;
 using namespace std;
@@ -58,7 +62,12 @@ protected:
         HTTPServerParams* hsp = new HTTPServerParams;
         HTTPServerParams* hsp = new HTTPServerParams;
         hsp->setMaxThreads(stoi(args[1]));
         hsp->setMaxThreads(stoi(args[1]));
         hsp->setKeepAlive(true);
         hsp->setKeepAlive(true);
-        HTTPServer s(new MyRequestHandlerFactory, ServerSocket(stoi(args[0]), 4000), hsp);
+        hsp->setMaxKeepAliveRequests(MAX_CONNECTIONS);
+        hsp->setMaxQueued(MAX_CONNECTIONS);
+        hsp->setThreadPriority(Thread::PRIO_HIGHEST);
+        ServerSocket socket(stoi(args[0]), MAX_CONNECTIONS);
+        socket.setBlocking(false);
+        HTTPServer s(new MyRequestHandlerFactory, socket, hsp);
         s.start();
         s.start();
         waitForTerminationRequest();
         waitForTerminationRequest();
         s.stop();
         s.stop();

+ 6 - 6
frameworks/C++/poco/poco.dockerfile

@@ -1,11 +1,11 @@
-FROM buildpack-deps:xenial
+FROM buildpack-deps:noble
 
 
 RUN apt-get update -yqq && apt-get install -yqq software-properties-common unzip cmake
 RUN apt-get update -yqq && apt-get install -yqq software-properties-common unzip cmake
 
 
-RUN apt-get install -yqq g++-4.8 libjson0-dev
-RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50
+RUN apt-get install -yqq g++-14
+RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 50
 
 
-ENV POCO_VERSION 1.6.1
+ENV POCO_VERSION 1.13.3
 ENV POCO_HOME /poco
 ENV POCO_HOME /poco
 
 
 WORKDIR ${POCO_HOME}
 WORKDIR ${POCO_HOME}
@@ -20,10 +20,10 @@ ENV LD_LIBRARY_PATH ${POCO_HOME}/lib/Linux/x86_64
 
 
 COPY benchmark.cpp benchmark.cpp
 COPY benchmark.cpp benchmark.cpp
 
 
-RUN g++-4.8 \
+RUN g++-14 \
     -O3 \
     -O3 \
     -DNDEBUG \
     -DNDEBUG \
-    -std=c++0x \
+    -std=c++17 \
     -o \
     -o \
     poco \
     poco \
     benchmark.cpp \
     benchmark.cpp \

+ 0 - 19
frameworks/C++/silicon/CMakeLists.txt

@@ -1,19 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-project(silicon)
-
-include_directories(/include $ENV{MICROHTTPD_HOME}/include)
-
-link_directories(/lib $ENV{MICROHTTPD_HOME}/lib)
-
-add_definitions(-std=c++14 -ftemplate-depth=1024 -DNDEBUG -O3)
-
-add_executable(silicon_tpc_mysql techempower_microhttpd.cc)
-target_link_libraries(silicon_tpc_mysql microhttpd mysqlclient)
-
-add_executable(silicon_epoll_mysql techempower_microhttpd.cc)
-set_target_properties(silicon_epoll_mysql PROPERTIES COMPILE_FLAGS "-DTFB_USE_EPOLL")
-target_link_libraries(silicon_epoll_mysql microhttpd mysqlclient)
-
-add_executable(silicon_lwan_mysql techempower_lwan.cc)
-target_link_libraries(silicon_lwan_mysql mysqlclient lwan ubsan curl z pthread dl luajit-5.1)

+ 0 - 8
frameworks/C++/silicon/README.md

@@ -1,8 +0,0 @@
-# C++/silicon Benchmarking test
-
-Silicon is a C++ web framework located at https://github.com/matt-42/silicon
-
-### Note
-
-The `silicon-epoll-mysql` and `silicon-lwan-mysql` tests are currently not working. They have been removed from the `benchmark_config.json` file but the implementations still exist. You can see the old `benchmark_config.json` [here](https://github.com/TechEmpower/FrameworkBenchmarks/blob/5d44d57cbb5cbc209a2d6aeb23010b466c055200/frameworks/C%2B%2B/silicon/benchmark_config.json).
-

+ 0 - 28
frameworks/C++/silicon/benchmark_config.json

@@ -1,28 +0,0 @@
-{
-  "framework": "silicon",
-  "tests": [{
-    "default": {
-      "json_url"       : "/json",
-      "db_url"         : "/db",
-      "query_url"      : "/queries?queries=",
-      "fortune_url"    : "/fortunes",
-      "update_url"     : "/updates?queries=",
-      "plaintext_url"  : "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "silicon",
-      "language": "C++",
-      "flavor": "None",
-      "orm": "Full",
-      "platform": "None",
-      "webserver": "microhttpd",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "silicon-tpc-mysql",
-      "notes": "",
-      "versus": "silicon"
-    }
-  }]
-}

+ 0 - 47
frameworks/C++/silicon/build/symbols.hh

@@ -1,47 +0,0 @@
-// Generated by iod_generate_symbols.
-#include <iod/symbol.hh>
-#ifndef IOD_SYMBOL_db
-#define IOD_SYMBOL_db
-    iod_define_symbol(db)
-#endif
-
-#ifndef IOD_SYMBOL_fortunes
-#define IOD_SYMBOL_fortunes
-    iod_define_symbol(fortunes)
-#endif
-
-#ifndef IOD_SYMBOL_id
-#define IOD_SYMBOL_id
-    iod_define_symbol(id)
-#endif
-
-#ifndef IOD_SYMBOL_json
-#define IOD_SYMBOL_json
-    iod_define_symbol(json)
-#endif
-
-#ifndef IOD_SYMBOL_message
-#define IOD_SYMBOL_message
-    iod_define_symbol(message)
-#endif
-
-#ifndef IOD_SYMBOL_plaintext
-#define IOD_SYMBOL_plaintext
-    iod_define_symbol(plaintext)
-#endif
-
-#ifndef IOD_SYMBOL_queries
-#define IOD_SYMBOL_queries
-    iod_define_symbol(queries)
-#endif
-
-#ifndef IOD_SYMBOL_randomNumber
-#define IOD_SYMBOL_randomNumber
-    iod_define_symbol(randomNumber)
-#endif
-
-#ifndef IOD_SYMBOL_updates
-#define IOD_SYMBOL_updates
-    iod_define_symbol(updates)
-#endif
-

+ 0 - 102
frameworks/C++/silicon/build/techempower.hh

@@ -1,102 +0,0 @@
-#include <unistd.h>
-#include <iostream>
-#include <silicon/api.hh>
-#include <silicon/middleware_factories.hh>
-#include <silicon/middlewares/mysql_connection.hh>
-#include <silicon/middlewares/mysql_orm.hh>
-#include "symbols.hh"
-
-using namespace s;
-using namespace sl;
-
-typedef decltype(D(_id(_auto_increment, _primary_key) = int(),
-                   _randomNumber = int())) random_number;
-
-typedef decltype(D(_id(_auto_increment, _primary_key) = int(),
-                   _message = std::string())) fortune;
-
-typedef mysql_orm_factory<random_number> rn_orm_factory;
-typedef mysql_orm<random_number> rn_orm;
-
-typedef mysql_orm_factory<fortune> fortune_orm_factory;
-typedef mysql_orm<fortune> fortune_orm;
-
-
-std::string escape_html_entities(std::string& data)
-{
-    std::string buffer;
-    buffer.reserve(data.size());
-    for(size_t pos = 0; pos != data.size(); ++pos) {
-        switch(data[pos]) {
-            case '&':  buffer.append("&amp;");       break;
-            case '\"': buffer.append("&quot;");      break;
-            case '\'': buffer.append("&apos;");      break;
-            case '<':  buffer.append("&lt;");        break;
-            case '>':  buffer.append("&gt;");        break;
-            default:   buffer.append(&data[pos], 1); break;
-        }
-    }
-    return std::move(buffer);
-}
-
-auto techempower_api = http_api(
-
-  GET / _plaintext = [] () { return response(_content_type = string_ref("text/plain"),
-                                       _body = string_ref("Hello, World!")); },
-
-  GET / _json = [] () { return response(_content_type = string_ref("application/json"),
-                                  _body = D(_message = "Hello, World!")); },
-                        
-  GET / _db = [] (rn_orm& orm) {
-    random_number r;
-    orm.find_by_id(1245, r);
-    return response(_content_type = "application/json",
-                    _body = r);
-  },
-
-  GET / _queries * get_parameters(_queries = optional(std::string("1"))) = [] (auto param, rn_orm& orm) {
-    int N = atoi(param.queries.c_str());
-    N = std::max(1, std::min(N, 500));
-
-    std::vector<random_number> qs(N);
-    for (int i = 0; i < N; i++)
-      orm.find_by_id(1 + rand() % 9999, qs[i]);
-    return response(_content_type = "application/json",
-                    _body = std::move(qs));
-  },
-
-  GET / _updates * get_parameters(_queries = optional(std::string("1"))) = [] (auto param, rn_orm& orm) {
-    int N = atoi(param.queries.c_str());
-    N = std::max(1, std::min(N, 500));
-
-    std::vector<random_number> qs(N);
-    for (int i = 0; i < N; i++)
-    {
-      orm.find_by_id(1 + rand() % 9999, qs[i]);
-      qs[i].randomNumber = 1 + rand() % 9999;
-      orm.update(qs[i]);
-    }
-    return response(_content_type = "application/json",
-                    _body = std::move(qs));
-  },
-  
-  GET / _fortunes = [] (fortune_orm& orm) {
-    std::vector<fortune> table;
-    orm.forall([&] (fortune& f) { table.push_back(f); });
-    table.push_back(fortune(0, "Additional fortune added at request time."));
-
-    std::sort(table.begin(), table.end(),
-              [] (const fortune& a, const fortune& b) { return a.message < b.message; });
-
-    std::stringstream ss;
-
-    ss << "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>";
-    for(auto& f : table)
-      ss << "<tr><td>" << f.id << "</td><td>" << escape_html_entities(f.message) << "</td></tr>";
-    ss << "</table></body></html>";
-
-    return response(_content_type = "text/html; charset=utf-8",
-                    _body = ss.str());
-  }
-  
-  );

+ 0 - 41
frameworks/C++/silicon/build/techempower_lwan.cc

@@ -1,41 +0,0 @@
-#include <silicon/backends/lwan.hh>
-
-#include "techempower.hh"
-
-using namespace s;
-using namespace sl;
-
-int main(int argc, char* argv[])
-{
-  if (argc != 3)
-  {
-    std::cerr << "Usage: " << argv[0] << " mysql_host port" << std::endl;
-    return 1;
-  }
-
-  auto techempower_middlewares = middleware_factories(
-    mysql_connection_factory(argv[1], "benchmarkdbuser", "benchmarkdbpass", "hello_world"),
-    fortune_orm_factory("Fortune"),
-    rn_orm_factory("World")
-    );
-  
-  try
-  {
-
-    // Write the pid.
-    std::ofstream pidfile(argv[3]);
-    pidfile << getpid() << std::endl;
-    pidfile.close();
-
-    // Start the server.
-    sl::lwan_json_serve(techempower_api, techempower_middlewares, atoi(argv[2]));
-  }
-  catch (std::exception& e)
-  {
-    std::cerr << e.what() << std::endl;
-  }
-  catch (sl::error::error& e)
-  {
-    std::cerr << e.what() << std::endl;
-  }
-}

+ 0 - 48
frameworks/C++/silicon/build/techempower_microhttpd.cc

@@ -1,48 +0,0 @@
-#include <silicon/backends/mhd.hh>
-
-#include "techempower.hh"
-
-using namespace s;
-using namespace sl;
-
-int main(int argc, char* argv[])
-{
-
-  if (argc != 4)
-  {
-    std::cerr << "Usage: " << argv[0] << " mysql_host port nthreads" << std::endl;
-    return 1;
-  }
-
-  auto techempower_middlewares = middleware_factories(
-    mysql_connection_factory(argv[1], "benchmarkdbuser", "benchmarkdbpass", "hello_world"),
-    fortune_orm_factory("Fortune"),
-    rn_orm_factory("World")
-    );
-  
-  try
-  {
-    // Write the pid.
-    std::ofstream pidfile(argv[3]);
-    pidfile << getpid() << std::endl;
-    pidfile.close();
-
-    // Start the server.
-    sl::mhd_json_serve(techempower_api, techempower_middlewares, atoi(argv[2]), _blocking
-#ifdef TFB_USE_EPOLL
-                       , _linux_epoll, _nthreads = atoi(argv[3])
-#else
-                       , _one_thread_per_connection
-#endif
-      );
-    
-  }
-  catch (std::exception& e)
-  {
-    std::cerr << e.what() << std::endl;
-  }
-  catch (sl::error::error& e)
-  {
-    std::cerr << e.what() << std::endl;
-  }
-}

+ 0 - 39
frameworks/C++/silicon/silicon.dockerfile

@@ -1,39 +0,0 @@
-FROM buildpack-deps:xenial
-
-RUN apt-get update -yqq && apt-get install -yqq software-properties-common cmake apt-transport-https
-
-RUN add-apt-repository -s "deb http://apt.llvm.org/`lsb_release -cs`/ llvm-toolchain-`lsb_release -cs`-3.9 main"
-RUN wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key| apt-key add -
-RUN apt-get update -yqq
-RUN apt-get install -yqq clang-3.9 lldb-3.9
-
-ENV MICROHTTPD_VERSION=0.9.39
-ENV MICROHTTPD=/libmicrohttpd
-ENV MICROHTTPD_HOME=$MICROHTTPD-$VERSION
-
-RUN wget http://mirror.ibcp.fr/pub/gnu/libmicrohttpd/libmicrohttpd-$MICROHTTPD_VERSION.tar.gz
-RUN tar xf libmicrohttpd-$MICROHTTPD_VERSION.tar.gz
-RUN cd libmicrohttpd-$MICROHTTPD_VERSION && \
-    ./configure --prefix=$MICROHTTPD_HOME && \
-    make install
-
-ENV PATH=${MICROHTTPD_HOME}/bin:${PATH}
-
-RUN apt-get install -yqq libboost-dev cmake
-
-ENV SILICON=/silicon
-
-COPY ./ ./
-
-RUN git clone https://github.com/matt-42/silicon.git && \
-    cd silicon && \
-    git checkout ecaf04887c9dbbf0f457afab1f487268f6aeffab && \
-    CC=clang-3.9 CXX=clang++-3.9 ./install.sh /
-
-RUN cd build && \
-    cmake .. -DCMAKE_CXX_COMPILER=clang++-3.9 && \
-    make silicon_tpc_mysql
-
-EXPOSE 8080
-
-CMD /build/silicon_tpc_mysql tfb-database 8080 $(nproc)

+ 5 - 4
frameworks/C++/userver/README.md

@@ -2,14 +2,11 @@
 
 
 This is the [userver](https://github.com/userver-framework/userver) portion of a [benchmarking test suite](https://github.com/TechEmpower/FrameworkBenchmarks) comparing a variety of web development platforms.
 This is the [userver](https://github.com/userver-framework/userver) portion of a [benchmarking test suite](https://github.com/TechEmpower/FrameworkBenchmarks) comparing a variety of web development platforms.
 
 
-This benchmarks comes in two configurations: **userver** and **userver-bare**, where both configurations use exactly the same handlers code, but **userver-bare** replaces default http implementation of **userver** with custom one.  
-You see, **userver** being feature-rich framework widely used in production comes with a lot of useful functionality built-in (metrics, dynamic configuring, logging/tracing, congestion control etc...) none of which is of any use in benchmarks; although most of that can be disabled via configs, some parts remain, and these parts aren't free.  
-The aim of **userver-bare** is to explore practical limits of lower-level **userver** functionality when performance is an absolute must, while still being idiomatic userver code.
-
 ### Test Type Implementation Source Code
 ### Test Type Implementation Source Code
 
 
 * [Plaintext](userver_benchmark/controllers/plaintext/handler.cpp)
 * [Plaintext](userver_benchmark/controllers/plaintext/handler.cpp)
 * [Json](userver_benchmark/controllers/json/handler.cpp)
 * [Json](userver_benchmark/controllers/json/handler.cpp)
+* [Fortunes](userver_benchmark/controllers/fortunes/handler.cpp)
 * [Single Database Query](userver_benchmark/controllers/single_query/handler.cpp)
 * [Single Database Query](userver_benchmark/controllers/single_query/handler.cpp)
 * [Multiple Database Queries](userver_benchmark/controllers/multiple_queries/handler.cpp)
 * [Multiple Database Queries](userver_benchmark/controllers/multiple_queries/handler.cpp)
 * [Database Updates](userver_benchmark/controllers/updates/handler.cpp)
 * [Database Updates](userver_benchmark/controllers/updates/handler.cpp)
@@ -24,6 +21,10 @@ http://localhost:8080/plaintext
 
 
 http://localhost:8080/json
 http://localhost:8080/json
 
 
+### Fortunes
+
+http://localhost:8080/fortunes
+
 ### Single Database Query
 ### Single Database Query
 
 
 http://localhost:8080/db
 http://localhost:8080/db

+ 0 - 24
frameworks/C++/userver/benchmark_config.json

@@ -25,30 +25,6 @@
         "display_name": "userver",
         "display_name": "userver",
         "notes": "",
         "notes": "",
         "versus": "None"
         "versus": "None"
-      },
-      "bare": {
-        "json_url": "/json",
-        "plaintext_url": "/plaintext",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "update_url": "/updates?queries=",
-        "cached_query_url": "/cached-queries?count=",
-	"fortune_url": "/fortunes",
-        "port": 8081,
-        "approach": "Realistic",
-        "classification": "Micro",
-        "database": "postgres",
-        "framework": "userver",
-        "language": "C++",
-        "flavor": "None",
-        "orm": "Micro",
-        "platform": "None",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "userver[bare]",
-        "notes": "",
-        "versus": "None"
       }
       }
     }
     }
   ]
   ]

+ 0 - 18
frameworks/C++/userver/config.toml

@@ -18,21 +18,3 @@ orm = "Micro"
 platform = "None"
 platform = "None"
 webserver = "None"
 webserver = "None"
 versus = "None"
 versus = "None"
-
-[bare]
-urls.plaintext = "/plaintext"
-urls.json = "/json"
-urls.db = "/db"
-urls.query = "/queries?queries="
-urls.update = "/updates?queries="
-urls.cached_query = "/cached-queries?count="
-urls.fortune = "/fortunes"
-approach = "Realistic"
-classification = "Micro"
-database = "Postgres"
-database_os = "Linux"
-os = "Linux"
-orm = "Micro"
-platform = "None"
-webserver = "None"
-versus = "None"

+ 0 - 29
frameworks/C++/userver/userver-bare.dockerfile

@@ -1,29 +0,0 @@
-FROM ghcr.io/userver-framework/ubuntu-userver-build-base:v2 AS builder
-
-RUN apt update && \
-    apt install -y lsb-release wget software-properties-common gnupg && \
-        wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 16
-
-WORKDIR /src
-RUN git clone https://github.com/userver-framework/userver.git && \
-    cd userver && git checkout c2ca5454f0b0e93dd0a2e082904dedda5cda3052
-
-COPY userver_benchmark/ ./
-RUN mkdir build && cd build && \
-    cmake -DUSERVER_IS_THE_ROOT_PROJECT=0 -DUSERVER_FEATURE_CRYPTOPP_BLAKE2=0 \
-          -DUSERVER_FEATURE_UTEST=0 \
-          -DUSERVER_FEATURE_POSTGRESQL=1 \
-          -DUSERVER_FEATURE_ERASE_LOG_WITH_LEVEL=warning \
-          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -flto=thin" -DCMAKE_C_FLAGS="-march=native -flto=thin" \
-          -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_COMPILER=clang-16 -DUSERVER_USE_LD=lld-16 \
-          -DUSERVER_LTO=0 .. && \
-    make -j $(nproc)
-
-FROM builder AS runner
-WORKDIR /app
-COPY userver_configs/* ./
-COPY --from=builder /src/build/userver_techempower ./
-
-EXPOSE 8081
-CMD ./userver_techempower -c ./static_config.yaml
-

+ 3 - 3
frameworks/C++/userver/userver.dockerfile

@@ -1,4 +1,4 @@
-FROM ghcr.io/userver-framework/ubuntu-userver-build-base:v2 AS builder
+FROM ghcr.io/userver-framework/ubuntu-22.04-userver-pg AS builder
 
 
 RUN apt update && \
 RUN apt update && \
     apt install -y lsb-release wget software-properties-common gnupg && \
     apt install -y lsb-release wget software-properties-common gnupg && \
@@ -6,7 +6,7 @@ RUN apt update && \
 
 
 WORKDIR /src
 WORKDIR /src
 RUN git clone https://github.com/userver-framework/userver.git && \
 RUN git clone https://github.com/userver-framework/userver.git && \
-    cd userver && git checkout c2ca5454f0b0e93dd0a2e082904dedda5cda3052
+    cd userver && git checkout bdd5e1e03921ff378b062f86a189c3cfa3d66332
 
 
 COPY userver_benchmark/ ./
 COPY userver_benchmark/ ./
 RUN mkdir build && cd build && \
 RUN mkdir build && cd build && \
@@ -14,7 +14,7 @@ RUN mkdir build && cd build && \
           -DUSERVER_FEATURE_UTEST=0 \
           -DUSERVER_FEATURE_UTEST=0 \
           -DUSERVER_FEATURE_POSTGRESQL=1 \
           -DUSERVER_FEATURE_POSTGRESQL=1 \
           -DUSERVER_FEATURE_ERASE_LOG_WITH_LEVEL=warning \
           -DUSERVER_FEATURE_ERASE_LOG_WITH_LEVEL=warning \
-          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -flto=thin" -DCMAKE_C_FLAGS="-march=native -flto=thin" \
+          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native" -DCMAKE_C_FLAGS="-march=native" \
           -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_COMPILER=clang-16 -DUSERVER_USE_LD=lld-16 \
           -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_COMPILER=clang-16 -DUSERVER_USE_LD=lld-16 \
           -DUSERVER_LTO=0 .. && \
           -DUSERVER_LTO=0 .. && \
     make -j $(nproc)
     make -j $(nproc)

+ 2 - 17
frameworks/C++/userver/userver_benchmark/userver_techempower.cpp

@@ -46,20 +46,6 @@ class NoopTracingManager final
       userver::server::http::HttpResponse&) const final {}
       userver::server::http::HttpResponse&) const final {}
 };
 };
 
 
-class MinimalMiddlewarePipelineBuilder final
-    : public userver::server::middlewares::PipelineBuilder {
- public:
-  static constexpr std::string_view kName{
-      "minimal-middleware-pipeline-builder"};
-  using userver::server::middlewares::PipelineBuilder::PipelineBuilder;
-
- private:
-  userver::server::middlewares::MiddlewaresList BuildPipeline(
-      userver::server::middlewares::MiddlewaresList) const override {
-    return {"userver-unknown-exceptions-handling-middleware"};
-  }
-};
-
 int Main(int argc, char* argv[]) {
 int Main(int argc, char* argv[]) {
   auto component_list =
   auto component_list =
       userver::components::MinimalServerComponentList()
       userver::components::MinimalServerComponentList()
@@ -78,10 +64,9 @@ int Main(int argc, char* argv[]) {
           .Append<cached_queries::WorldCacheComponent>()  // cache component
           .Append<cached_queries::WorldCacheComponent>()  // cache component
           .Append<cached_queries::Handler>()
           .Append<cached_queries::Handler>()
           .Append<fortunes::Handler>()
           .Append<fortunes::Handler>()
-          // tracing and metrics tweaks
+          // tracing tweaks
           .Append<NoopTracingManager>()
           .Append<NoopTracingManager>()
-          .Append<MinimalMiddlewarePipelineBuilder>()
-          // bare
+          // bare (not used in the benchmark currently)
           .Append<bare::SimpleRouter>()
           .Append<bare::SimpleRouter>()
           .Append<bare::SimpleServer>();
           .Append<bare::SimpleServer>();
 
 

+ 2 - 5
frameworks/C++/userver/userver_configs/static_config.yaml

@@ -1,8 +1,7 @@
 # yaml
 # yaml
 components_manager:
 components_manager:
     event_thread_pool:
     event_thread_pool:
-        threads: 9
-        dedicated_timer_threads: 1
+        threads: 8
     coro_pool:
     coro_pool:
         initial_size: 10000              # Preallocate 10000 coroutines at startup.
         initial_size: 10000              # Preallocate 10000 coroutines at startup.
         max_size: 300000                 # Do not keep more than 300000 preallocated coroutines.
         max_size: 300000                 # Do not keep more than 300000 preallocated coroutines.
@@ -12,7 +11,7 @@ components_manager:
 
 
         main-task-processor:            # Make a task processor for CPU-bound couroutine tasks.
         main-task-processor:            # Make a task processor for CPU-bound couroutine tasks.
             thread_name: main-worker    # OS will show the threads of this task processor with 'main-worker' prefix.
             thread_name: main-worker    # OS will show the threads of this task processor with 'main-worker' prefix.
-            worker_threads: 46
+            worker_threads: 48
             guess-cpu-limit: true
             guess-cpu-limit: true
 
 
         fs-task-processor:              # Make a separate task processor for filesystem bound tasks.
         fs-task-processor:              # Make a separate task processor for filesystem bound tasks.
@@ -29,7 +28,6 @@ components_manager:
                 handler-defaults:
                 handler-defaults:
                     set_tracing_headers: false
                     set_tracing_headers: false
             server-name: us
             server-name: us
-            middleware-pipeline-builder: minimal-middleware-pipeline-builder
         simple-router:
         simple-router:
         simple-server:
         simple-server:
             port: 8081
             port: 8081
@@ -63,7 +61,6 @@ components_manager:
         noop-tracing-manager:
         noop-tracing-manager:
         tracing-manager-locator:
         tracing-manager-locator:
             component-name: noop-tracing-manager
             component-name: noop-tracing-manager
-        minimal-middleware-pipeline-builder:
 
 
         plaintext-handler:
         plaintext-handler:
             path: /plaintext
             path: /plaintext

+ 0 - 29
frameworks/C/duda/README.md

@@ -1,29 +0,0 @@
-# Duda I/O Benchmarking Test
-
-This is the web service used to benchmark Duda I/O web services framework.
-
-http://duda.io
-
-## Requirements
-
-Just the GNU C Compiler and a Linux system running Kernel version >= 2.6.32
-
-## Tests available
-
-### 1. JSON
-
-URL: /json
-
-### 6. Plain text
-
-URL: /plaintext
-
-## About pending tests
-
-Most of tests that are related to database query are pending and will be available for the next Round.
-
-## Contact
-
-Eduardo Silva <[email protected]>
-
-

+ 0 - 24
frameworks/C/duda/benchmark_config.json

@@ -1,24 +0,0 @@
-{
-  "framework": "duda",
-  "tests": [{
-    "default": {
-      "json_url": "/json",
-      "plaintext_url": "/plaintext",
-      "port": 2001,
-      "approach": "Realistic",
-      "classification": "Platform",
-      "database": "None",
-      "framework": "None",
-      "language": "C",
-      "flavor": "None",
-      "orm": "Raw",
-      "platform": "duda",
-      "webserver": "Monkey",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "Duda I/O",
-      "notes": "",
-      "versus": "duda"
-    }
-  }]
-}

+ 0 - 13
frameworks/C/duda/duda.dockerfile

@@ -1,13 +0,0 @@
-FROM python:2.7
-
-COPY ./ ./
-# Get v0.31 (no official releases that work 2015-06-25)
-
-RUN git clone https://github.com/monkey/dudac.git
-RUN cd dudac && git checkout 7c3d5b03b09fb4cb5f5e338fff72df2e25e95ef0 && \
-    ./dudac -r && \
-    ./dudac -s
-
-EXPOSE 2001
-
-CMD ["./dudac/dudac", "-w", "webservice", "-p", "2001"]

+ 0 - 7
frameworks/C/duda/webservice/Makefile.in

@@ -1,7 +0,0 @@
-NAME    = ws
-CC      = gcc
-CFLAGS  = -g -Wall -O2
-LDFLAGS =
-DEFS    =
-INCDIR  =
-OBJECTS = main.o

+ 0 - 81
frameworks/C/duda/webservice/main.c

@@ -1,81 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-
-/*
- * Duda I/O Benchmark Tests
- * ========================
- * This web service is made for the performance contest made by
- * TechEmpower, mode details here:
- *
- *     http://www.techempower.com/benchmarks
- *
- * At the moment only Tests 1 & 6 are implemented.
- */
-
-#include "webservice.h"
-#include "packages/json/json.h"
-
-/* Test Macros (Tn) */
-#define JSON_CONTENT_TYPE    "Content-Type: application/json"
-#define PLAIN_CONTENT_TYPE   "Content-Type: text/plain"
-#define T6_BODY              "Hello, World!"
-
-DUDA_REGISTER("Duda I/O Benchmark Test", "WS Bench");
-
-/*
- * Test type 1: JSON serialization
- * ===============================
- * This test use the JSON API object to compose the JSON response
- */
-void cb_json(duda_request_t *dr)
-{
-    char *body;
-    int body_len;
-    json_t *j_root;
-
-    /* Instance the JSON object and compose the content */
-    j_root = json->create_object();
-    json->add_to_object(j_root,
-                        "message",
-                        json->create_string("Hello, World!"));
-
-    /* Format output to string */
-    body = json->print_unformatted_gc(dr, j_root);
-    body_len = strlen(body);
-
-    /* Delete the JSON tree */
-    json->delete(j_root);
-
-    /* Compose the response */
-    response->http_status(dr, 200);
-    response->http_header_n(dr, JSON_CONTENT_TYPE, sizeof(JSON_CONTENT_TYPE) - 1);
-    response->print(dr, body, body_len);
-    response->end(dr, NULL);
-}
-
-
-/*
- * Test type 6: Plaintext
- * ======================
- */
-void cb_plaintext(duda_request_t *dr)
-{
-    response->http_status(dr, 200);
-    response->http_header_n(dr, PLAIN_CONTENT_TYPE, sizeof(PLAIN_CONTENT_TYPE) - 1);
-    response->print(dr, T6_BODY, sizeof(T6_BODY) - 1);
-    response->end(dr, NULL);
-}
-
-int duda_main()
-{
-    /* load packages */
-    duda_load_package(json, "json");
-
-    /* let this web service own the virtual host */
-    conf->service_root();
-
-    /* set callbacks */
-    map->static_add("/json", "cb_json");            /* Test #1 */
-    map->static_add("/plaintext", "cb_plaintext");  /* Test #6 */
-
-    return 0;
-}

+ 1 - 0
frameworks/C/h2o/benchmark_config.json

@@ -1,5 +1,6 @@
 {
 {
   "framework": "h2o",
   "framework": "h2o",
+  "maintainers": ["volyrique"],
   "tests": [{
   "tests": [{
     "default": {
     "default": {
       "json_url": "/json",
       "json_url": "/json",

+ 28 - 18
frameworks/C/h2o/h2o.dockerfile

@@ -6,19 +6,28 @@ FROM "ubuntu:${UBUNTU_VERSION}" AS compile
 
 
 ARG DEBIAN_FRONTEND=noninteractive
 ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get -yqq update && \
 RUN apt-get -yqq update && \
+    apt-get -yqq install \
+      ca-certificates \
+      curl \
+      lsb-release && \
+    install -dm755 /usr/share/postgresql-common/pgdg && \
+    curl --fail -LSso /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
+      "https://www.postgresql.org/media/keys/ACCC4CF8.asc" && \
+    sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
+      https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > \
+      /etc/apt/sources.list.d/pgdg.list' && \
+    apt-get -yqq update && \
     apt-get -yqq install \
     apt-get -yqq install \
       autoconf \
       autoconf \
       bison \
       bison \
       cmake \
       cmake \
-      curl \
       flex \
       flex \
       g++ \
       g++ \
       libbpfcc-dev \
       libbpfcc-dev \
       libbrotli-dev \
       libbrotli-dev \
       libcap-dev \
       libcap-dev \
-      libicu-dev \
       libnuma-dev \
       libnuma-dev \
-      libreadline-dev \
+      libpq-dev \
       libssl-dev \
       libssl-dev \
       libtool \
       libtool \
       libuv1-dev \
       libuv1-dev \
@@ -33,7 +42,7 @@ RUN apt-get -yqq update && \
       ruby \
       ruby \
       systemtap-sdt-dev
       systemtap-sdt-dev
 
 
-ARG H2O_VERSION=18b175f71ede08b50d3e5ae8303dacef3ea510fc
+ARG H2O_VERSION=c54c63285b52421da2782f028022647fc2ea3dd1
 
 
 WORKDIR /tmp/h2o-build
 WORKDIR /tmp/h2o-build
 RUN curl -LSs "https://github.com/h2o/h2o/archive/${H2O_VERSION}.tar.gz" | \
 RUN curl -LSs "https://github.com/h2o/h2o/archive/${H2O_VERSION}.tar.gz" | \
@@ -57,18 +66,6 @@ RUN curl -LSs "https://github.com/x86-64/mustache-c/archive/${MUSTACHE_C_REVISIO
     CFLAGS="-flto -march=native -mtune=native -O3" ./autogen.sh && \
     CFLAGS="-flto -march=native -mtune=native -O3" ./autogen.sh && \
     make -j "$(nproc)" install
     make -j "$(nproc)" install
 
 
-ARG POSTGRESQL_VERSION=a37bb7c13995b834095d9d064cad1023a6f99b10
-
-WORKDIR /tmp/postgresql-build
-RUN curl -LSs "https://github.com/postgres/postgres/archive/${POSTGRESQL_VERSION}.tar.gz" | \
-      tar --strip-components=1 -xz && \
-    CFLAGS="-flto -march=native -mtune=native -O3" ./configure \
-      --includedir=/usr/local/include/postgresql \
-      --prefix=/usr/local \
-      --with-ssl=openssl && \
-    make -j "$(nproc)" -C src/include install && \
-    make -j "$(nproc)" -C src/interfaces/libpq install
-
 ARG H2O_APP_PREFIX
 ARG H2O_APP_PREFIX
 WORKDIR /tmp/build
 WORKDIR /tmp/build
 COPY CMakeLists.txt ../
 COPY CMakeLists.txt ../
@@ -85,15 +82,28 @@ RUN cmake \
 
 
 FROM "ubuntu:${UBUNTU_VERSION}"
 FROM "ubuntu:${UBUNTU_VERSION}"
 
 
+ARG POSTGRESQL_VERSION=17
+
 ARG DEBIAN_FRONTEND=noninteractive
 ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get -yqq update && \
 RUN apt-get -yqq update && \
+    apt-get -yqq install \
+      ca-certificates \
+      curl \
+      lsb-release && \
+    install -dm755 /usr/share/postgresql-common/pgdg && \
+    curl --fail -LSso /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
+      "https://www.postgresql.org/media/keys/ACCC4CF8.asc" && \
+    sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
+      https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > \
+      /etc/apt/sources.list.d/pgdg.list' && \
+    apt-get -yqq update && \
     apt-get -yqq install \
     apt-get -yqq install \
       libnuma1 \
       libnuma1 \
-      libyajl2
+      libyajl2 \
+      "postgresql-client-${POSTGRESQL_VERSION}"
 ARG H2O_APP_PREFIX
 ARG H2O_APP_PREFIX
 COPY --from=compile "${H2O_APP_PREFIX}" "${H2O_APP_PREFIX}/"
 COPY --from=compile "${H2O_APP_PREFIX}" "${H2O_APP_PREFIX}/"
 COPY --from=compile /usr/local/lib/libmustache_c.so "${H2O_APP_PREFIX}/lib/"
 COPY --from=compile /usr/local/lib/libmustache_c.so "${H2O_APP_PREFIX}/lib/"
-COPY --from=compile /usr/local/lib/libpq.so.5.17 "${H2O_APP_PREFIX}/lib/libpq.so.5"
 ENV LD_LIBRARY_PATH="${H2O_APP_PREFIX}/lib"
 ENV LD_LIBRARY_PATH="${H2O_APP_PREFIX}/lib"
 EXPOSE 8080
 EXPOSE 8080
 ARG BENCHMARK_ENV
 ARG BENCHMARK_ENV

+ 126 - 83
frameworks/C/h2o/src/database.c

@@ -56,8 +56,8 @@ typedef struct {
 
 
 typedef struct {
 typedef struct {
 	list_t l;
 	list_t l;
-	const char *name;
-	const char *query;
+	char *name;
+	char *query;
 } prepared_statement_t;
 } prepared_statement_t;
 
 
 static h2o_socket_t *create_socket(int sd, h2o_loop_t *loop);
 static h2o_socket_t *create_socket(int sd, h2o_loop_t *loop);
@@ -75,7 +75,7 @@ static void on_database_write_ready(h2o_socket_t *sock, const char *err);
 static void on_process_queries(void *arg);
 static void on_process_queries(void *arg);
 static void poll_database_connection(h2o_socket_t *sock, const char *err);
 static void poll_database_connection(h2o_socket_t *sock, const char *err);
 static void prepare_statements(db_conn_t *conn);
 static void prepare_statements(db_conn_t *conn);
-static void process_queries(db_conn_t *conn, bool removed);
+static void process_queries(db_conn_pool_t *pool);
 static void remove_connection(db_conn_t *conn);
 static void remove_connection(db_conn_t *conn);
 static void start_database_connect(db_conn_pool_t *pool, db_conn_t *conn);
 static void start_database_connect(db_conn_pool_t *pool, db_conn_t *conn);
 
 
@@ -237,7 +237,10 @@ static void on_database_connect_read_ready(h2o_socket_t *sock, const char *err)
 					h2o_timer_unlink(&conn->timer);
 					h2o_timer_unlink(&conn->timer);
 					h2o_socket_read_stop(conn->sock);
 					h2o_socket_read_stop(conn->sock);
 					h2o_socket_read_start(conn->sock, on_database_read_ready);
 					h2o_socket_read_start(conn->sock, on_database_read_ready);
-					process_queries(conn, true);
+					*conn->pool->conn.tail = &conn->l;
+					conn->pool->conn.tail = &conn->l.next;
+					conn->l.next = NULL;
+					process_queries(conn->pool);
 					return;
 					return;
 				default:
 				default:
 					LIBRARY_ERROR("PQresultStatus", PQresultErrorMessage(result));
 					LIBRARY_ERROR("PQresultStatus", PQresultErrorMessage(result));
@@ -370,7 +373,13 @@ static void on_database_read_ready(h2o_socket_t *sock, const char *err)
 	for (PGnotify *notify = PQnotifies(conn->conn); notify; notify = PQnotifies(conn->conn))
 	for (PGnotify *notify = PQnotifies(conn->conn); notify; notify = PQnotifies(conn->conn))
 		PQfreemem(notify);
 		PQfreemem(notify);
 
 
-	process_queries(conn, removed);
+	if (removed && conn->query_num) {
+		*conn->pool->conn.tail = &conn->l;
+		conn->pool->conn.tail = &conn->l.next;
+		conn->l.next = NULL;
+	}
+
+	process_queries(conn->pool);
 }
 }
 
 
 static void on_database_timeout(h2o_timer_t *timer)
 static void on_database_timeout(h2o_timer_t *timer)
@@ -405,20 +414,83 @@ static void on_database_write_ready(h2o_socket_t *sock, const char *err)
 
 
 static void on_process_queries(void *arg)
 static void on_process_queries(void *arg)
 {
 {
+	list_t *iter = NULL;
 	db_conn_pool_t * const pool = arg;
 	db_conn_pool_t * const pool = arg;
+	size_t query_num = 0;
 
 
-	while (pool->queries.head && pool->conn) {
-		db_conn_t * const conn = H2O_STRUCT_FROM_MEMBER(db_conn_t, l, pool->conn);
+	while (pool->queries.head && pool->conn.head) {
+		db_conn_t * const conn = H2O_STRUCT_FROM_MEMBER(db_conn_t, l, pool->conn.head);
+		db_query_param_t * const param = H2O_STRUCT_FROM_MEMBER(db_query_param_t,
+		                                                        l,
+		                                                        conn->pool->queries.head);
 
 
-		pool->conn = conn->l.next;
 		assert(conn->query_num);
 		assert(conn->query_num);
-		process_queries(conn, true);
+		assert(pool->query_num < pool->config->max_query_num);
+		pool->conn.head = conn->l.next;
+		pool->queries.head = param->l.next;
+
+		if (!pool->conn.head) {
+			assert(pool->conn.tail == &conn->l.next);
+			pool->conn.tail = &pool->conn.head;
+		}
+
+		if (++pool->query_num == pool->config->max_query_num) {
+			assert(!pool->queries.head);
+			assert(pool->queries.tail == &param->l.next);
+			pool->queries.tail = &pool->queries.head;
+		}
+
+		if (do_execute_query(conn, param)) {
+			param->on_error(param, DB_ERROR);
+			on_database_error(conn, DB_ERROR);
+		}
+		else {
+			query_num++;
+
+			if (conn->query_num) {
+				*pool->conn.tail = &conn->l;
+				pool->conn.tail = &conn->l.next;
+				conn->l.next = NULL;
+			}
+			else {
+				conn->l.next = iter;
+				iter = &conn->l;
+			}
+		}
 	}
 	}
 
 
-	if (pool->queries.head && pool->conn_num)
-		start_database_connect(pool, NULL);
+	if (iter)
+		do {
+			db_conn_t * const conn = H2O_STRUCT_FROM_MEMBER(db_conn_t, l, iter);
+
+			iter = conn->l.next;
+
+			if (flush_connection(on_database_write_ready, conn))
+				on_database_error(conn, DB_ERROR);
+		} while (iter);
 
 
+	pool->conn.tail = &pool->conn.head;
 	pool->process_queries = false;
 	pool->process_queries = false;
+	query_num += pool->config->max_query_num - pool->query_num;
+
+	for (iter = pool->conn.head; iter;) {
+		db_conn_t * const conn = H2O_STRUCT_FROM_MEMBER(db_conn_t, l, iter);
+
+		iter = conn->l.next;
+
+		if (flush_connection(on_database_write_ready, conn)) {
+			*pool->conn.tail = iter;
+			on_database_error(conn, DB_ERROR);
+		}
+		else
+			pool->conn.tail = &conn->l.next;
+	}
+
+	const size_t conn_num = pool->config->max_db_conn_num - pool->conn_num;
+
+	if (query_num > conn_num)
+		for (query_num -= conn_num; pool->conn_num && query_num; query_num--)
+			start_database_connect(pool, NULL);
 }
 }
 
 
 static void poll_database_connection(h2o_socket_t *sock, const char *err)
 static void poll_database_connection(h2o_socket_t *sock, const char *err)
@@ -536,54 +608,44 @@ static void prepare_statements(db_conn_t *conn)
 	}
 	}
 	else {
 	else {
 		h2o_socket_read_start(conn->sock, on_database_read_ready);
 		h2o_socket_read_start(conn->sock, on_database_read_ready);
-		process_queries(conn, true);
+		*conn->pool->conn.tail = &conn->l;
+		conn->pool->conn.tail = &conn->l.next;
+		conn->l.next = NULL;
+		process_queries(conn->pool);
 	}
 	}
 }
 }
 
 
-static void process_queries(db_conn_t *conn, bool removed)
+static void process_queries(db_conn_pool_t *pool)
 {
 {
-	const bool flush = conn->query_num && conn->pool->queries.head;
-
-	while (conn->query_num && conn->pool->queries.head) {
-		db_query_param_t * const param = H2O_STRUCT_FROM_MEMBER(db_query_param_t,
-		                                                        l,
-		                                                        conn->pool->queries.head);
-
-		if (++conn->pool->query_num == conn->pool->config->max_query_num) {
-			assert(conn->pool->queries.tail == &param->l.next);
-			conn->pool->queries.tail = &conn->pool->queries.head;
-		}
-
-		conn->pool->queries.head = param->l.next;
-
-		if (do_execute_query(conn, param)) {
-			param->on_error(param, DB_ERROR);
-			on_database_error(conn, DB_ERROR);
-			return;
-		}
-	}
-
-	if (flush && flush_connection(on_database_write_ready, conn))
-		on_database_error(conn, DB_ERROR);
-	else if (conn->query_num && removed) {
-		conn->l.next = conn->pool->conn;
-		conn->pool->conn = &conn->l;
+	if (!pool->process_queries && pool->queries.head) {
+		task_message_t * const msg = h2o_mem_alloc(sizeof(*msg));
+
+		assert(pool->query_num < pool->config->max_query_num);
+		memset(msg, 0, sizeof(*msg));
+		msg->arg = pool;
+		msg->super.type = TASK;
+		msg->task = on_process_queries;
+		pool->process_queries = true;
+		send_local_message(&msg->super, pool->local_messages);
 	}
 	}
-	else if (!conn->query_num && !removed)
-		// This call should not be problematic, assuming a relatively low number of connections.
-		remove_connection(conn);
 }
 }
 
 
 static void remove_connection(db_conn_t *conn)
 static void remove_connection(db_conn_t *conn)
 {
 {
-	list_t *iter = conn->pool->conn;
-	list_t **prev = &conn->pool->conn;
+	list_t *iter = conn->pool->conn.head;
+	list_t **prev = &conn->pool->conn.head;
 
 
 	for (; iter && iter != &conn->l; iter = iter->next)
 	for (; iter && iter != &conn->l; iter = iter->next)
 		prev = &iter->next;
 		prev = &iter->next;
 
 
-	if (iter)
+	if (iter) {
 		*prev = iter->next;
 		*prev = iter->next;
+
+		if (!conn->pool->conn.head) {
+			assert(conn->pool->conn.tail == &iter->next);
+			conn->pool->conn.tail = &conn->pool->conn.head;
+		}
+	}
 }
 }
 
 
 static void start_database_connect(db_conn_pool_t *pool, db_conn_t *conn)
 static void start_database_connect(db_conn_pool_t *pool, db_conn_t *conn)
@@ -651,8 +713,8 @@ void add_prepared_statement(const char *name, const char *query, list_t **prepar
 
 
 	memset(p, 0, sizeof(*p));
 	memset(p, 0, sizeof(*p));
 	p->l.next = *prepared_statements;
 	p->l.next = *prepared_statements;
-	p->name = name;
-	p->query = query;
+	p->name = h2o_strdup(NULL, name, SIZE_MAX).base;
+	p->query = h2o_strdup(NULL, query, SIZE_MAX).base;
 	*prepared_statements = &p->l;
 	*prepared_statements = &p->l;
 }
 }
 
 
@@ -661,37 +723,15 @@ int execute_database_query(db_conn_pool_t *pool, db_query_param_t *param)
 	int ret = 1;
 	int ret = 1;
 
 
 	if (pool->query_num) {
 	if (pool->query_num) {
-		if (pool->conn) {
-			// Delay sending the database queries to the server, so that if there is a rapid
-			// succession of calls to this function, all resultant queries would be inserted
-			// into a command pipeline with a smaller number of system calls.
-			if (!pool->process_queries) {
-				task_message_t * const msg = h2o_mem_alloc(sizeof(*msg));
-
-				memset(msg, 0, sizeof(*msg));
-				msg->arg = pool;
-				msg->super.type = TASK;
-				msg->task = on_process_queries;
-				send_local_message(&msg->super, pool->local_messages);
-				pool->process_queries = true;
-			}
-
-			ret = 0;
-		}
-		else {
-			if (pool->conn_num)
-				start_database_connect(pool, NULL);
-
-			if (pool->conn_num < pool->config->max_db_conn_num && pool->query_num)
-				ret = 0;
-		}
-
-		if (!ret) {
-			param->l.next = NULL;
-			*pool->queries.tail = &param->l;
-			pool->queries.tail = &param->l.next;
-			pool->query_num--;
-		}
+		// Delay sending the database queries to the server, so that if there is a rapid
+		// succession of calls to this function, all resultant queries would be inserted
+		// into a command pipeline with a smaller number of system calls.
+		param->l.next = NULL;
+		*pool->queries.tail = &param->l;
+		pool->queries.tail = &param->l.next;
+		pool->query_num--;
+		process_queries(pool);
+		ret = 0;
 	}
 	}
 
 
 	return ret;
 	return ret;
@@ -704,9 +744,9 @@ void free_database_connection_pool(db_conn_pool_t *pool)
 
 
 	size_t num = 0;
 	size_t num = 0;
 
 
-	if (pool->conn)
+	if (pool->conn.head)
 		do {
 		do {
-			db_conn_t * const conn = H2O_STRUCT_FROM_MEMBER(db_conn_t, l, pool->conn);
+			db_conn_t * const conn = H2O_STRUCT_FROM_MEMBER(db_conn_t, l, pool->conn.head);
 
 
 			assert(!conn->queries.head);
 			assert(!conn->queries.head);
 			assert(conn->query_num == pool->config->max_pipeline_query_num);
 			assert(conn->query_num == pool->config->max_pipeline_query_num);
@@ -715,10 +755,10 @@ void free_database_connection_pool(db_conn_pool_t *pool)
 			h2o_socket_read_stop(conn->sock);
 			h2o_socket_read_stop(conn->sock);
 			h2o_socket_close(conn->sock);
 			h2o_socket_close(conn->sock);
 			PQfinish(conn->conn);
 			PQfinish(conn->conn);
-			pool->conn = pool->conn->next;
-			free(conn);
+			pool->conn.head = conn->l.next;
 			num++;
 			num++;
-		} while (pool->conn);
+			free(conn);
+		} while (pool->conn.head);
 
 
 	assert(num + pool->conn_num == pool->config->max_db_conn_num);
 	assert(num + pool->conn_num == pool->config->max_db_conn_num);
 }
 }
@@ -732,6 +772,7 @@ void initialize_database_connection_pool(const char *conninfo,
 {
 {
 	memset(pool, 0, sizeof(*pool));
 	memset(pool, 0, sizeof(*pool));
 	pool->config = config;
 	pool->config = config;
+	pool->conn.tail = &pool->conn.head;
 	pool->conninfo = conninfo ? conninfo : "";
 	pool->conninfo = conninfo ? conninfo : "";
 	pool->local_messages = local_messages;
 	pool->local_messages = local_messages;
 	pool->loop = loop;
 	pool->loop = loop;
@@ -750,6 +791,8 @@ void remove_prepared_statements(list_t *prepared_statements)
 			                                                        prepared_statements);
 			                                                        prepared_statements);
 
 
 			prepared_statements = prepared_statements->next;
 			prepared_statements = prepared_statements->next;
+			free(p->name);
+			free(p->query);
 			free(p);
 			free(p);
 		} while (prepared_statements);
 		} while (prepared_statements);
 }
 }

+ 3 - 3
frameworks/C/h2o/src/database.h

@@ -49,10 +49,10 @@ typedef struct db_query_param_t {
 	on_result_t on_result;
 	on_result_t on_result;
 	void (*on_timeout)(struct db_query_param_t *);
 	void (*on_timeout)(struct db_query_param_t *);
 	const char *command;
 	const char *command;
-	const char * const *paramValues;
-	const int *paramLengths;
 	const int *paramFormats;
 	const int *paramFormats;
+	const int *paramLengths;
 	const Oid *paramTypes;
 	const Oid *paramTypes;
+	const char * const *paramValues;
 	size_t nParams;
 	size_t nParams;
 	uint_fast32_t flags;
 	uint_fast32_t flags;
 	int resultFormat;
 	int resultFormat;
@@ -60,7 +60,7 @@ typedef struct db_query_param_t {
 
 
 typedef struct {
 typedef struct {
 	const struct config_t *config;
 	const struct config_t *config;
-	list_t *conn;
+	queue_t conn;
 	const char *conninfo;
 	const char *conninfo;
 	h2o_linklist_t *local_messages;
 	h2o_linklist_t *local_messages;
 	h2o_loop_t *loop;
 	h2o_loop_t *loop;

+ 29 - 0
frameworks/C/h2o/src/event_loop.c

@@ -32,13 +32,16 @@
 #include <netinet/tcp.h>
 #include <netinet/tcp.h>
 #include <openssl/ssl.h>
 #include <openssl/ssl.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/types.h>
 
 
 #include "error.h"
 #include "error.h"
 #include "event_loop.h"
 #include "event_loop.h"
 #include "global_data.h"
 #include "global_data.h"
 #include "thread.h"
 #include "thread.h"
+#include "utility.h"
 
 
+#define CONN_NUM_SAMPLE_PERIOD 2500
 #define DEFAULT_TCP_FASTOPEN_QUEUE_LEN 4096
 #define DEFAULT_TCP_FASTOPEN_QUEUE_LEN 4096
 
 
 static void accept_connection(h2o_socket_t *listener, const char *err);
 static void accept_connection(h2o_socket_t *listener, const char *err);
@@ -72,6 +75,7 @@ static void accept_connection(h2o_socket_t *listener, const char *err)
 				if (!sock)
 				if (!sock)
 					break;
 					break;
 
 
+				ctx->event_loop.accepted_conn_num++;
 				ctx->event_loop.conn_num++;
 				ctx->event_loop.conn_num++;
 				sock->on_close.cb = on_close_connection;
 				sock->on_close.cb = on_close_connection;
 				sock->on_close.data = &ctx->event_loop.conn_num;
 				sock->on_close.data = &ctx->event_loop.conn_num;
@@ -277,11 +281,36 @@ static void start_accept_polling(const config_t *config,
 
 
 void event_loop(struct thread_context_t *ctx)
 void event_loop(struct thread_context_t *ctx)
 {
 {
+	uint64_t last_sample = 0;
+
 	while (!ctx->shutdown || ctx->event_loop.conn_num) {
 	while (!ctx->shutdown || ctx->event_loop.conn_num) {
 		h2o_evloop_run(ctx->event_loop.h2o_ctx.loop, INT32_MAX);
 		h2o_evloop_run(ctx->event_loop.h2o_ctx.loop, INT32_MAX);
 		process_messages(&ctx->global_thread_data->h2o_receiver,
 		process_messages(&ctx->global_thread_data->h2o_receiver,
 		                 &ctx->event_loop.local_messages);
 		                 &ctx->event_loop.local_messages);
+
+		const uint64_t now = h2o_now(ctx->event_loop.h2o_ctx.loop);
+
+		if (now - last_sample > CONN_NUM_SAMPLE_PERIOD || last_sample > now) {
+			const size_t i = ctx->event_loop.conn_num_sample_idx;
+
+			ctx->event_loop.conn_num_sample[i] = ctx->event_loop.conn_num;
+			ctx->event_loop.conn_num_sample_idx =
+				(i + 1) % ARRAY_SIZE(ctx->event_loop.conn_num_sample);
+			last_sample = now;
+		}
 	}
 	}
+
+	flockfile(stdout);
+	printf("Thread %ld statistics:\nAccepted connections: %zu\nConnection number samples: %zu",
+	       syscall(SYS_gettid),
+	       ctx->event_loop.accepted_conn_num,
+	       *ctx->event_loop.conn_num_sample);
+
+	for (size_t i = 1; i < ARRAY_SIZE(ctx->event_loop.conn_num_sample); i++)
+		printf(",%zu", ctx->event_loop.conn_num_sample[i]);
+
+	putc_unlocked('\n', stdout);
+	funlockfile(stdout);
 }
 }
 
 
 void free_event_loop(event_loop_t *event_loop, h2o_multithread_receiver_t *h2o_receiver)
 void free_event_loop(event_loop_t *event_loop, h2o_multithread_receiver_t *h2o_receiver)

+ 5 - 0
frameworks/C/h2o/src/event_loop.h

@@ -27,6 +27,8 @@
 
 
 #include "global_data.h"
 #include "global_data.h"
 
 
+#define CONN_NUM_SAMPLES 512
+
 typedef enum {
 typedef enum {
 	SHUTDOWN,
 	SHUTDOWN,
 	TASK
 	TASK
@@ -41,6 +43,9 @@ typedef struct {
 	h2o_accept_ctx_t h2o_accept_ctx;
 	h2o_accept_ctx_t h2o_accept_ctx;
 	h2o_context_t h2o_ctx;
 	h2o_context_t h2o_ctx;
 	h2o_linklist_t local_messages;
 	h2o_linklist_t local_messages;
+	size_t accepted_conn_num;
+	size_t conn_num_sample[CONN_NUM_SAMPLES];
+	size_t conn_num_sample_idx;
 } event_loop_t;
 } event_loop_t;
 
 
 typedef struct {
 typedef struct {

+ 123 - 65
frameworks/C/h2o/src/handlers/world.c

@@ -57,17 +57,18 @@
 // MAX_UPDATE_QUERY_LEN must be updated whenever UPDATE_QUERY_BEGIN, UPDATE_QUERY_ELEM,
 // MAX_UPDATE_QUERY_LEN must be updated whenever UPDATE_QUERY_BEGIN, UPDATE_QUERY_ELEM,
 // UPDATE_QUERY_MIDDLE, UPDATE_QUERY_ELEM2, and UPDATE_QUERY_END are changed.
 // UPDATE_QUERY_MIDDLE, UPDATE_QUERY_ELEM2, and UPDATE_QUERY_END are changed.
 #define UPDATE_QUERY_BEGIN "UPDATE " WORLD_TABLE_NAME " SET randomNumber = CASE id "
 #define UPDATE_QUERY_BEGIN "UPDATE " WORLD_TABLE_NAME " SET randomNumber = CASE id "
-#define UPDATE_QUERY_ELEM "WHEN %" PRIu32 " THEN %" PRIu32 " "
-#define UPDATE_QUERY_MIDDLE "ELSE randomNumber END WHERE id IN (%" PRIu32
-#define UPDATE_QUERY_ELEM2 ",%" PRIu32
+#define UPDATE_QUERY_ELEM "WHEN $%zu::integer THEN $%zu::integer "
+#define UPDATE_QUERY_MIDDLE "ELSE randomNumber END WHERE id IN ($1::integer"
+#define UPDATE_QUERY_ELEM2 ",$%zu::integer"
 #define UPDATE_QUERY_END ");"
 #define UPDATE_QUERY_END ");"
 
 
 #define MAX_UPDATE_QUERY_LEN(n) \
 #define MAX_UPDATE_QUERY_LEN(n) \
 	(sizeof(UPDATE_QUERY_BEGIN) + sizeof(UPDATE_QUERY_MIDDLE) + \
 	(sizeof(UPDATE_QUERY_BEGIN) + sizeof(UPDATE_QUERY_MIDDLE) + \
 	 sizeof(UPDATE_QUERY_END) - 1 - sizeof(UPDATE_QUERY_ELEM2) + \
 	 sizeof(UPDATE_QUERY_END) - 1 - sizeof(UPDATE_QUERY_ELEM2) + \
 	 (n) * (sizeof(UPDATE_QUERY_ELEM) - 1 + sizeof(UPDATE_QUERY_ELEM2) - 1 + \
 	 (n) * (sizeof(UPDATE_QUERY_ELEM) - 1 + sizeof(UPDATE_QUERY_ELEM2) - 1 + \
-	        3 * (sizeof(MKSTR(MAX_ID)) - 1) - 3 * (sizeof(PRIu32) - 1) - 3))
+	        3 * sizeof(MKSTR(MAX_QUERIES)) - 3 * (sizeof("%zu") - 1)))
 
 
+#define UPDATE_QUERY_NAME_PREFIX WORLD_TABLE_NAME "Update"
 #define USE_CACHE 2
 #define USE_CACHE 2
 #define WORLD_QUERY "SELECT * FROM " WORLD_TABLE_NAME " WHERE id = $1::integer;"
 #define WORLD_QUERY "SELECT * FROM " WORLD_TABLE_NAME " WHERE id = $1::integer;"
 
 
@@ -236,8 +237,10 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req)
 
 
 	const size_t num_query = get_query_number(req);
 	const size_t num_query = get_query_number(req);
 
 
-	// MAX_QUERIES is a relatively small number, so assume no overflow in the following
-	// arithmetic operations.
+	// MAX_QUERIES is a relatively small number, say less than or equal to UINT16_MAX, so assume no
+	// unsigned overflow in the following arithmetic operations.
+	static_assert(MAX_QUERIES <= UINT16_MAX,
+	              "potential out-of-bounds memory accesses in the following code");
 	assert(num_query && num_query <= MAX_QUERIES);
 	assert(num_query && num_query <= MAX_QUERIES);
 
 
 	size_t base_size = offsetof(multiple_query_ctx_t, res) + num_query * sizeof(query_result_t);
 	size_t base_size = offsetof(multiple_query_ctx_t, res) + num_query * sizeof(query_result_t);
@@ -259,11 +262,16 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req)
 	size_t sz = base_size + num_query_in_progress * sizeof(query_param_t);
 	size_t sz = base_size + num_query_in_progress * sizeof(query_param_t);
 
 
 	if (do_update) {
 	if (do_update) {
-		const size_t reuse_size = (num_query_in_progress - 1) * sizeof(query_param_t);
-		const size_t update_query_len = MAX_UPDATE_QUERY_LEN(num_query);
+		size_t s = base_size + sizeof(query_param_t);
 
 
-		if (update_query_len > reuse_size)
-			sz += update_query_len - reuse_size;
+		s = (s + _Alignof(const char *) - 1) / _Alignof(const char *);
+		s = s * _Alignof(const char *) + 2 * num_query * sizeof(const char *);
+		s = (s + _Alignof(int) - 1) / _Alignof(int);
+		s = s * _Alignof(int) + 4 * num_query * sizeof(int);
+		s += sizeof(UPDATE_QUERY_NAME_PREFIX MKSTR(MAX_QUERIES));
+
+		if (s > sz)
+			sz = s;
 	}
 	}
 
 
 	multiple_query_ctx_t * const query_ctx = h2o_mem_alloc(sz);
 	multiple_query_ctx_t * const query_ctx = h2o_mem_alloc(sz);
@@ -332,65 +340,57 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req)
 
 
 static void do_updates(multiple_query_ctx_t *query_ctx)
 static void do_updates(multiple_query_ctx_t *query_ctx)
 {
 {
-	char *iter = (char *) (query_ctx->query_param + 1);
-	size_t sz = MAX_UPDATE_QUERY_LEN(query_ctx->num_result);
-
-	// Sort the results to avoid database deadlock.
-	qsort(query_ctx->res, query_ctx->num_result, sizeof(*query_ctx->res), compare_items);
-	query_ctx->query_param->param.command = iter;
-	query_ctx->query_param->param.nParams = 0;
-	query_ctx->query_param->param.on_result = on_update_result;
-	query_ctx->query_param->param.paramFormats = NULL;
-	query_ctx->query_param->param.paramLengths = NULL;
-	query_ctx->query_param->param.paramValues = NULL;
-	query_ctx->query_param->param.flags = 0;
+	size_t offset =
+		offsetof(multiple_query_ctx_t, res) + query_ctx->num_result * sizeof(*query_ctx->res);
 
 
-	int c = snprintf(iter, sz, UPDATE_QUERY_BEGIN);
-
-	if ((size_t) c >= sz)
-		goto error;
-
-	iter += c;
-	sz -= c;
-
-	for (size_t i = 0; i < query_ctx->num_result; i++) {
-		query_ctx->res[i].random_number = 1 + get_random_number(MAX_ID,
-		                                                        &query_ctx->ctx->random_seed);
-		c = snprintf(iter,
-		             sz,
-		             UPDATE_QUERY_ELEM,
-		             query_ctx->res[i].id,
-		             query_ctx->res[i].random_number);
+	offset = ((offset + _Alignof(query_param_t) - 1) / _Alignof(query_param_t));
+	offset = offset * _Alignof(query_param_t) + sizeof(query_param_t);
+	offset = (offset + _Alignof(const char *) - 1) / _Alignof(const char *);
+	offset *= _Alignof(const char *);
 
 
-		if ((size_t) c >= sz)
-			goto error;
+	const char ** const paramValues = (const char **) ((char *) query_ctx + offset);
+	const size_t nParams = query_ctx->num_result * 2;
 
 
-		iter += c;
-		sz -= c;
-	}
+	offset += nParams * sizeof(*paramValues);
+	offset = (offset + _Alignof(int) - 1) / _Alignof(int);
+	offset *= _Alignof(int);
 
 
-	c = snprintf(iter, sz, UPDATE_QUERY_MIDDLE, query_ctx->res->id);
+	int * const paramFormats = (int *) ((char *) query_ctx + offset);
+	int * const paramLengths = paramFormats + nParams;
+	char * const command = (char *) (paramLengths + nParams);
+	const size_t command_size =
+		sizeof(UPDATE_QUERY_NAME_PREFIX MKSTR(MAX_QUERIES)) - sizeof(UPDATE_QUERY_NAME_PREFIX) + 1;
+	const int c = snprintf(command + sizeof(UPDATE_QUERY_NAME_PREFIX) - 1,
+	                       command_size,
+	                       "%zu",
+	                       query_ctx->num_result);
 
 
-	if ((size_t) c >= sz)
+	if ((size_t) c >= command_size)
 		goto error;
 		goto error;
 
 
-	iter += c;
-	sz -= c;
-
-	for (size_t i = 1; i < query_ctx->num_result; i++) {
-		c = snprintf(iter, sz, UPDATE_QUERY_ELEM2, query_ctx->res[i].id);
-
-		if ((size_t) c >= sz)
-			goto error;
-
-		iter += c;
-		sz -= c;
-	}
-
-	c = snprintf(iter, sz, UPDATE_QUERY_END);
+	memcpy(command, UPDATE_QUERY_NAME_PREFIX, sizeof(UPDATE_QUERY_NAME_PREFIX) - 1);
+	// Sort the results to avoid database deadlock.
+	qsort(query_ctx->res, query_ctx->num_result, sizeof(*query_ctx->res), compare_items);
 
 
-	if ((size_t) c >= sz)
-		goto error;
+	for (size_t i = 0; i < query_ctx->num_result; i++) {
+		query_ctx->res[i].id = htonl(query_ctx->res[i].id);
+		query_ctx->res[i].random_number =
+			htonl(1 + get_random_number(MAX_ID, &query_ctx->ctx->random_seed));
+		paramFormats[2 * i] = 1;
+		paramFormats[2 * i + 1] = 1;
+		paramLengths[2 * i] = sizeof(query_ctx->res[i].id);
+		paramLengths[2 * i + 1] = sizeof(query_ctx->res[i].random_number);
+		paramValues[2 * i] = (const char *) &query_ctx->res[i].id;
+		paramValues[2 * i + 1] = (const char *) &query_ctx->res[i].random_number;
+	}
+
+	query_ctx->query_param->param.command = command;
+	query_ctx->query_param->param.flags = IS_PREPARED;
+	query_ctx->query_param->param.nParams = nParams;
+	query_ctx->query_param->param.on_result = on_update_result;
+	query_ctx->query_param->param.paramFormats = paramFormats;
+	query_ctx->query_param->param.paramLengths = paramLengths;
+	query_ctx->query_param->param.paramValues = paramValues;
 
 
 	if (execute_database_query(&query_ctx->ctx->request_handler_data.hello_world_db,
 	if (execute_database_query(&query_ctx->ctx->request_handler_data.hello_world_db,
 	                           &query_ctx->query_param->param)) {
 	                           &query_ctx->query_param->param)) {
@@ -416,7 +416,7 @@ static void fetch_from_cache(uint64_t now,
 		h2o_cache_ref_t * const r = h2o_cache_fetch(data->world_cache, now, key, 0);
 		h2o_cache_ref_t * const r = h2o_cache_fetch(data->world_cache, now, key, 0);
 
 
 		if (r) {
 		if (r) {
-			const uint32_t * const table = (const uint32_t *) r->value.base;
+			const uint16_t * const table = (const uint16_t *) r->value.base;
 
 
 			for (size_t i = 0; i < query_ctx->num_query; i++) {
 			for (size_t i = 0; i < query_ctx->num_query; i++) {
 				const uint32_t id = query_ctx->res[i].id;
 				const uint32_t id = query_ctx->res[i].id;
@@ -440,7 +440,7 @@ static void fetch_from_cache(uint64_t now,
 			memset(ctx, 0, sizeof(*ctx));
 			memset(ctx, 0, sizeof(*ctx));
 			ctx->data = data;
 			ctx->data = data;
 			ctx->loop = query_ctx->ctx->event_loop.h2o_ctx.loop;
 			ctx->loop = query_ctx->ctx->event_loop.h2o_ctx.loop;
-			ctx->table.len = (MAX_ID + 1) * sizeof(uint32_t);
+			ctx->table.len = (MAX_ID + 1) * sizeof(uint16_t);
 			ctx->table.base = h2o_mem_alloc(ctx->table.len);
 			ctx->table.base = h2o_mem_alloc(ctx->table.len);
 			memset(ctx->table.base, 0, ctx->table.len);
 			memset(ctx->table.base, 0, ctx->table.len);
 			ctx->param.command = POPULATE_CACHE_QUERY;
 			ctx->param.command = POPULATE_CACHE_QUERY;
@@ -605,10 +605,11 @@ static result_return_t on_populate_cache_result(db_query_param_t *param, PGresul
 		                                                                param,
 		                                                                param,
 		                                                                param);
 		                                                                param);
 		query_result_t r = {.id = 0};
 		query_result_t r = {.id = 0};
-		uint32_t * const table = (uint32_t *) query_ctx->table.base;
+		uint16_t * const table = (uint16_t *) query_ctx->table.base;
 
 
 		for (size_t i = 0; i < num_rows; i++) {
 		for (size_t i = 0; i < num_rows; i++) {
 			process_result(result, i, &r);
 			process_result(result, i, &r);
+			assert(r.random_number <= UINT16_MAX);
 			table[r.id] = r.random_number;
 			table[r.id] = r.random_number;
 		}
 		}
 
 
@@ -725,8 +726,14 @@ static result_return_t on_update_result(db_query_param_t *param, PGresult *resul
 		query_ctx->gen = get_json_generator(&query_ctx->ctx->json_generator,
 		query_ctx->gen = get_json_generator(&query_ctx->ctx->json_generator,
 		                                    &query_ctx->ctx->json_generator_num);
 		                                    &query_ctx->ctx->json_generator_num);
 
 
-		if (query_ctx->gen)
+		if (query_ctx->gen) {
+			for (size_t i = 0; i < query_ctx->num_result; i++) {
+				query_ctx->res[i].id = ntohl(query_ctx->res[i].id);
+				query_ctx->res[i].random_number = ntohl(query_ctx->res[i].random_number);
+			}
+
 			serialize_items(query_ctx->res, query_ctx->num_result, &query_ctx->gen, query_ctx->req);
 			serialize_items(query_ctx->res, query_ctx->num_result, &query_ctx->gen, query_ctx->req);
+		}
 		else
 		else
 			send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, query_ctx->req);
 			send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, query_ctx->req);
 	}
 	}
@@ -886,6 +893,57 @@ void initialize_world_handlers(h2o_hostconf_t *hostconf,
                                h2o_access_log_filehandle_t *log_handle,
                                h2o_access_log_filehandle_t *log_handle,
                                request_handler_data_t *data)
                                request_handler_data_t *data)
 {
 {
+	char name[sizeof(UPDATE_QUERY_NAME_PREFIX MKSTR(MAX_QUERIES))];
+	char query[MAX_UPDATE_QUERY_LEN(MAX_QUERIES)];
+	const size_t name_size = sizeof(name) - sizeof(UPDATE_QUERY_NAME_PREFIX) + 1;
+
+	assert(sizeof(name) >= sizeof(UPDATE_QUERY_NAME_PREFIX));
+	memcpy(name, UPDATE_QUERY_NAME_PREFIX, sizeof(UPDATE_QUERY_NAME_PREFIX) - 1);
+	assert(sizeof(query) >= sizeof(UPDATE_QUERY_BEGIN));
+	memcpy(query, UPDATE_QUERY_BEGIN, sizeof(UPDATE_QUERY_BEGIN) - 1);
+
+	for (size_t i = 0; i < MAX_QUERIES; i++) {
+		char *iter = query + sizeof(UPDATE_QUERY_BEGIN) - 1;
+		size_t sz = sizeof(query) - sizeof(UPDATE_QUERY_BEGIN) + 1;
+		int c = snprintf(name + sizeof(UPDATE_QUERY_NAME_PREFIX) - 1, name_size, "%zu", i + 1);
+
+		if ((size_t) c >= name_size)
+			continue;
+
+		for (size_t j = 0; j <= i; j++) {
+			c = snprintf(iter,
+			             sz,
+			             UPDATE_QUERY_ELEM,
+			             2 * j + 1,
+			             2 * j + 2);
+
+			if ((size_t) c >= sz)
+				continue;
+
+			iter += c;
+			sz -= c;
+		}
+
+		assert(sz >= sizeof(UPDATE_QUERY_MIDDLE));
+		memcpy(iter, UPDATE_QUERY_MIDDLE, sizeof(UPDATE_QUERY_MIDDLE) - 1);
+		iter += sizeof(UPDATE_QUERY_MIDDLE) - 1;
+		sz -= sizeof(UPDATE_QUERY_MIDDLE) - 1;
+
+		for (size_t j = 1; j <= i; j++) {
+			c = snprintf(iter, sz, UPDATE_QUERY_ELEM2, 2 * j + 1);
+
+			if ((size_t) c >= sz)
+				continue;
+
+			iter += c;
+			sz -= c;
+		}
+
+		assert(sz >= sizeof(UPDATE_QUERY_END));
+		memcpy(iter, UPDATE_QUERY_END, sizeof(UPDATE_QUERY_END));
+		add_prepared_statement(name, query, &data->prepared_statements);
+	}
+
 	add_prepared_statement(WORLD_TABLE_NAME, WORLD_QUERY, &data->prepared_statements);
 	add_prepared_statement(WORLD_TABLE_NAME, WORLD_QUERY, &data->prepared_statements);
 	register_request_handler("/cached-worlds", cached_queries, hostconf, log_handle);
 	register_request_handler("/cached-worlds", cached_queries, hostconf, log_handle);
 	register_request_handler("/db", single_query, hostconf, log_handle);
 	register_request_handler("/db", single_query, hostconf, log_handle);

+ 0 - 17
frameworks/CSharp/appmpower/appmpower-ado-pg.dockerfile

@@ -1,17 +0,0 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build
-RUN apt-get update
-RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
-
-WORKDIR /app
-COPY src .
-RUN dotnet publish -c Release -o out /p:Driver=ado
-
-# Construct the actual image that will run
-FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
-
-WORKDIR /app
-COPY --from=build /app/out ./
-
-EXPOSE 8080
-
-ENTRYPOINT ["./appMpower"]

+ 53 - 0
frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile

@@ -0,0 +1,53 @@
+FROM mcr.microsoft.com/dotnet/sdk:9.0.100 AS build
+RUN apt-get update
+RUN apt-get -yqq install clang zlib1g-dev
+RUN apt-get update
+
+WORKDIR /app
+COPY src .
+RUN dotnet publish -c Release -o out /p:Database=mysql
+
+# Construct the actual image that will run
+FROM mcr.microsoft.com/dotnet/aspnet:9.0.0 AS runtime
+
+RUN apt-get update
+# The following installs standard versions unixodbc and pgsqlodbc
+# unixodbc still needs to be installed even if compiled locally
+RUN apt-get install -y unixodbc-dev unixodbc wget curl
+RUN apt-get update
+
+WORKDIR /odbc
+
+RUN curl -L -o mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz https://downloads.mariadb.com/Connectors/odbc/connector-odbc-3.1.20/mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz
+RUN tar -xvzf mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz
+RUN cp mariadb-connector-odbc-3.1.20-debian-bookworm-amd64/lib/mariadb/libm* /usr/lib/
+RUN cp -r /odbc/mariadb-connector-odbc-3.1.20-debian-bookworm-amd64/lib/mariadb /usr/local/lib/mariadb
+RUN rm mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz
+#TODOLOCAL
+#RUN curl -L -o mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz https://downloads.mariadb.com/Connectors/odbc/connector-odbc-3.1.20/mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz
+#RUN tar -xvzf mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz
+#RUN cp mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64/lib/mariadb/libm* /usr/lib/
+#RUN cp -r /odbc/mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64/lib/mariadb /usr/local/lib/mariadb
+#RUN rm mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz
+
+ENV PATH=/usr/local/unixODBC/bin:$PATH
+
+WORKDIR /etc/
+COPY odbcinst.ini .
+
+# Full PGO
+ENV DOTNET_TieredPGO 1 
+ENV DOTNET_TC_QuickJitForLoops 1 
+ENV DOTNET_ReadyToRun 0
+
+ENV ASPNETCORE_URLS http://+:8080
+WORKDIR /app
+COPY --from=build /app/out ./
+
+RUN cp /usr/lib/libm* /app
+#RUN cp /usr/lib/aarch64-linux-gnu/libodbc* /app
+RUN cp /usr/lib/x86_64-linux-gnu/libodbc* /app
+
+EXPOSE 8080
+
+ENTRYPOINT ["./appMpower"]

+ 14 - 4
frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile

@@ -1,16 +1,16 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0.100 AS build
 RUN apt-get update
 RUN apt-get update
 RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 
 
 WORKDIR /app
 WORKDIR /app
 COPY src .
 COPY src .
-RUN dotnet publish -c Release -o out /p:Driver=odbc
+RUN dotnet publish -c Release -o out /p:Database=postgresql
 
 
 # Construct the actual image that will run
 # Construct the actual image that will run
-FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0.0 AS runtime
 
 
 RUN apt-get update
 RUN apt-get update
-RUN apt-get install -y unixodbc odbc-postgresql
+RUN apt-get install -y unixodbc-dev unixodbc odbc-postgresql
 # unixodbc still needs to be installed even if compiled locally
 # unixodbc still needs to be installed even if compiled locally
 
 
 ENV PATH=/usr/local/unixODBC/bin:$PATH
 ENV PATH=/usr/local/unixODBC/bin:$PATH
@@ -18,9 +18,19 @@ ENV PATH=/usr/local/unixODBC/bin:$PATH
 WORKDIR /etc/
 WORKDIR /etc/
 COPY odbcinst.ini .
 COPY odbcinst.ini .
 
 
+# Full PGO
+ENV DOTNET_TieredPGO 1 
+ENV DOTNET_TC_QuickJitForLoops 1 
+ENV DOTNET_ReadyToRun 0
+
+ENV ASPNETCORE_URLS http://+:8080
 WORKDIR /app
 WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./
 
 
+#RUN cp /usr/lib/aarch64-linux-gnu/libodbc* /app
+RUN cp /usr/lib/x86_64-linux-gnu/libodbc* /app
+
+
 EXPOSE 8080
 EXPOSE 8080
 
 
 ENTRYPOINT ["./appMpower"]
 ENTRYPOINT ["./appMpower"]

+ 8 - 2
frameworks/CSharp/appmpower/appmpower.dockerfile

@@ -1,14 +1,20 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0.100 AS build
 RUN apt-get update
 RUN apt-get update
 RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 
 
 WORKDIR /app
 WORKDIR /app
 COPY src .
 COPY src .
+#RUN dotnet publish appMpower/appMpower.csproj -c Release -o out
 RUN dotnet publish -c Release -o out
 RUN dotnet publish -c Release -o out
 
 
 # Construct the actual image that will run
 # Construct the actual image that will run
-FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0.0 AS runtime
+# Full PGO
+ENV DOTNET_TieredPGO 1 
+ENV DOTNET_TC_QuickJitForLoops 1 
+ENV DOTNET_ReadyToRun 0
 
 
+ENV ASPNETCORE_URLS http://+:8080
 WORKDIR /app
 WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./
 
 

+ 4 - 4
frameworks/CSharp/appmpower/benchmark_config.json

@@ -39,11 +39,11 @@
         "webserver": "Kestrel",
         "webserver": "Kestrel",
         "os": "Linux",
         "os": "Linux",
         "database_os": "Linux",
         "database_os": "Linux",
-        "display_name": "appMpower [aot-no-reflection,odbc]",
+        "display_name": "appMpower [aot-no-reflection,pg,odbc]",
         "notes": "",
         "notes": "",
         "versus": "aspnetcore-minimal"
         "versus": "aspnetcore-minimal"
       },
       },
-      "ado-pg": {
+      "odbc-my": {
         "db_url": "/db",
         "db_url": "/db",
         "query_url": "/queries?c=",
         "query_url": "/queries?c=",
         "update_url": "/updates?c=",
         "update_url": "/updates?c=",
@@ -52,7 +52,7 @@
         "port": 8080,
         "port": 8080,
         "approach": "Realistic",
         "approach": "Realistic",
         "classification": "Platform",
         "classification": "Platform",
-        "database": "Postgres",
+        "database": "MySQL",
         "framework": "appmpower",
         "framework": "appmpower",
         "language": "C#",
         "language": "C#",
         "orm": "Raw",
         "orm": "Raw",
@@ -61,7 +61,7 @@
         "webserver": "Kestrel",
         "webserver": "Kestrel",
         "os": "Linux",
         "os": "Linux",
         "database_os": "Linux",
         "database_os": "Linux",
-        "display_name": "appMpower [aot-no-reflection,ado]",
+        "display_name": "appMpower [aot-no-reflection,my,odbc]",
         "notes": "",
         "notes": "",
         "versus": "aspnetcore-minimal"
         "versus": "aspnetcore-minimal"
       }
       }

+ 2 - 2
frameworks/CSharp/appmpower/config.toml

@@ -30,7 +30,7 @@ platform = ".NET"
 webserver = "Kestrel"
 webserver = "Kestrel"
 versus = "aspnetcore-minimal"
 versus = "aspnetcore-minimal"
 
 
-[ado-pg]
+[odbc-my]
 urls.db = "/db"
 urls.db = "/db"
 urls.query = "/queries?c="
 urls.query = "/queries?c="
 urls.update = "/updates?c="
 urls.update = "/updates?c="
@@ -38,7 +38,7 @@ urls.fortune = "/fortunes"
 urls.cached_query = "/cached-worlds?c="
 urls.cached_query = "/cached-worlds?c="
 approach = "Realistic"
 approach = "Realistic"
 classification = "Micro"
 classification = "Micro"
-database = "Postgres"
+database = "MySQL"
 database_os = "Linux"
 database_os = "Linux"
 os = "Linux"
 os = "Linux"
 orm = "Raw"
 orm = "Raw"

+ 10 - 0
frameworks/CSharp/appmpower/odbcinst.ini

@@ -5,6 +5,7 @@ Pooling=0
 
 
 [ODBC Drivers]
 [ODBC Drivers]
 PostgreSQL = Installed
 PostgreSQL = Installed
+MariaDB = Installed
 
 
 ;
 ;
 ;  odbcinst.ini
 ;  odbcinst.ini
@@ -15,7 +16,16 @@ Description=ODBC for PostgreSQL
 ; in version 08.x. Note that the library can also be installed under an other
 ; in version 08.x. Note that the library can also be installed under an other
 ; path than /usr/local/lib/ following your installation.
 ; path than /usr/local/lib/ following your installation.
 ; This is the standard location used by apt-get install -y unixodbc
 ; This is the standard location used by apt-get install -y unixodbc
+;ON SERVER
 Driver = /usr/lib/x86_64-linux-gnu/odbc/psqlodbcw.so
 Driver = /usr/lib/x86_64-linux-gnu/odbc/psqlodbcw.so
+;TODOLOCAL: ON MAC
+;Driver =/usr/lib/aarch64-linux-gnu/odbc/psqlodbcw.so
+
 ;Driver =/usr/local/pgsqlodbc/lib/psqlodbcw.so
 ;Driver =/usr/local/pgsqlodbc/lib/psqlodbcw.so
 Threading = 0
 Threading = 0
 CPTimeout = 0
 CPTimeout = 0
+
+[MariaDB]
+Description=MariaDB ODBC for MySQL
+Driver = /usr/lib/libmaodbc.so
+Threading   = 0

+ 0 - 15
frameworks/CSharp/appmpower/src/CachedWorldSerializer.cs

@@ -1,15 +0,0 @@
-using System.Text.Json;
-
-namespace appMpower
-{
-   public class CachedWorldSerializer : Kestrel.IJsonSerializer<CachedWorld>
-   {
-      public void Serialize(Utf8JsonWriter utf8JsonWriter, CachedWorld world)
-      {
-         utf8JsonWriter.WriteStartObject();
-         utf8JsonWriter.WriteNumber("id", world.Id);
-         utf8JsonWriter.WriteNumber("randomNumber", world.RandomNumber);
-         utf8JsonWriter.WriteEndObject();
-      }
-   }
-}

+ 0 - 200
frameworks/CSharp/appmpower/src/Data/DbConnection.cs

@@ -1,200 +0,0 @@
-using System.Collections.Concurrent;
-using System.Data;
-using System.Threading.Tasks;
-
-namespace appMpower.Data
-{
-   public class DbConnection : IDbConnection
-   {
-      private string _connectionString;
-      internal InternalConnection _internalConnection;
-
-      public DbConnection()
-      {
-         _connectionString = DbProviderFactory.ConnectionString;
-      }
-
-      public DbConnection(string connectionString)
-      {
-         _connectionString = connectionString;
-      }
-
-      internal ConcurrentDictionary<string, DbCommand> DbCommands
-      {
-         get
-         {
-            return _internalConnection.DbCommands;
-         }
-         set
-         {
-            _internalConnection.DbCommands = value;
-         }
-      }
-
-      public short Number
-      {
-         get
-         {
-            return _internalConnection.Number;
-         }
-         set
-         {
-            _internalConnection.Number = value;
-         }
-      }
-
-      public IDbConnection Connection
-      {
-         get
-         {
-            return _internalConnection.DbConnection;
-         }
-         set
-         {
-            _internalConnection.DbConnection = value;
-         }
-      }
-
-      public string ConnectionString
-      {
-         get
-         {
-            return _internalConnection.DbConnection.ConnectionString;
-         }
-         set
-         {
-            _internalConnection.DbConnection.ConnectionString = value;
-         }
-      }
-
-      public int ConnectionTimeout
-      {
-         get
-         {
-            return _internalConnection.DbConnection.ConnectionTimeout;
-         }
-      }
-
-      public string Database
-      {
-         get
-         {
-            return _internalConnection.DbConnection.Database;
-         }
-      }
-
-      public ConnectionState State
-      {
-         get
-         {
-            if (_internalConnection is null) return ConnectionState.Closed;
-            return _internalConnection.DbConnection.State;
-         }
-      }
-
-      public IDbTransaction BeginTransaction()
-      {
-         return _internalConnection.DbConnection.BeginTransaction();
-      }
-
-      public IDbTransaction BeginTransaction(IsolationLevel il)
-      {
-         return _internalConnection.DbConnection.BeginTransaction(il);
-      }
-
-      public void ChangeDatabase(string databaseName)
-      {
-         _internalConnection.DbConnection.ChangeDatabase(databaseName);
-      }
-
-      public void Close()
-      {
-         _internalConnection.DbConnection.Close();
-      }
-
-      public async Task CloseAsync()
-      {
-         await (_internalConnection.DbConnection as System.Data.Common.DbConnection).CloseAsync();
-      }
-
-      public IDbCommand CreateCommand()
-      {
-         return _internalConnection.DbConnection.CreateCommand();
-      }
-
-      public void Open()
-      {
-         if (_internalConnection.DbConnection.State == ConnectionState.Closed)
-         {
-            _internalConnection.DbConnection.Open();
-         }
-      }
-
-      public void Dispose()
-      {
-#if ADO
-         _internalConnection.DbConnection.Dispose();
-         _internalConnection.Dispose();
-#else
-         DbConnections.Release(_internalConnection);
-#endif
-      }
-
-      public async Task OpenAsync()
-      {
-#if ADO && POSTGRESQL
-         _internalConnection = new(); 
-         _internalConnection.DbConnection = new Npgsql.NpgsqlConnection(_connectionString);
-#else
-         if (_internalConnection is null)
-         {
-            _internalConnection = await DbConnections.GetConnection(_connectionString);
-         }
-#endif
-
-         if (_internalConnection.DbConnection.State == ConnectionState.Closed)
-         {
-            await (_internalConnection.DbConnection as System.Data.Common.DbConnection).OpenAsync();
-         }
-      }
-
-      internal DbCommand GetCommand(string commandText, CommandType commandType, DbCommand dbCommand)
-      {
-#if ADO
-         dbCommand.Command = _internalConnection.DbConnection.CreateCommand();
-         dbCommand.Command.CommandText = commandText;
-         dbCommand.Command.CommandType = commandType;
-         dbCommand.DbConnection = this;
-#else
-         DbCommand internalCommand;
-
-         if (_internalConnection.DbCommands.TryRemove(commandText, out internalCommand))
-         {
-            dbCommand.Command = internalCommand.Command;
-            dbCommand.DbConnection = internalCommand.DbConnection;
-         }
-         else
-         {
-            dbCommand.Command = _internalConnection.DbConnection.CreateCommand();
-            dbCommand.Command.CommandText = commandText;
-            dbCommand.Command.CommandType = commandType;
-            dbCommand.DbConnection = this;
-
-            //For non odbc drivers like Npgsql which do not support Prepare
-            dbCommand.Command.Prepare();
-
-            //Console.WriteLine("prepare pool connection: " + this._internalConnection.Number + " for command " + _internalConnection.DbCommands.Count);
-         }
-#endif
-
-         return dbCommand;
-      }
-
-      public void ReleaseCommand(DbCommand dbCommand)
-      {
-#if !ADO
-         _internalConnection.DbCommands.TryAdd(dbCommand.CommandText, dbCommand);
-#endif
-      }
-   }
-}

+ 0 - 67
frameworks/CSharp/appmpower/src/Data/DbConnections.cs

@@ -1,67 +0,0 @@
-using System.Collections.Concurrent;
-using System.Threading.Tasks;
-
-namespace appMpower.Data
-{
-   public static class DbConnections
-   {
-      private static bool _connectionsCreated = false;
-      private static short _createdConnections = 0;
-      private static short _maxConnections = 500;
-
-      private static ConcurrentStack<InternalConnection> _stack = new();
-      private static ConcurrentQueue<TaskCompletionSource<InternalConnection>> _waitingQueue = new();
-
-      public static async Task<InternalConnection> GetConnection(string connectionString)
-      {
-         InternalConnection internalConnection = null;
-
-         if (_connectionsCreated)
-         {
-            if (!_stack.TryPop(out internalConnection))
-            {
-               internalConnection = await GetDbConnectionAsync();
-            }
-
-            return internalConnection;
-         }
-         else
-         {
-            internalConnection = new InternalConnection();
-            internalConnection.DbConnection = new System.Data.Odbc.OdbcConnection(connectionString);
-
-            _createdConnections++;
-
-            if (_createdConnections == _maxConnections) _connectionsCreated = true;
-
-            internalConnection.Number = _createdConnections;
-            internalConnection.DbCommands = new ConcurrentDictionary<string, DbCommand>();
-            //Console.WriteLine("opened connection number: " + dbConnection.Number);
-
-            return internalConnection;
-         }
-      }
-
-      public static Task<InternalConnection> GetDbConnectionAsync()
-      {
-         var taskCompletionSource = new TaskCompletionSource<InternalConnection>(TaskCreationOptions.RunContinuationsAsynchronously);
-
-         _waitingQueue.Enqueue(taskCompletionSource);
-         return taskCompletionSource.Task;
-      }
-
-      public static void Release(InternalConnection internalConnection)
-      {
-         TaskCompletionSource<InternalConnection> taskCompletionSource;
-
-         if (_waitingQueue.TryDequeue(out taskCompletionSource))
-         {
-            taskCompletionSource.SetResult(internalConnection);
-         }
-         else
-         {
-            _stack.Push(internalConnection);
-         }
-      }
-   }
-}

+ 0 - 17
frameworks/CSharp/appmpower/src/Data/DbProviderFactory.cs

@@ -1,17 +0,0 @@
-using System.Data;
-
-namespace appMpower.Data
-{
-   public static class DbProviderFactory
-   {
-#if MYSQL
-      public const string ConnectionString = "Driver={MariaDB};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;Pooling=false;OPTIONS=67108864;FLAG_FORWARD_CURSOR=1"; 
-#elif ADO
-      public const string ConnectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=0;Maximum Pool Size=18;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; 
-      //public const string ConnectionString = "Server=localhost;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=18;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; 
-#else
-      public const string ConnectionString = "Driver={PostgreSQL};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false";
-      //public const string ConnectionString = "Driver={PostgreSQL};Server=localhost;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false";
-#endif
-   }
-}

+ 0 - 16
frameworks/CSharp/appmpower/src/Data/InternalConnection.cs

@@ -1,16 +0,0 @@
-using System.Collections.Concurrent;
-using System.Data;
-
-namespace appMpower.Data
-{
-   public class InternalConnection : System.IDisposable
-   {
-      public short Number { get; set; }
-      public IDbConnection DbConnection { get; set; }
-      public ConcurrentDictionary<string, DbCommand> DbCommands { get; set; }
-
-      public void Dispose()
-      {
-      }
-   }
-}

+ 0 - 117
frameworks/CSharp/appmpower/src/HttpApplication.cs

@@ -1,117 +0,0 @@
-using System;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting.Server;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Http.Features;
-using appMpower.Kestrel;
-
-namespace appMpower
-{
-   public class HttpApplication : IHttpApplication<IFeatureCollection>
-   {
-      public static readonly byte[] _plainText = Encoding.UTF8.GetBytes("Hello, World!");
-      private readonly static JsonMessageSerializer _jsonMessageSerializer = new JsonMessageSerializer();
-      private readonly static WorldSerializer _worldSerializer = new WorldSerializer();
-      private readonly static CachedWorldSerializer _cachedWorldSerializer = new CachedWorldSerializer();
-
-      public IFeatureCollection CreateContext(IFeatureCollection featureCollection)
-      {
-         return featureCollection;
-      }
-
-      public async Task ProcessRequestAsync(IFeatureCollection featureCollection)
-      {
-         var request = featureCollection as IHttpRequestFeature;
-         var httpResponse = featureCollection as IHttpResponseFeature;
-         var httpResponseBody = featureCollection as IHttpResponseBodyFeature;
-
-         PathString pathString = request.Path;
-
-         if (pathString.HasValue)
-         {
-            int pathStringLength = pathString.Value.Length;
-            string pathStringStart = pathString.Value.Substring(1, 1);
-
-            if (pathStringLength == 10 && pathStringStart == "p")
-            {
-               //await PlainText.RenderAsync(httpResponse.Headers, httpResponseBody.Writer, _plainText);
-               PlainText.Render(httpResponse.Headers, httpResponseBody, _plainText);
-               return;
-            }
-            else if (pathStringLength == 5 && pathStringStart == "j")
-            {
-               Json.RenderOne(httpResponse.Headers, httpResponseBody.Writer, new JsonMessage { message = "Hello, World!" }, _jsonMessageSerializer);
-               return;
-            }
-            else if (pathStringLength == 3 && pathStringStart == "d")
-            {
-               Json.RenderOne(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadSingleQueryRow(), _worldSerializer);
-               return;
-            }
-            else if (pathStringLength == 8 && pathStringStart == "q")
-            {
-               int count = 1;
-
-               if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1)
-               {
-                  count = 1;
-               }
-               else if (count > 500)
-               {
-                  count = 500;
-               }
-
-#if ADO
-               Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadMultipleQueriesRows(count), _worldSerializer);
-#else
-               Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.ReadMultipleRows(count), _worldSerializer);
-#endif
-
-               return;
-            }
-            else if (pathStringLength == 9 && pathStringStart == "f")
-            {
-               await FortunesView.Render(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadFortunesRows());
-               return;
-            }
-            else if (pathStringLength == 8 && pathStringStart == "u")
-            {
-               int count = 1;
-
-               if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1)
-               {
-                  count = 1;
-               }
-               else if (count > 500)
-               {
-                  count = 500;
-               }
-
-               Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadMultipleUpdatesRows(count), _worldSerializer);
-               return;
-            }
-            else if (pathStringLength == 14 && pathStringStart == "c")
-            {
-               int count = 1;
-
-               if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1)
-               {
-                  count = 1;
-               }
-               else if (count > 500)
-               {
-                  count = 500;
-               }
-
-               Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadCachedQueries(count), _cachedWorldSerializer);
-               return;
-            }
-         }
-      }
-
-      public void DisposeContext(IFeatureCollection featureCollection, Exception exception)
-      {
-      }
-   }
-}

+ 0 - 7
frameworks/CSharp/appmpower/src/JsonMessage.cs

@@ -1,7 +0,0 @@
-namespace appMpower
-{
-   public struct JsonMessage
-   {
-      public string message { get; set; }
-   }
-}

+ 0 - 58
frameworks/CSharp/appmpower/src/Kestrel/Json.cs

@@ -1,58 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO.Pipelines;
-using System.Text.Json;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Primitives;
-
-namespace appMpower.Kestrel
-{
-   public static class Json
-   {
-      private readonly static KeyValuePair<string, StringValues> _headerServer =
-         new KeyValuePair<string, StringValues>("Server", "k");
-      private readonly static KeyValuePair<string, StringValues> _headerContentType =
-         new KeyValuePair<string, StringValues>("Content-Type", "application/json");
-
-      [ThreadStatic]
-      private static Utf8JsonWriter _utf8JsonWriter;
-
-      public static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions
-      {
-         SkipValidation = true
-      };
-
-      public static void RenderOne<T>(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, T t, IJsonSerializer<T> jsonSerializer)
-      {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-
-         Utf8JsonWriter utf8JsonWriter = _utf8JsonWriter ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true });
-         utf8JsonWriter.Reset(pipeWriter);
-
-         jsonSerializer.Serialize(utf8JsonWriter, t);
-         utf8JsonWriter.Flush();
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", utf8JsonWriter.BytesCommitted.ToString()));
-      }
-
-      public static void RenderMany<T>(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, T[] tArray, IJsonSerializer<T> jsonSerializer)
-      {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-
-         Utf8JsonWriter utf8JsonWriter = _utf8JsonWriter ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true });
-         utf8JsonWriter.Reset(pipeWriter);
-
-         utf8JsonWriter.WriteStartArray();
-
-         foreach (var t in tArray)
-         {
-            jsonSerializer.Serialize(utf8JsonWriter, t);
-         }
-
-         utf8JsonWriter.WriteEndArray();
-         utf8JsonWriter.Flush();
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", utf8JsonWriter.BytesCommitted.ToString()));
-      }
-   }
-}

+ 0 - 38
frameworks/CSharp/appmpower/src/Kestrel/PlainText.cs

@@ -1,38 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-using System.IO.Pipelines;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Primitives;
-using Microsoft.AspNetCore.Http.Features;
-
-namespace appMpower.Kestrel
-{
-   public static class PlainText
-   {
-      private readonly static KeyValuePair<string, StringValues> _headerServer =
-         new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
-      private readonly static KeyValuePair<string, StringValues> _headerContentType =
-         new KeyValuePair<string, StringValues>("Content-Type", new StringValues("text/plain"));
-
-      public static async Task RenderAsync(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, ReadOnlyMemory<byte> utf8String)
-      {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", utf8String.Length.ToString()));
-
-         await pipeWriter.WriteAsync(utf8String);
-         pipeWriter.Complete();
-      }
-
-      public static void Render(IHeaderDictionary headerDictionary, IHttpResponseBodyFeature httpResponseBodyFeature, byte[] utf8String)
-      {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-         int length = utf8String.Length;
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", length.ToString()));
-
-         httpResponseBodyFeature.Stream.Write(utf8String, 0, length);
-      }
-   }
-}

+ 0 - 25
frameworks/CSharp/appmpower/src/Kestrel/ServiceProvider.cs

@@ -1,25 +0,0 @@
-using System;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-
-namespace appMpower.Kestrel
-{
-   public class ServiceProvider : ISupportRequiredService, IServiceProvider
-   {
-      public object GetRequiredService(Type serviceType)
-      {
-         return GetService(serviceType);
-      }
-
-      public object GetService(Type serviceType)
-      {
-         if (serviceType == typeof(ILoggerFactory))
-         {
-            return NullLoggerFactory.Instance;
-         }
-
-         return null;
-      }
-   }
-}

+ 0 - 257
frameworks/CSharp/appmpower/src/Memory/CacheEntry.cs

@@ -1,257 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Primitives;
-using Microsoft.Extensions.Caching.Memory;
-
-namespace appMpower.Memory
-{
-   internal sealed partial class CacheEntry : ICacheEntry
-   {
-      private static readonly Action<object> ExpirationCallback = ExpirationTokensExpired;
-
-      private readonly MemoryCache _cache;
-
-      private CacheEntryTokens _tokens; // might be null if user is not using the tokens or callbacks
-      private TimeSpan? _absoluteExpirationRelativeToNow;
-      private TimeSpan? _slidingExpiration;
-      private long? _size;
-      private CacheEntry _previous; // this field is not null only before the entry is added to the cache and tracking is enabled
-      private object _value;
-      private CacheEntryState _state;
-
-      internal CacheEntry(object key, MemoryCache memoryCache)
-      {
-         Key = key ?? throw new ArgumentNullException(nameof(key));
-         _cache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
-         _previous = memoryCache.TrackLinkedCacheEntries ? CacheEntryHelper.EnterScope(this) : null;
-         _state = new CacheEntryState(CacheItemPriority.Normal);
-      }
-
-      /// <summary>
-      /// Gets or sets an absolute expiration date for the cache entry.
-      /// </summary>
-      public DateTimeOffset? AbsoluteExpiration { get; set; }
-
-      /// <summary>
-      /// Gets or sets an absolute expiration time, relative to now.
-      /// </summary>
-      public TimeSpan? AbsoluteExpirationRelativeToNow
-      {
-         get => _absoluteExpirationRelativeToNow;
-         set
-         {
-            // this method does not set AbsoluteExpiration as it would require calling Clock.UtcNow twice:
-            // once here and once in MemoryCache.SetEntry
-
-            if (value <= TimeSpan.Zero)
-            {
-               throw new ArgumentOutOfRangeException(
-                   nameof(AbsoluteExpirationRelativeToNow),
-                   value,
-                   "The relative expiration value must be positive.");
-            }
-
-            _absoluteExpirationRelativeToNow = value;
-         }
-      }
-
-      /// <summary>
-      /// Gets or sets how long a cache entry can be inactive (e.g. not accessed) before it will be removed.
-      /// This will not extend the entry lifetime beyond the absolute expiration (if set).
-      /// </summary>
-      public TimeSpan? SlidingExpiration
-      {
-         get => _slidingExpiration;
-         set
-         {
-            if (value <= TimeSpan.Zero)
-            {
-               throw new ArgumentOutOfRangeException(
-                   nameof(SlidingExpiration),
-                   value,
-                   "The sliding expiration value must be positive.");
-            }
-
-            _slidingExpiration = value;
-         }
-      }
-
-      /// <summary>
-      /// Gets the <see cref="IChangeToken"/> instances which cause the cache entry to expire.
-      /// </summary>
-      public IList<IChangeToken> ExpirationTokens => GetOrCreateTokens().ExpirationTokens;
-
-      /// <summary>
-      /// Gets or sets the callbacks will be fired after the cache entry is evicted from the cache.
-      /// </summary>
-      public IList<PostEvictionCallbackRegistration> PostEvictionCallbacks => GetOrCreateTokens().PostEvictionCallbacks;
-
-      /// <summary>
-      /// Gets or sets the priority for keeping the cache entry in the cache during a
-      /// memory pressure triggered cleanup. The default is <see cref="CacheItemPriority.Normal"/>.
-      /// </summary>
-      public CacheItemPriority Priority { get => _state.Priority; set => _state.Priority = value; }
-
-      /// <summary>
-      /// Gets or sets the size of the cache entry value.
-      /// </summary>
-      public long? Size
-      {
-         get => _size;
-         set
-         {
-            if (value < 0)
-            {
-               throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be non-negative.");
-            }
-
-            _size = value;
-         }
-      }
-
-      public object Key { get; private set; }
-
-      public object Value
-      {
-         get => _value;
-         set
-         {
-            _value = value;
-            _state.IsValueSet = true;
-         }
-      }
-
-      internal DateTimeOffset LastAccessed { get; set; }
-
-      internal EvictionReason EvictionReason { get => _state.EvictionReason; private set => _state.EvictionReason = value; }
-
-      public void Dispose()
-      {
-         if (!_state.IsDisposed)
-         {
-            _state.IsDisposed = true;
-
-            if (_cache.TrackLinkedCacheEntries)
-            {
-               CacheEntryHelper.ExitScope(this, _previous);
-            }
-
-            // Don't commit or propagate options if the CacheEntry Value was never set.
-            // We assume an exception occurred causing the caller to not set the Value successfully,
-            // so don't use this entry.
-            if (_state.IsValueSet)
-            {
-               _cache.SetEntry(this);
-
-               if (_previous != null && CanPropagateOptions())
-               {
-                  PropagateOptions(_previous);
-               }
-            }
-
-            _previous = null; // we don't want to root unnecessary objects
-         }
-      }
-
-      [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling
-      internal bool CheckExpired(in DateTimeOffset now)
-          => _state.IsExpired
-              || CheckForExpiredTime(now)
-              || (_tokens != null && _tokens.CheckForExpiredTokens(this));
-
-      internal void SetExpired(EvictionReason reason)
-      {
-         if (EvictionReason == EvictionReason.None)
-         {
-            EvictionReason = reason;
-         }
-         _state.IsExpired = true;
-         _tokens?.DetachTokens();
-      }
-
-      [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling
-      private bool CheckForExpiredTime(in DateTimeOffset now)
-      {
-         if (!AbsoluteExpiration.HasValue && !_slidingExpiration.HasValue)
-         {
-            return false;
-         }
-
-         return FullCheck(now);
-
-         bool FullCheck(in DateTimeOffset offset)
-         {
-            if (AbsoluteExpiration.HasValue && AbsoluteExpiration.Value <= offset)
-            {
-               SetExpired(EvictionReason.Expired);
-               return true;
-            }
-
-            if (_slidingExpiration.HasValue
-                && (offset - LastAccessed) >= _slidingExpiration)
-            {
-               SetExpired(EvictionReason.Expired);
-               return true;
-            }
-
-            return false;
-         }
-      }
-
-      internal void AttachTokens() => _tokens?.AttachTokens(this);
-
-      private static void ExpirationTokensExpired(object obj)
-      {
-         // start a new thread to avoid issues with callbacks called from RegisterChangeCallback
-         Task.Factory.StartNew(state =>
-         {
-            var entry = (CacheEntry)state;
-            entry.SetExpired(EvictionReason.TokenExpired);
-            entry._cache.EntryExpired(entry);
-         }, obj, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
-      }
-
-      internal void InvokeEvictionCallbacks() => _tokens?.InvokeEvictionCallbacks(this);
-
-      // this simple check very often allows us to avoid expensive call to PropagateOptions(CacheEntryHelper.Current)
-      [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling
-      internal bool CanPropagateOptions() => (_tokens != null && _tokens.CanPropagateTokens()) || AbsoluteExpiration.HasValue;
-
-      internal void PropagateOptions(CacheEntry parent)
-      {
-         if (parent == null)
-         {
-            return;
-         }
-
-         // Copy expiration tokens and AbsoluteExpiration to the cache entries hierarchy.
-         // We do this regardless of it gets cached because the tokens are associated with the value we'll return.
-         _tokens?.PropagateTokens(parent);
-
-         if (AbsoluteExpiration.HasValue)
-         {
-            if (!parent.AbsoluteExpiration.HasValue || AbsoluteExpiration < parent.AbsoluteExpiration)
-            {
-               parent.AbsoluteExpiration = AbsoluteExpiration;
-            }
-         }
-      }
-
-      private CacheEntryTokens GetOrCreateTokens()
-      {
-         if (_tokens != null)
-         {
-            return _tokens;
-         }
-
-         CacheEntryTokens result = new CacheEntryTokens();
-         return Interlocked.CompareExchange(ref _tokens, result, null) ?? result;
-      }
-   }
-}

+ 0 - 32
frameworks/CSharp/appmpower/src/Memory/CacheEntryHelper.cs

@@ -1,32 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.Threading;
-
-namespace appMpower.Memory
-{
-   internal static class CacheEntryHelper
-   {
-      private static readonly AsyncLocal<CacheEntry> _current = new AsyncLocal<CacheEntry>();
-
-      internal static CacheEntry Current
-      {
-         get => _current.Value;
-         private set => _current.Value = value;
-      }
-
-      internal static CacheEntry EnterScope(CacheEntry current)
-      {
-         CacheEntry previous = Current;
-         Current = current;
-         return previous;
-      }
-
-      internal static void ExitScope(CacheEntry current, CacheEntry previous)
-      {
-         Debug.Assert(Current == current, "Entries disposed in invalid order");
-         Current = previous;
-      }
-   }
-}

+ 0 - 62
frameworks/CSharp/appmpower/src/Memory/CacheEntryState.cs

@@ -1,62 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Microsoft.Extensions.Caching.Memory;
-
-namespace appMpower.Memory
-{
-   internal sealed partial class CacheEntry
-   {
-      // this type exists just to reduce CacheEntry size by replacing many enum & boolean fields with one of a size of Int32
-      private struct CacheEntryState
-      {
-         private byte _flags;
-         private byte _evictionReason;
-         private byte _priority;
-
-         internal CacheEntryState(CacheItemPriority priority) : this() => _priority = (byte)priority;
-
-         internal bool IsDisposed
-         {
-            get => ((Flags)_flags & Flags.IsDisposed) != 0;
-            set => SetFlag(Flags.IsDisposed, value);
-         }
-
-         internal bool IsExpired
-         {
-            get => ((Flags)_flags & Flags.IsExpired) != 0;
-            set => SetFlag(Flags.IsExpired, value);
-         }
-
-         internal bool IsValueSet
-         {
-            get => ((Flags)_flags & Flags.IsValueSet) != 0;
-            set => SetFlag(Flags.IsValueSet, value);
-         }
-
-         internal EvictionReason EvictionReason
-         {
-            get => (EvictionReason)_evictionReason;
-            set => _evictionReason = (byte)value;
-         }
-
-         internal CacheItemPriority Priority
-         {
-            get => (CacheItemPriority)_priority;
-            set => _priority = (byte)value;
-         }
-
-         private void SetFlag(Flags option, bool value) => _flags = (byte)(value ? (_flags | (byte)option) : (_flags & ~(byte)option));
-
-         [Flags]
-         private enum Flags : byte
-         {
-            Default = 0,
-            IsValueSet = 1 << 0,
-            IsExpired = 1 << 1,
-            IsDisposed = 1 << 2,
-         }
-      }
-   }
-}

+ 0 - 140
frameworks/CSharp/appmpower/src/Memory/CacheEntryTokens.cs

@@ -1,140 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Primitives;
-using Microsoft.Extensions.Caching.Memory;
-
-namespace appMpower.Memory
-{
-   internal sealed partial class CacheEntry
-   {
-      // this type exists just to reduce average CacheEntry size
-      // which typically is not using expiration tokens or callbacks
-      private sealed class CacheEntryTokens
-      {
-         private List<IChangeToken> _expirationTokens;
-         private List<IDisposable> _expirationTokenRegistrations;
-         private List<PostEvictionCallbackRegistration> _postEvictionCallbacks; // this is not really related to tokens, but was moved here to shrink typical CacheEntry size
-
-         internal List<IChangeToken> ExpirationTokens => _expirationTokens ??= new List<IChangeToken>();
-         internal List<PostEvictionCallbackRegistration> PostEvictionCallbacks => _postEvictionCallbacks ??= new List<PostEvictionCallbackRegistration>();
-
-         internal void AttachTokens(CacheEntry cacheEntry)
-         {
-            if (_expirationTokens != null)
-            {
-               lock (this)
-               {
-                  for (int i = 0; i < _expirationTokens.Count; i++)
-                  {
-                     IChangeToken expirationToken = _expirationTokens[i];
-                     if (expirationToken.ActiveChangeCallbacks)
-                     {
-                        _expirationTokenRegistrations ??= new List<IDisposable>(1);
-                        IDisposable registration = expirationToken.RegisterChangeCallback(ExpirationCallback, cacheEntry);
-                        _expirationTokenRegistrations.Add(registration);
-                     }
-                  }
-               }
-            }
-         }
-
-         internal bool CheckForExpiredTokens(CacheEntry cacheEntry)
-         {
-            if (_expirationTokens != null)
-            {
-               for (int i = 0; i < _expirationTokens.Count; i++)
-               {
-                  IChangeToken expiredToken = _expirationTokens[i];
-                  if (expiredToken.HasChanged)
-                  {
-                     cacheEntry.SetExpired(EvictionReason.TokenExpired);
-                     return true;
-                  }
-               }
-            }
-            return false;
-         }
-
-         internal bool CanPropagateTokens() => _expirationTokens != null;
-
-         internal void PropagateTokens(CacheEntry parentEntry)
-         {
-            if (_expirationTokens != null)
-            {
-               lock (this)
-               {
-                  lock (parentEntry.GetOrCreateTokens())
-                  {
-                     foreach (IChangeToken expirationToken in _expirationTokens)
-                     {
-                        parentEntry.AddExpirationToken(expirationToken);
-                     }
-                  }
-               }
-            }
-         }
-
-         internal void DetachTokens()
-         {
-            // _expirationTokenRegistrations is not checked for null, because AttachTokens might initialize it under lock
-            // instead we are checking for _expirationTokens, because if they are not null, then _expirationTokenRegistrations might also be not null
-            if (_expirationTokens != null)
-            {
-               lock (this)
-               {
-                  List<IDisposable> registrations = _expirationTokenRegistrations;
-                  if (registrations != null)
-                  {
-                     _expirationTokenRegistrations = null;
-                     for (int i = 0; i < registrations.Count; i++)
-                     {
-                        IDisposable registration = registrations[i];
-                        registration.Dispose();
-                     }
-                  }
-               }
-            }
-         }
-
-         internal void InvokeEvictionCallbacks(CacheEntry cacheEntry)
-         {
-            if (_postEvictionCallbacks != null)
-            {
-               Task.Factory.StartNew(state => InvokeCallbacks((CacheEntry)state), cacheEntry,
-                   CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
-            }
-         }
-
-         private static void InvokeCallbacks(CacheEntry entry)
-         {
-            List<PostEvictionCallbackRegistration> callbackRegistrations = Interlocked.Exchange(ref entry._tokens._postEvictionCallbacks, null);
-
-            if (callbackRegistrations == null)
-            {
-               return;
-            }
-
-            for (int i = 0; i < callbackRegistrations.Count; i++)
-            {
-               PostEvictionCallbackRegistration registration = callbackRegistrations[i];
-
-               try
-               {
-                  registration.EvictionCallback?.Invoke(entry.Key, entry.Value, entry.EvictionReason, registration.State);
-               }
-               catch (Exception e)
-               {
-                  // This will be invoked on a background thread, don't let it throw.
-                  entry._cache._logger.LogError(e, "EvictionCallback invoked failed");
-               }
-            }
-         }
-      }
-   }
-}

+ 0 - 520
frameworks/CSharp/appmpower/src/Memory/MemoryCache.cs

@@ -1,520 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Internal;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
-using Microsoft.Extensions.Caching.Memory;
-
-namespace appMpower.Memory
-{
-   /// <summary>
-   /// An implementation of <see cref="IMemoryCache"/> using a dictionary to
-   /// store its entries.
-   /// </summary>
-   public class MemoryCache : IMemoryCache
-   {
-      internal readonly ILogger _logger;
-
-      private readonly MemoryCacheOptions _options;
-      private readonly ConcurrentDictionary<object, CacheEntry> _entries;
-
-      private long _cacheSize;
-      private bool _disposed;
-      private DateTimeOffset _lastExpirationScan;
-
-      /// <summary>
-      /// Creates a new <see cref="MemoryCache"/> instance.
-      /// </summary>
-      /// <param name="optionsAccessor">The options of the cache.</param>
-      public MemoryCache(IOptions<MemoryCacheOptions> optionsAccessor)
-          : this(optionsAccessor, NullLoggerFactory.Instance) { }
-
-      /// <summary>
-      /// Creates a new <see cref="MemoryCache"/> instance.
-      /// </summary>
-      /// <param name="optionsAccessor">The options of the cache.</param>
-      /// <param name="loggerFactory">The factory used to create loggers.</param>
-      public MemoryCache(IOptions<MemoryCacheOptions> optionsAccessor, ILoggerFactory loggerFactory)
-      {
-         if (optionsAccessor == null)
-         {
-            throw new ArgumentNullException(nameof(optionsAccessor));
-         }
-
-         if (loggerFactory == null)
-         {
-            throw new ArgumentNullException(nameof(loggerFactory));
-         }
-
-         _options = optionsAccessor.Value;
-         //_logger = loggerFactory.CreateLogger<MemoryCache>();
-         _logger = loggerFactory.CreateLogger("MemoryCache");
-
-         _entries = new ConcurrentDictionary<object, CacheEntry>();
-
-         if (_options.Clock == null)
-         {
-            _options.Clock = new SystemClock();
-         }
-
-         _lastExpirationScan = _options.Clock.UtcNow;
-         TrackLinkedCacheEntries = _options.TrackLinkedCacheEntries; // we store the setting now so it's consistent for entire MemoryCache lifetime
-      }
-
-      /// <summary>
-      /// Cleans up the background collection events.
-      /// </summary>
-      ~MemoryCache() => Dispose(false);
-
-      /// <summary>
-      /// Gets the count of the current entries for diagnostic purposes.
-      /// </summary>
-      public int Count => _entries.Count;
-
-      // internal for testing
-      internal long Size { get => Interlocked.Read(ref _cacheSize); }
-
-      internal bool TrackLinkedCacheEntries { get; }
-
-      private ICollection<KeyValuePair<object, CacheEntry>> EntriesCollection => _entries;
-
-      /// <inheritdoc />
-      public ICacheEntry CreateEntry(object key)
-      {
-         CheckDisposed();
-         ValidateCacheKey(key);
-
-         return new CacheEntry(key, this);
-      }
-
-      internal void SetEntry(CacheEntry entry)
-      {
-         if (_disposed)
-         {
-            // No-op instead of throwing since this is called during CacheEntry.Dispose
-            return;
-         }
-
-         if (_options.SizeLimit.HasValue && !entry.Size.HasValue)
-         {
-            //throw new InvalidOperationException(SR.Format(SR.CacheEntryHasEmptySize, nameof(entry.Size), nameof(_options.SizeLimit)));
-            throw new InvalidOperationException();
-         }
-
-         DateTimeOffset utcNow = _options.Clock.UtcNow;
-
-         DateTimeOffset? absoluteExpiration = null;
-         if (entry.AbsoluteExpirationRelativeToNow.HasValue)
-         {
-            absoluteExpiration = utcNow + entry.AbsoluteExpirationRelativeToNow;
-         }
-         else if (entry.AbsoluteExpiration.HasValue)
-         {
-            absoluteExpiration = entry.AbsoluteExpiration;
-         }
-
-         // Applying the option's absolute expiration only if it's not already smaller.
-         // This can be the case if a dependent cache entry has a smaller value, and
-         // it was set by cascading it to its parent.
-         if (absoluteExpiration.HasValue)
-         {
-            if (!entry.AbsoluteExpiration.HasValue || absoluteExpiration.Value < entry.AbsoluteExpiration.Value)
-            {
-               entry.AbsoluteExpiration = absoluteExpiration;
-            }
-         }
-
-         // Initialize the last access timestamp at the time the entry is added
-         entry.LastAccessed = utcNow;
-
-         if (_entries.TryGetValue(entry.Key, out CacheEntry priorEntry))
-         {
-            priorEntry.SetExpired(EvictionReason.Replaced);
-         }
-
-         bool exceedsCapacity = UpdateCacheSizeExceedsCapacity(entry);
-
-         if (!entry.CheckExpired(utcNow) && !exceedsCapacity)
-         {
-            bool entryAdded = false;
-
-            if (priorEntry == null)
-            {
-               // Try to add the new entry if no previous entries exist.
-               entryAdded = _entries.TryAdd(entry.Key, entry);
-            }
-            else
-            {
-               // Try to update with the new entry if a previous entries exist.
-               entryAdded = _entries.TryUpdate(entry.Key, entry, priorEntry);
-
-               if (entryAdded)
-               {
-                  if (_options.SizeLimit.HasValue)
-                  {
-                     // The prior entry was removed, decrease the by the prior entry's size
-                     Interlocked.Add(ref _cacheSize, -priorEntry.Size.Value);
-                  }
-               }
-               else
-               {
-                  // The update will fail if the previous entry was removed after retrival.
-                  // Adding the new entry will succeed only if no entry has been added since.
-                  // This guarantees removing an old entry does not prevent adding a new entry.
-                  entryAdded = _entries.TryAdd(entry.Key, entry);
-               }
-            }
-
-            if (entryAdded)
-            {
-               entry.AttachTokens();
-            }
-            else
-            {
-               if (_options.SizeLimit.HasValue)
-               {
-                  // Entry could not be added, reset cache size
-                  Interlocked.Add(ref _cacheSize, -entry.Size.Value);
-               }
-               entry.SetExpired(EvictionReason.Replaced);
-               entry.InvokeEvictionCallbacks();
-            }
-
-            if (priorEntry != null)
-            {
-               priorEntry.InvokeEvictionCallbacks();
-            }
-         }
-         else
-         {
-            if (exceedsCapacity)
-            {
-               // The entry was not added due to overcapacity
-               entry.SetExpired(EvictionReason.Capacity);
-
-               TriggerOvercapacityCompaction();
-            }
-            else
-            {
-               if (_options.SizeLimit.HasValue)
-               {
-                  // Entry could not be added due to being expired, reset cache size
-                  Interlocked.Add(ref _cacheSize, -entry.Size.Value);
-               }
-            }
-
-            entry.InvokeEvictionCallbacks();
-            if (priorEntry != null)
-            {
-               RemoveEntry(priorEntry);
-            }
-         }
-
-         StartScanForExpiredItemsIfNeeded(utcNow);
-      }
-
-      /// <inheritdoc />
-      public bool TryGetValue(object key, out object result)
-      {
-         ValidateCacheKey(key);
-         CheckDisposed();
-
-         DateTimeOffset utcNow = _options.Clock.UtcNow;
-
-         if (_entries.TryGetValue(key, out CacheEntry entry))
-         {
-            // Check if expired due to expiration tokens, timers, etc. and if so, remove it.
-            // Allow a stale Replaced value to be returned due to concurrent calls to SetExpired during SetEntry.
-            if (!entry.CheckExpired(utcNow) || entry.EvictionReason == EvictionReason.Replaced)
-            {
-               entry.LastAccessed = utcNow;
-               result = entry.Value;
-
-               if (TrackLinkedCacheEntries && entry.CanPropagateOptions())
-               {
-                  // When this entry is retrieved in the scope of creating another entry,
-                  // that entry needs a copy of these expiration tokens.
-                  entry.PropagateOptions(CacheEntryHelper.Current);
-               }
-
-               StartScanForExpiredItemsIfNeeded(utcNow);
-
-               return true;
-            }
-            else
-            {
-               // TODO: For efficiency queue this up for batch removal
-               RemoveEntry(entry);
-            }
-         }
-
-         StartScanForExpiredItemsIfNeeded(utcNow);
-
-         result = null;
-         return false;
-      }
-
-      /// <inheritdoc />
-      public void Remove(object key)
-      {
-         ValidateCacheKey(key);
-
-         CheckDisposed();
-         if (_entries.TryRemove(key, out CacheEntry entry))
-         {
-            if (_options.SizeLimit.HasValue)
-            {
-               Interlocked.Add(ref _cacheSize, -entry.Size.Value);
-            }
-
-            entry.SetExpired(EvictionReason.Removed);
-            entry.InvokeEvictionCallbacks();
-         }
-
-         StartScanForExpiredItemsIfNeeded(_options.Clock.UtcNow);
-      }
-
-      private void RemoveEntry(CacheEntry entry)
-      {
-         if (EntriesCollection.Remove(new KeyValuePair<object, CacheEntry>(entry.Key, entry)))
-         {
-            if (_options.SizeLimit.HasValue)
-            {
-               Interlocked.Add(ref _cacheSize, -entry.Size.Value);
-            }
-            entry.InvokeEvictionCallbacks();
-         }
-      }
-
-      internal void EntryExpired(CacheEntry entry)
-      {
-         // TODO: For efficiency consider processing these expirations in batches.
-         RemoveEntry(entry);
-         StartScanForExpiredItemsIfNeeded(_options.Clock.UtcNow);
-      }
-
-      // Called by multiple actions to see how long it's been since we last checked for expired items.
-      // If sufficient time has elapsed then a scan is initiated on a background task.
-      [MethodImpl(MethodImplOptions.AggressiveInlining)]
-      private void StartScanForExpiredItemsIfNeeded(DateTimeOffset utcNow)
-      {
-         if (_options.ExpirationScanFrequency < utcNow - _lastExpirationScan)
-         {
-            ScheduleTask(utcNow);
-         }
-
-         void ScheduleTask(DateTimeOffset utcNow)
-         {
-            _lastExpirationScan = utcNow;
-            Task.Factory.StartNew(state => ScanForExpiredItems((MemoryCache)state), this,
-                CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
-         }
-      }
-
-      private static void ScanForExpiredItems(MemoryCache cache)
-      {
-         DateTimeOffset now = cache._lastExpirationScan = cache._options.Clock.UtcNow;
-
-         foreach (KeyValuePair<object, CacheEntry> item in cache._entries)
-         {
-            CacheEntry entry = item.Value;
-
-            if (entry.CheckExpired(now))
-            {
-               cache.RemoveEntry(entry);
-            }
-         }
-      }
-
-      private bool UpdateCacheSizeExceedsCapacity(CacheEntry entry)
-      {
-         if (!_options.SizeLimit.HasValue)
-         {
-            return false;
-         }
-
-         long newSize = 0L;
-         for (int i = 0; i < 100; i++)
-         {
-            long sizeRead = Interlocked.Read(ref _cacheSize);
-            newSize = sizeRead + entry.Size.Value;
-
-            if (newSize < 0 || newSize > _options.SizeLimit)
-            {
-               // Overflow occurred, return true without updating the cache size
-               return true;
-            }
-
-            if (sizeRead == Interlocked.CompareExchange(ref _cacheSize, newSize, sizeRead))
-            {
-               return false;
-            }
-         }
-
-         return true;
-      }
-
-      private void TriggerOvercapacityCompaction()
-      {
-         _logger.LogDebug("Overcapacity compaction triggered");
-
-         // Spawn background thread for compaction
-         ThreadPool.QueueUserWorkItem(s => OvercapacityCompaction((MemoryCache)s), this);
-      }
-
-      private static void OvercapacityCompaction(MemoryCache cache)
-      {
-         long currentSize = Interlocked.Read(ref cache._cacheSize);
-
-         cache._logger.LogDebug($"Overcapacity compaction executing. Current size {currentSize}");
-
-         double? lowWatermark = cache._options.SizeLimit * (1 - cache._options.CompactionPercentage);
-         if (currentSize > lowWatermark)
-         {
-            cache.Compact(currentSize - (long)lowWatermark, entry => entry.Size.Value);
-         }
-
-         cache._logger.LogDebug($"Overcapacity compaction executed. New size {Interlocked.Read(ref cache._cacheSize)}");
-      }
-
-      /// Remove at least the given percentage (0.10 for 10%) of the total entries (or estimated memory?), according to the following policy:
-      /// 1. Remove all expired items.
-      /// 2. Bucket by CacheItemPriority.
-      /// 3. Least recently used objects.
-      /// ?. Items with the soonest absolute expiration.
-      /// ?. Items with the soonest sliding expiration.
-      /// ?. Larger objects - estimated by object graph size, inaccurate.
-      public void Compact(double percentage)
-      {
-         int removalCountTarget = (int)(_entries.Count * percentage);
-         Compact(removalCountTarget, _ => 1);
-      }
-
-      private void Compact(long removalSizeTarget, Func<CacheEntry, long> computeEntrySize)
-      {
-         var entriesToRemove = new List<CacheEntry>();
-         var lowPriEntries = new List<CacheEntry>();
-         var normalPriEntries = new List<CacheEntry>();
-         var highPriEntries = new List<CacheEntry>();
-         long removedSize = 0;
-
-         // Sort items by expired & priority status
-         DateTimeOffset now = _options.Clock.UtcNow;
-         foreach (KeyValuePair<object, CacheEntry> item in _entries)
-         {
-            CacheEntry entry = item.Value;
-            if (entry.CheckExpired(now))
-            {
-               entriesToRemove.Add(entry);
-               removedSize += computeEntrySize(entry);
-            }
-            else
-            {
-               switch (entry.Priority)
-               {
-                  case CacheItemPriority.Low:
-                     lowPriEntries.Add(entry);
-                     break;
-                  case CacheItemPriority.Normal:
-                     normalPriEntries.Add(entry);
-                     break;
-                  case CacheItemPriority.High:
-                     highPriEntries.Add(entry);
-                     break;
-                  case CacheItemPriority.NeverRemove:
-                     break;
-                  default:
-                     throw new NotSupportedException("Not implemented: " + entry.Priority);
-               }
-            }
-         }
-
-         ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, lowPriEntries);
-         ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, normalPriEntries);
-         ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, highPriEntries);
-
-         foreach (CacheEntry entry in entriesToRemove)
-         {
-            RemoveEntry(entry);
-         }
-
-         // Policy:
-         // 1. Least recently used objects.
-         // ?. Items with the soonest absolute expiration.
-         // ?. Items with the soonest sliding expiration.
-         // ?. Larger objects - estimated by object graph size, inaccurate.
-         static void ExpirePriorityBucket(ref long removedSize, long removalSizeTarget, Func<CacheEntry, long> computeEntrySize, List<CacheEntry> entriesToRemove, List<CacheEntry> priorityEntries)
-         {
-            // Do we meet our quota by just removing expired entries?
-            if (removalSizeTarget <= removedSize)
-            {
-               // No-op, we've met quota
-               return;
-            }
-
-            // Expire enough entries to reach our goal
-            // TODO: Refine policy
-
-            // LRU
-            priorityEntries.Sort((e1, e2) => e1.LastAccessed.CompareTo(e2.LastAccessed));
-            foreach (CacheEntry entry in priorityEntries)
-            {
-               entry.SetExpired(EvictionReason.Capacity);
-               entriesToRemove.Add(entry);
-               removedSize += computeEntrySize(entry);
-
-               if (removalSizeTarget <= removedSize)
-               {
-                  break;
-               }
-            }
-         }
-      }
-
-      public void Dispose()
-      {
-         Dispose(true);
-      }
-
-      protected virtual void Dispose(bool disposing)
-      {
-         if (!_disposed)
-         {
-            if (disposing)
-            {
-               GC.SuppressFinalize(this);
-            }
-
-            _disposed = true;
-         }
-      }
-
-      private void CheckDisposed()
-      {
-         if (_disposed)
-         {
-            Throw();
-         }
-
-         static void Throw() => throw new ObjectDisposedException(typeof(MemoryCache).FullName);
-      }
-
-      private static void ValidateCacheKey(object key)
-      {
-         if (key == null)
-         {
-            Throw();
-         }
-
-         static void Throw() => throw new ArgumentNullException(nameof(key));
-      }
-   }
-}

+ 0 - 67
frameworks/CSharp/appmpower/src/Memory/MemoryCacheOptions.cs

@@ -1,67 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Microsoft.Extensions.Internal;
-using Microsoft.Extensions.Options;
-
-namespace appMpower.Memory
-{
-   public class MemoryCacheOptions : IOptions<MemoryCacheOptions>
-   {
-      private long? _sizeLimit;
-      private double _compactionPercentage = 0.05;
-
-      public ISystemClock Clock { get; set; }
-
-      /// <summary>
-      /// Gets or sets the minimum length of time between successive scans for expired items.
-      /// </summary>
-      public TimeSpan ExpirationScanFrequency { get; set; } = TimeSpan.FromMinutes(1);
-
-      /// <summary>
-      /// Gets or sets the maximum size of the cache.
-      /// </summary>
-      public long? SizeLimit
-      {
-         get => _sizeLimit;
-         set
-         {
-            if (value < 0)
-            {
-               throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be non-negative.");
-            }
-
-            _sizeLimit = value;
-         }
-      }
-
-      /// <summary>
-      /// Gets or sets the amount to compact the cache by when the maximum size is exceeded.
-      /// </summary>
-      public double CompactionPercentage
-      {
-         get => _compactionPercentage;
-         set
-         {
-            if (value < 0 || value > 1)
-            {
-               throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be between 0 and 1 inclusive.");
-            }
-
-            _compactionPercentage = value;
-         }
-      }
-
-      /// <summary>
-      /// Gets or sets whether to track linked entries. Disabled by default.
-      /// </summary>
-      /// <remarks>Prior to .NET 7 this feature was always enabled.</remarks>
-      public bool TrackLinkedCacheEntries { get; set; }
-
-      MemoryCacheOptions IOptions<MemoryCacheOptions>.Value
-      {
-         get { return this; }
-      }
-   }
-}

+ 0 - 24
frameworks/CSharp/appmpower/src/Microsoft/CachKey.cs

@@ -1,24 +0,0 @@
-using System;
-
-namespace PlatformBenchmarks
-{
-   public sealed class CacheKey : IEquatable<CacheKey>
-   {
-      private readonly int _value;
-
-      public CacheKey(int value)
-          => _value = value;
-
-      public bool Equals(CacheKey key)
-          => key._value == _value;
-
-      public override bool Equals(object obj)
-          => ReferenceEquals(obj, this);
-
-      public override int GetHashCode()
-          => _value;
-
-      public override string ToString()
-          => _value.ToString();
-   }
-}

+ 0 - 59
frameworks/CSharp/appmpower/src/Microsoft/StringBuilderCache.cs

@@ -1,59 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved. 
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 
-
-using System;
-using System.Text;
-
-namespace PlatformBenchmarks
-{
-   internal static class StringBuilderCache
-   {
-      private const int DefaultCapacity = 1386;
-      private const int MaxBuilderSize = DefaultCapacity * 3;
-
-      [ThreadStatic]
-      private static StringBuilder t_cachedInstance;
-
-      /// <summary>Get a StringBuilder for the specified capacity.</summary>
-      /// <remarks>If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied.</remarks>
-      public static StringBuilder Acquire(int capacity = DefaultCapacity)
-      {
-         if (capacity <= MaxBuilderSize)
-         {
-            StringBuilder sb = t_cachedInstance;
-            if (capacity < DefaultCapacity)
-            {
-               capacity = DefaultCapacity;
-            }
-
-            if (sb != null)
-            {
-               // Avoid stringbuilder block fragmentation by getting a new StringBuilder
-               // when the requested size is larger than the current capacity
-               if (capacity <= sb.Capacity)
-               {
-                  t_cachedInstance = null;
-                  sb.Clear();
-                  return sb;
-               }
-            }
-         }
-         return new StringBuilder(capacity);
-      }
-
-      public static void Release(StringBuilder sb)
-      {
-         if (sb.Capacity <= MaxBuilderSize)
-         {
-            t_cachedInstance = sb;
-         }
-      }
-
-      public static string GetStringAndRelease(StringBuilder sb)
-      {
-         string result = sb.ToString();
-         Release(sb);
-         return result;
-      }
-   }
-}

+ 0 - 42
frameworks/CSharp/appmpower/src/Program.cs

@@ -1,42 +0,0 @@
-using System;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Hosting.Server.Features;
-using Microsoft.AspNetCore.Server.Kestrel.Core;
-using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets;
-using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
-
-namespace appMpower
-{
-   class Program
-   {
-      static async Task Main(string[] args)
-      {
-         var socketTransportOptions = new SocketTransportOptions();
-         var socketTransportFactory = new SocketTransportFactory(Options.Create(socketTransportOptions), NullLoggerFactory.Instance);
-         var kestrelServerOptions = new KestrelServerOptions();
-
-         kestrelServerOptions.Listen(IPAddress.Any, 8080);
-         kestrelServerOptions.AllowSynchronousIO = true; 
-         kestrelServerOptions.AddServerHeader = false;
-
-         using var kestrelServer = new KestrelServer(Options.Create(kestrelServerOptions), socketTransportFactory, NullLoggerFactory.Instance);
-
-         await kestrelServer.StartAsync(new HttpApplication(), CancellationToken.None);
-
-         Console.WriteLine("Listening on:");
-
-         foreach (var address in kestrelServer.Features.Get<IServerAddressesFeature>().Addresses)
-         {
-            Console.WriteLine(" - " + address);
-         }
-
-         Console.WriteLine("Process CTRL+C to quit");
-         var wh = new ManualResetEventSlim();
-         Console.CancelKeyPress += (sender, e) => wh.Set();
-         wh.Wait();
-      }
-   }
-}

+ 10 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Constants.cs

@@ -0,0 +1,10 @@
+using appMpower.Orm.Data; 
+
+namespace appMpower.Orm
+{
+  public static class Constants
+  {
+    public static Dbms Dbms = Dbms.PostgreSQL; 
+    public static DbProvider DbProvider = DbProvider.ODBC; 
+  }
+}

+ 40 - 63
frameworks/CSharp/appmpower/src/Data/DbCommand.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbCommand.cs

@@ -1,56 +1,40 @@
 using System.Data;
 using System.Data;
-using System.Threading.Tasks;
+using System.Data.Odbc; 
 
 
-namespace appMpower.Data
+namespace appMpower.Orm.Data
 {
 {
    public class DbCommand : IDbCommand
    public class DbCommand : IDbCommand
    {
    {
-      private IDbCommand _dbCommand;
+      private OdbcCommand _odbcCommand;
       private DbConnection _dbConnection;
       private DbConnection _dbConnection;
 
 
       public DbCommand(DbConnection dbConnection)
       public DbCommand(DbConnection dbConnection)
       {
       {
-         _dbCommand = dbConnection.CreateCommand();
+         _odbcCommand = (OdbcCommand)dbConnection.CreateCommand();
          _dbConnection = dbConnection;
          _dbConnection = dbConnection;
       }
       }
 
 
       public DbCommand(string commandText, DbConnection dbConnection)
       public DbCommand(string commandText, DbConnection dbConnection)
       {
       {
-         dbConnection.GetCommand(commandText, CommandType.Text, this);
+         _odbcCommand = dbConnection.GetCommand(commandText, CommandType.Text);
+         _dbConnection = dbConnection;
       }
       }
 
 
       public DbCommand(string commandText, CommandType commandType, DbConnection dbConnection)
       public DbCommand(string commandText, CommandType commandType, DbConnection dbConnection)
       {
       {
-         dbConnection.GetCommand(commandText, commandType, this);
-      }
-
-      internal DbCommand(IDbCommand dbCommand, DbConnection dbConnection)
-      {
-         _dbCommand = dbCommand;
-         _dbConnection = dbConnection;
+         _odbcCommand = dbConnection.GetCommand(commandText, commandType);
+         _dbConnection = dbConnection; 
       }
       }
 
 
       internal IDbCommand Command
       internal IDbCommand Command
       {
       {
          get
          get
          {
          {
-            return _dbCommand;
+            return _odbcCommand;
          }
          }
          set
          set
          {
          {
-            _dbCommand = value;
-         }
-      }
-
-      internal DbConnection DbConnection
-      {
-         get
-         {
-            return _dbConnection;
-         }
-         set
-         {
-            _dbConnection = value;
+            _odbcCommand = (OdbcCommand)value;
          }
          }
       }
       }
 
 
@@ -58,11 +42,11 @@ namespace appMpower.Data
       {
       {
          get
          get
          {
          {
-            return _dbCommand.CommandText;
+            return _odbcCommand.CommandText;
          }
          }
          set
          set
          {
          {
-            _dbCommand.CommandText = value;
+            _odbcCommand.CommandText = value;
          }
          }
       }
       }
 
 
@@ -70,22 +54,22 @@ namespace appMpower.Data
       {
       {
          get
          get
          {
          {
-            return _dbCommand.CommandTimeout;
+            return _odbcCommand.CommandTimeout;
          }
          }
          set
          set
          {
          {
-            _dbCommand.CommandTimeout = value;
+            _odbcCommand.CommandTimeout = value;
          }
          }
       }
       }
       public CommandType CommandType
       public CommandType CommandType
       {
       {
          get
          get
          {
          {
-            return _dbCommand.CommandType;
+            return _odbcCommand.CommandType;
          }
          }
          set
          set
          {
          {
-            _dbCommand.CommandType = value;
+            _odbcCommand.CommandType = value;
          }
          }
       }
       }
 
 
@@ -94,11 +78,11 @@ namespace appMpower.Data
       {
       {
          get
          get
          {
          {
-            return _dbCommand.Connection;
+            return _odbcCommand.Connection;
          }
          }
          set
          set
          {
          {
-            _dbCommand.Connection = (IDbConnection?)value;
+            _odbcCommand.Connection = (OdbcConnection?)value;
          }
          }
       }
       }
 #nullable disable
 #nullable disable
@@ -107,7 +91,7 @@ namespace appMpower.Data
       {
       {
          get
          get
          {
          {
-            return _dbCommand.Parameters;
+            return _odbcCommand.Parameters;
          }
          }
       }
       }
 
 
@@ -116,11 +100,11 @@ namespace appMpower.Data
       {
       {
          get
          get
          {
          {
-            return _dbCommand.Transaction;
+            return _odbcCommand.Transaction;
          }
          }
          set
          set
          {
          {
-            _dbCommand.Transaction = (IDbTransaction?)value;
+            _odbcCommand.Transaction = (OdbcTransaction?)value;
          }
          }
       }
       }
 #nullable disable
 #nullable disable
@@ -129,21 +113,21 @@ namespace appMpower.Data
       {
       {
          get
          get
          {
          {
-            return _dbCommand.UpdatedRowSource;
+            return _odbcCommand.UpdatedRowSource;
          }
          }
          set
          set
          {
          {
-            _dbCommand.UpdatedRowSource = value;
+            _odbcCommand.UpdatedRowSource = value;
          }
          }
       }
       }
       public void Cancel()
       public void Cancel()
       {
       {
-         _dbCommand.Cancel();
+         _odbcCommand.Cancel();
       }
       }
 
 
       public IDbDataParameter CreateParameter()
       public IDbDataParameter CreateParameter()
       {
       {
-         return _dbCommand.CreateParameter();
+         return _odbcCommand.CreateParameter();
       }
       }
 
 
       public IDbDataParameter CreateParameter(string name, object value)
       public IDbDataParameter CreateParameter(string name, object value)
@@ -153,21 +137,21 @@ namespace appMpower.Data
 
 
       public IDbDataParameter CreateParameter(string name, DbType dbType, object value)
       public IDbDataParameter CreateParameter(string name, DbType dbType, object value)
       {
       {
-         IDbDataParameter dbDataParameter = null;
+         IDbDataParameter dbDataParameter;
 
 
-         if (this.Parameters.Contains(name))
+         if (_odbcCommand.Parameters.Contains(name))
          {
          {
-            dbDataParameter = this.Parameters[name] as IDbDataParameter;
+            dbDataParameter = _odbcCommand.Parameters[name];
             dbDataParameter.Value = value;
             dbDataParameter.Value = value;
          }
          }
          else
          else
          {
          {
-            dbDataParameter = _dbCommand.CreateParameter();
+            dbDataParameter = _odbcCommand.CreateParameter();
 
 
             dbDataParameter.ParameterName = name;
             dbDataParameter.ParameterName = name;
             dbDataParameter.DbType = dbType;
             dbDataParameter.DbType = dbType;
             dbDataParameter.Value = value;
             dbDataParameter.Value = value;
-            this.Parameters.Add(dbDataParameter);
+            _odbcCommand.Parameters.Add(dbDataParameter);
          }
          }
 
 
          return dbDataParameter;
          return dbDataParameter;
@@ -175,51 +159,44 @@ namespace appMpower.Data
 
 
       public int ExecuteNonQuery()
       public int ExecuteNonQuery()
       {
       {
-         return _dbCommand.ExecuteNonQuery();
+         return _odbcCommand.ExecuteNonQuery();
       }
       }
 
 
       public IDataReader ExecuteReader()
       public IDataReader ExecuteReader()
       {
       {
-         return _dbCommand.ExecuteReader();
+         return _odbcCommand.ExecuteReader();
       }
       }
 
 
       public async Task<int> ExecuteNonQueryAsync()
       public async Task<int> ExecuteNonQueryAsync()
       {
       {
-         return await (_dbCommand as System.Data.Common.DbCommand).ExecuteNonQueryAsync();
-      }
-
-      public async Task<System.Data.Common.DbDataReader> ExecuteReaderAsync(CommandBehavior behavior)
-      {
-         return await (_dbCommand as System.Data.Common.DbCommand).ExecuteReaderAsync(behavior);
+         return await _odbcCommand.ExecuteNonQueryAsync();
       }
       }
 
 
       public IDataReader ExecuteReader(CommandBehavior behavior)
       public IDataReader ExecuteReader(CommandBehavior behavior)
       {
       {
-         return _dbCommand.ExecuteReader(behavior);
+         return _odbcCommand.ExecuteReader(behavior);
       }
       }
 
 
-#nullable enable
-      public object? ExecuteScalar()
+      public async Task<System.Data.Common.DbDataReader> ExecuteReaderAsync(CommandBehavior behavior)
       {
       {
-         return _dbCommand.ExecuteScalar();
+         return await _odbcCommand.ExecuteReaderAsync(behavior);
       }
       }
-#nullable disable
 
 
 #nullable enable
 #nullable enable
-      public async Task<object?> ExecuteScalarAsync()
+      public object? ExecuteScalar()
       {
       {
-         return await ((System.Data.Common.DbCommand)_dbCommand).ExecuteScalarAsync();
+         return _odbcCommand.ExecuteScalar();
       }
       }
 #nullable disable
 #nullable disable
 
 
       public void Prepare()
       public void Prepare()
       {
       {
-         _dbCommand.Prepare();
+         _odbcCommand.Prepare();
       }
       }
 
 
       public void Dispose()
       public void Dispose()
       {
       {
-         _dbConnection.ReleaseCommand(this);
+         _dbConnection.Release(_odbcCommand);
       }
       }
    }
    }
 }
 }

+ 174 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs

@@ -0,0 +1,174 @@
+using System.Collections.Concurrent;
+using System.Data;
+using System.Data.Odbc;
+
+namespace appMpower.Orm.Data
+{
+   public class DbConnection : IDbConnection
+   {
+      private string _connectionString;
+      private bool _keyed = false;
+      private int _number;
+      private OdbcConnection _odbcConnection;
+      private ConcurrentStack<OdbcCommand> _odbcCommands = new();
+      private Dictionary<string, OdbcCommand> _keyedOdbcCommands;
+
+      public DbConnection()
+      {
+      }
+
+      public DbConnection(string connectionString, bool keyed = false)
+      {
+         _keyed = keyed;
+         _connectionString = connectionString; 
+         GetConnection();
+      }
+
+      public IDbConnection Connection
+      {
+         get
+         {
+            return _odbcConnection;
+         }
+         set
+         {
+            _odbcConnection = (OdbcConnection)value;
+         }
+      }
+
+      public string ConnectionString
+      {
+         get
+         {
+            return _odbcConnection.ConnectionString;
+         }
+         set
+         {
+            _connectionString = value; 
+            GetConnection();
+         }
+      }
+
+      private void GetConnection()
+      {
+         if (_keyed)
+         {
+            (_number, _odbcConnection, _keyedOdbcCommands) = 
+               DbConnectionsKeyed.GetConnectionBase(_connectionString).GetAwaiter().GetResult();
+         }
+         else
+         {
+            (_number, _odbcConnection, _odbcCommands) = 
+               DbConnections.GetConnectionBase(_connectionString).GetAwaiter().GetResult();
+         }
+      }
+
+      public int ConnectionTimeout
+      {
+         get
+         {
+            return _odbcConnection.ConnectionTimeout;
+         }
+      }
+
+      public string Database
+      {
+         get
+         {
+            return _odbcConnection.Database;
+         }
+      }
+
+      public ConnectionState State
+      {
+         get
+         {
+            if (_odbcConnection is null) return ConnectionState.Closed;
+            return _odbcConnection.State;
+         }
+      }
+
+      public IDbTransaction BeginTransaction()
+      {
+         return _odbcConnection.BeginTransaction();
+      }
+
+      public IDbTransaction BeginTransaction(IsolationLevel il)
+      {
+         return _odbcConnection.BeginTransaction(il);
+      }
+
+      public void ChangeDatabase(string databaseName)
+      {
+         _odbcConnection.ChangeDatabase(databaseName);
+      }
+
+      public void Close()
+      {
+         _odbcConnection.Close();
+      }
+
+      public IDbCommand CreateCommand()
+      {
+         return _odbcConnection.CreateCommand();
+      }
+
+      public void Open()
+      {
+         if (_odbcConnection.State == ConnectionState.Closed)
+         {
+            _odbcConnection.Open();
+         }
+      }
+
+      public async Task OpenAsync()
+      {
+         if (_odbcConnection.State == ConnectionState.Closed)
+         {
+            await _odbcConnection.OpenAsync();
+         }
+      }
+
+      public void Dispose()
+      {
+         if (_keyed)
+         {
+            DbConnectionsKeyed.Release((Number: _number, OdbcConnection: _odbcConnection, KeyedOdbcCommands: _keyedOdbcCommands));
+         }
+         else
+         {
+            DbConnections.Release((Number: _number, OdbcConnection: _odbcConnection, OdbcCommands: _odbcCommands));
+         }
+      }
+
+      internal OdbcCommand GetCommand(string commandText, CommandType commandType)
+      {
+         OdbcCommand odbcCommand;
+
+         if (_odbcCommands.TryPop(out odbcCommand))
+         {
+            if (commandText != odbcCommand.CommandText)
+            {
+               odbcCommand.CommandText = commandText; 
+               odbcCommand.Parameters.Clear();
+            }
+
+            return odbcCommand; 
+         }
+         else if (_keyed && _keyedOdbcCommands.TryGetValue(commandText, out odbcCommand)) return odbcCommand; 
+
+         odbcCommand = _odbcConnection.CreateCommand();
+         odbcCommand.CommandText = commandText;
+         odbcCommand.CommandType = commandType;
+         odbcCommand.Prepare();
+
+         return odbcCommand;
+      }
+
+      internal void Release(OdbcCommand odbcCommand)
+      {
+         if (_keyed) _keyedOdbcCommands.TryAdd(odbcCommand.CommandText, odbcCommand);
+         else _odbcCommands.Push(odbcCommand);
+      }
+   }
+}

+ 61 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs

@@ -0,0 +1,61 @@
+using System.Collections.Concurrent;
+using System.Data.Odbc;
+
+namespace appMpower.Orm.Data
+{
+   internal static class DbConnections
+   {
+      private static bool _maxConnectionsCreated = false;
+      private static short _createdConnections = 0;
+      private static short _maxConnections = 500;
+
+      private static ConcurrentStack<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> _connectionsStack = new();
+      private static ConcurrentQueue<TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)>> _waitingQueue = new();
+      
+      internal static async Task<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> GetConnectionBase(string connectionString)
+      {
+         (int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands) dbConnectionBase;
+
+         if (!_connectionsStack.TryPop(out dbConnectionBase))
+         {
+            if (_maxConnectionsCreated)
+            {
+               dbConnectionBase = await GetDbConnectionBaseAsync();
+            }
+            else
+            {
+               _createdConnections++;
+               dbConnectionBase = (Number: _maxConnections, OdbcConnection: new OdbcConnection(connectionString), OdbcCommands: new ConcurrentStack<OdbcCommand>());
+
+               if (_createdConnections == _maxConnections) _maxConnectionsCreated = true;
+
+               //Console.WriteLine("opened connection number: " + dbConnectionBase._number);
+            }
+         }
+
+         return dbConnectionBase;
+      }
+
+      internal static void Release((int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands) dbConnectionBase)
+      {
+         TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> taskCompletionSource;
+
+         if (_waitingQueue.TryDequeue(out taskCompletionSource))
+         {
+            taskCompletionSource.SetResult(dbConnectionBase);
+         }
+         else
+         {
+            _connectionsStack.Push(dbConnectionBase);
+         }
+      }
+
+      private static Task<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> GetDbConnectionBaseAsync()
+      {
+         var taskCompletionSource = new TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)>(TaskCreationOptions.RunContinuationsAsynchronously);
+
+         _waitingQueue.Enqueue(taskCompletionSource);
+         return taskCompletionSource.Task;
+      }
+   }
+}

+ 61 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnectionsKeyed.cs

@@ -0,0 +1,61 @@
+using System.Collections.Concurrent;
+using System.Data.Odbc;
+
+namespace appMpower.Orm.Data
+{
+   internal static class DbConnectionsKeyed
+   {
+      private static bool _maxConnectionsCreated = false;
+      private static short _createdConnections = 0;
+      private static short _maxConnections = 500;
+
+      private static ConcurrentStack<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> _connectionsStack = new();
+      private static ConcurrentQueue<TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)>> _waitingQueue = new();
+
+      internal static async Task<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands)> GetConnectionBase(string connectionString)
+      {
+         (int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands) dbConnectionBase;
+
+         if (!_connectionsStack.TryPop(out dbConnectionBase))
+         {
+            if (_maxConnectionsCreated)
+            {
+               dbConnectionBase = await GetDbConnectionBaseAsync();
+            }
+            else
+            {
+               _createdConnections++;
+               dbConnectionBase = (Number: _maxConnections, OdbcConnection: new OdbcConnection(connectionString), KeyedOdbcCommands: new Dictionary<string, OdbcCommand>());
+
+               if (_createdConnections == _maxConnections) _maxConnectionsCreated = true;
+
+               //Console.WriteLine("opened connection number: " + dbConnectionBase._number);
+            }
+         }
+
+         return dbConnectionBase;
+      }
+
+      internal static void Release((int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands) dbConnectionBase)
+      {
+         TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> taskCompletionSource;
+
+         if (_waitingQueue.TryDequeue(out taskCompletionSource))
+         {
+            taskCompletionSource.SetResult(dbConnectionBase);
+         }
+         else
+         {
+            _connectionsStack.Push(dbConnectionBase);
+         }
+      }
+
+      private static Task<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> GetDbConnectionBaseAsync()
+      {
+         var taskCompletionSource = new TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)>(TaskCreationOptions.RunContinuationsAsynchronously);
+
+         _waitingQueue.Enqueue(taskCompletionSource);
+         return taskCompletionSource.Task;
+      }
+   }
+}

+ 8 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProvider.cs

@@ -0,0 +1,8 @@
+namespace appMpower.Orm.Data
+{
+   public enum DbProvider
+   {
+      ADO = 0,
+      ODBC = 1,
+   }
+}

+ 21 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProviderFactory.cs

@@ -0,0 +1,21 @@
+using System.Data;
+
+namespace appMpower.Orm.Data
+{
+   public static class DbProviderFactory
+   {
+      public static string ConnectionString; 
+
+      public static void SetConnectionString()
+      {
+         if (Constants.Dbms == Dbms.MySQL)
+         {
+            ConnectionString = "Driver={MariaDB};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;Pooling=false;OPTIONS=67108864;FLAG_FORWARD_CURSOR=1;sslmode=DISABLED;CharSet=utf8;"; 
+         }
+         else
+         {
+            ConnectionString = "Driver={PostgreSQL};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false;sslmode=disable";
+         }
+      }
+   }
+}

+ 9 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Data/Dbms.cs

@@ -0,0 +1,9 @@
+namespace appMpower.Orm.Data
+{
+   public enum Dbms
+   {
+      MySQL = 0,
+      PostgreSQL = 1,
+      SQLServer = 2,
+   }
+}

+ 66 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/DotnetMethods.cs

@@ -0,0 +1,66 @@
+using System.Runtime.InteropServices;
+using System.Text; 
+using System.Text.Json; 
+using appMpower.Orm.Data; 
+using appMpower.Orm.Objects; 
+using appMpower.Orm.Serializers; 
+
+namespace appMpower.Orm;
+
+//These methods are for test purposes only; not used in actual execution
+public static class DotnetMethods
+{
+    private static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions
+    {
+        Indented = false, 
+        SkipValidation = true
+    };
+
+    private readonly static WorldSerializer _worldSerializer = new WorldSerializer();
+    private readonly static WorldsSerializer _worldsSerializer = new WorldsSerializer();
+
+    public static byte[] Db()
+    {
+        var world = RawDb.LoadSingleQueryRow().GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldSerializer.Serialize(utf8JsonWriter, world);
+
+        return memoryStream.ToArray();
+    }
+
+    public static byte[] Query(int queries)
+    {
+        World[] worlds = RawDb.ReadMultipleRows(queries).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldsSerializer.Serialize(utf8JsonWriter, worlds);
+
+        return memoryStream.ToArray();
+    }
+
+    public static byte[] Updates(int count)
+    {
+        World[] worlds = RawDb.LoadMultipleUpdatesRows(count).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldsSerializer.Serialize(utf8JsonWriter, worlds);
+
+        return memoryStream.ToArray();
+    }
+
+    public static byte[] Fortunes()
+    {
+        List<Fortune> fortunes = RawDb.LoadFortunesRows().GetAwaiter().GetResult(); 
+        string fortunesView = FortunesView.Render(fortunes);
+        byte[] byteArray = Encoding.UTF8.GetBytes(fortunesView);
+
+        return byteArray.ToArray();
+    }
+}

+ 4 - 17
frameworks/CSharp/appmpower/src/FortunesView.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/FortunesView.cs

@@ -1,33 +1,23 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.IO.Pipelines;
 using System.Globalization;
 using System.Globalization;
 using System.Text;
 using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using System.Web;
 using System.Web;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.Primitives;
 using PlatformBenchmarks;
 using PlatformBenchmarks;
+using appMpower.Orm.Objects;
 
 
-namespace appMpower
+namespace appMpower.Orm
 {
 {
    public static class FortunesView
    public static class FortunesView
    {
    {
-      private readonly static KeyValuePair<string, StringValues> _headerServer =
-         new KeyValuePair<string, StringValues>("Server", "k");
-      private readonly static KeyValuePair<string, StringValues> _headerContentType =
-         new KeyValuePair<string, StringValues>("Content-Type", "text/html; charset=UTF-8");
-
       public static char[] _fortunesTableStart = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>".ToCharArray();
       public static char[] _fortunesTableStart = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>".ToCharArray();
       public static char[] _fortunesRowStart = "<tr><td>".ToCharArray();
       public static char[] _fortunesRowStart = "<tr><td>".ToCharArray();
       public static char[] _fortunesColumn = "</td><td>".ToCharArray();
       public static char[] _fortunesColumn = "</td><td>".ToCharArray();
       public static char[] _fortunesRowEnd = "</td></tr>".ToCharArray();
       public static char[] _fortunesRowEnd = "</td></tr>".ToCharArray();
       public static char[] _fortunesTableEnd = "</table></body></html>".ToCharArray();
       public static char[] _fortunesTableEnd = "</table></body></html>".ToCharArray();
 
 
-      public static async Task Render(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, List<Fortune> fortunes)
+      public static string Render(List<Fortune> fortunes)
       {
       {
-         headerDictionary.Add(_headerServer);
-         headerDictionary.Add(_headerContentType);
-
          var writer = StringBuilderCache.Acquire();
          var writer = StringBuilderCache.Acquire();
 
 
          writer.Append(_fortunesTableStart);
          writer.Append(_fortunesTableStart);
@@ -39,10 +29,7 @@ namespace appMpower
 
 
          writer.Append(_fortunesTableEnd);
          writer.Append(_fortunesTableEnd);
 
 
-         headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", (writer.Length + 32).ToString()));
-
-         await pipeWriter.WriteAsync(Encoding.UTF8.GetBytes(StringBuilderCache.GetStringAndRelease(writer)));
-         pipeWriter.Complete();
+         return StringBuilderCache.GetStringAndRelease(writer);
       }
       }
    }
    }
 }
 }

+ 19 - 37
frameworks/CSharp/appmpower/src/Microsoft/BatchUpdateString.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/BatchUpdateString.cs

@@ -1,7 +1,8 @@
 // Copyright (c) .NET Foundation. All rights reserved. 
 // Copyright (c) .NET Foundation. All rights reserved. 
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 
 
 
-using System.Linq;
+using appMpower.Orm; 
+using appMpower.Orm.Data; 
 
 
 namespace PlatformBenchmarks
 namespace PlatformBenchmarks
 {
 {
@@ -33,51 +34,32 @@ namespace PlatformBenchmarks
          //sb.Append("(?::int,?::int)) AS temp(id, randomNumber) WHERE temp.id = world.id");
          //sb.Append("(?::int,?::int)) AS temp(id, randomNumber) WHERE temp.id = world.id");
          */
          */
 
 
-#if MYSQL
-         for (int i = 0; i < batchSize; i++)
+         if (Constants.Dbms == Dbms.MySQL)
          {
          {
-            sb.Append("UPDATE world SET randomNumber=? WHERE id=?;");
+            for (int i = 0; i < batchSize; i++)
+            {
+               sb.Append("UPDATE world SET randomNumber=? WHERE id=?;");
+            }
          }
          }
-#elif ADO
-         /*
-         sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ");
-         Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append($"(@i{i}, @r{i}), "));
-         sb.Append($"(@i{lastIndex}, @r{lastIndex}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
-         */
-
-         sb.Append("UPDATE world SET randomNumber=CASE id ");
-
-         for (int i = 0; i < batchSize; i++)
-         {
-            sb.Append("WHEN @i" + i + " THEN @r" + i + " ");
-         }
-
-         sb.Append("ELSE randomnumber END WHERE id IN(");
-
-         for (int i = 0; i < lastIndex; i++)
+         else
          {
          {
-            sb.Append("@j" + i + ",");
-         }
+            sb.Append("UPDATE world SET randomNumber=CASE id ");
 
 
-         sb.Append("@j" + lastIndex + ")");
-#else
-         sb.Append("UPDATE world SET randomNumber=CASE id ");
+            for (int i = 0; i < batchSize; i++)
+            {
+               sb.Append("WHEN ? THEN ? ");
+            }
 
 
-         for (int i = 0; i < batchSize; i++)
-         {
-            sb.Append("WHEN ? THEN ? ");
-         }
+            sb.Append("ELSE randomnumber END WHERE id IN(");
 
 
-         sb.Append("ELSE randomnumber END WHERE id IN(");
+            for (int i = 0; i < lastIndex; i++)
+            {
+               sb.Append("?,");
+            }
 
 
-         for (int i = 0; i < lastIndex; i++)
-         {
-            sb.Append("?,");
+            sb.Append("?)");
          }
          }
 
 
-         sb.Append("?)");
-#endif
-
          return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb);
          return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb);
       }
       }
    }
    }

+ 0 - 2
frameworks/CSharp/appmpower/src/Microsoft/ConcurrentRandom.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/ConcurrentRandom.cs

@@ -1,9 +1,7 @@
 // Copyright (c) .NET Foundation. All rights reserved. 
 // Copyright (c) .NET Foundation. All rights reserved. 
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 
 
 
-using System;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
-using System.Threading;
 
 
 namespace PlatformBenchmarks
 namespace PlatformBenchmarks
 {
 {

+ 54 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/StringBuilderCache.cs

@@ -0,0 +1,54 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Text;
+
+namespace PlatformBenchmarks; 
+
+internal static class StringBuilderCache
+{
+    private const int DefaultCapacity = 1386;
+    private const int MaxBuilderSize = DefaultCapacity * 3;
+    [ThreadStatic]
+    private static StringBuilder t_cachedInstance;
+
+    public static StringBuilder Acquire(int capacity = DefaultCapacity)
+    {
+        if (capacity <= MaxBuilderSize)
+        {
+            StringBuilder sb = t_cachedInstance;
+
+            if (capacity < DefaultCapacity)
+            {
+                capacity = DefaultCapacity;
+            }
+
+            if (sb != null)
+            {
+                if (capacity <= sb.Capacity)
+                {
+                    t_cachedInstance = null;
+                    sb.Clear();
+                    return sb;
+                }
+            }
+        }
+
+        return new StringBuilder(capacity);
+    }
+
+    public static void Release(StringBuilder sb)
+    {
+        if (sb.Capacity <= MaxBuilderSize)
+        {
+            t_cachedInstance = sb;
+        }
+    }
+
+    public static string GetStringAndRelease(StringBuilder sb)
+    {
+        string result = sb.ToString();
+        Release(sb);
+        return result;
+    }
+}

+ 203 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs

@@ -0,0 +1,203 @@
+using System.Runtime.InteropServices;
+using System.Text; 
+using System.Text.Json; 
+using appMpower.Orm.Data; 
+using appMpower.Orm.Objects; 
+using appMpower.Orm.Serializers; 
+
+namespace appMpower.Orm;
+
+public static class NativeMethods
+{
+    private static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions
+    {
+        Indented = false, 
+        SkipValidation = true
+    };
+
+    private readonly static WorldSerializer _worldSerializer = new WorldSerializer();
+    private readonly static WorldsSerializer _worldsSerializer = new WorldsSerializer();
+    private readonly static FortunesSerializer _fortunesSerializer = new FortunesSerializer();
+    private static readonly byte[] _delimiter = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };
+
+
+    [UnmanagedCallersOnly(EntryPoint = "Dbms")]
+    public static void Dbms(int dbms)
+    {
+        Constants.Dbms = (Dbms)dbms; 
+        DbProviderFactory.SetConnectionString();
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "DbProvider")]
+    public static void DbProvider(int dbProvider)
+    {
+        Constants.DbProvider = (DbProvider)dbProvider; 
+        DbProviderFactory.SetConnectionString();
+    }
+    
+    [UnmanagedCallersOnly(EntryPoint = "FreeHandlePointer")]
+    public static void FreeHandlePointer(IntPtr handlePointer)
+    {
+        GCHandle handle = GCHandle.FromIntPtr(handlePointer);
+        handle.Free();
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "Db")]
+    public static unsafe IntPtr Db(int* length, IntPtr* handlePointer)
+    {
+        var world = RawDb.LoadSingleQueryRow().GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldSerializer.Serialize(utf8JsonWriter, world);
+
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        byte[] byteArray = memoryStream.ToArray();
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        // return the managed and byteArrayPointer pointer
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+        /*
+        fixed(byte* b = memoryStream.ToArray())
+        {
+            return b; 
+        }
+        */
+    }
+
+    /*
+    [UnmanagedCallersOnly(EntryPoint = "Fortunes")]
+    public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer)
+    {
+        List<Fortune> fortunes = RawDb.LoadFortunesRows().GetAwaiter().GetResult(); 
+        string fortunesView = FortunesView.Render(fortunes);
+        byte[] byteArray = Encoding.UTF8.GetBytes(fortunesView);
+
+        *length = byteArray.Length; 
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+    */
+
+    [UnmanagedCallersOnly(EntryPoint = "Fortunes")]
+    public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer)
+    {
+        List<Fortune> fortunes = RawDb.LoadFortunesRows().GetAwaiter().GetResult(); 
+
+        int totalSize = 0;
+
+        foreach (var fortune in fortunes)
+        {
+            totalSize += sizeof(int) // for Id
+                       + Encoding.UTF8.GetByteCount(fortune.Message ?? "") // for Message
+                       + _delimiter.Length; // for delimiter
+        }
+
+        // Allocate the total buffer
+        byte[] buffer = new byte[totalSize];
+        int offset = 0;
+
+        // Write each object to the buffer
+        foreach (var fortune in fortunes)
+        {
+            // Write Id
+            BitConverter.TryWriteBytes(buffer.AsSpan(offset, sizeof(int)), fortune.Id);
+            offset += sizeof(int);
+
+            // Write Message
+            int descriptionLength = Encoding.UTF8.GetBytes(fortune.Message ?? "", buffer.AsSpan(offset));
+            offset += descriptionLength;
+
+            // Write Delimiter
+            _delimiter.CopyTo(buffer, offset);
+            offset += _delimiter.Length;
+        }
+
+        byte[] byteArray = buffer.ToArray();
+        *length = byteArray.Length; 
+
+        /*
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _fortunesSerializer.Serialize(utf8JsonWriter, fortunes);
+
+        byte[] byteArray = memoryStream.ToArray();
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        */
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "Query")]
+    public static unsafe IntPtr Query(int queries, int* length, IntPtr* handlePointer)
+    {
+        World[] worlds = RawDb.ReadMultipleRows(queries).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldsSerializer.Serialize(utf8JsonWriter, worlds);
+
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        byte[] byteArray = memoryStream.ToArray();
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "Updates")]
+    public static unsafe IntPtr Updates(int count, int* length, IntPtr* handlePointer)
+    {
+        World[] worlds = RawDb.LoadMultipleUpdatesRows(count).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldsSerializer.Serialize(utf8JsonWriter, worlds);
+
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        byte[] byteArray = memoryStream.ToArray();
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+
+    [UnmanagedCallersOnly(EntryPoint = "DbById")]
+    public static unsafe IntPtr DbById(int id, int* length, IntPtr* handlePointer)
+    {
+        var world = RawDb.LoadSingleQueryRowById(id).GetAwaiter().GetResult();
+
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _worldSerializer.Serialize(utf8JsonWriter, world);
+
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        byte[] byteArray = memoryStream.ToArray();
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
+}

+ 1 - 1
frameworks/CSharp/appmpower/src/CachedWorld.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/CachedWorld.cs

@@ -1,4 +1,4 @@
-namespace appMpower
+namespace appMpower.Orm.Objects
 {
 {
    public struct CachedWorld
    public struct CachedWorld
    {
    {

+ 1 - 3
frameworks/CSharp/appmpower/src/Fortune.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/Fortune.cs

@@ -1,6 +1,4 @@
-using System;
-
-namespace appMpower
+namespace appMpower.Orm.Objects
 {
 {
    public readonly struct Fortune : IComparable<Fortune>, IComparable
    public readonly struct Fortune : IComparable<Fortune>, IComparable
    {
    {

+ 1 - 1
frameworks/CSharp/appmpower/src/World.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/World.cs

@@ -1,4 +1,4 @@
-namespace appMpower
+namespace appMpower.Orm.Objects
 {
 {
    public struct World
    public struct World
    {
    {

+ 50 - 131
frameworks/CSharp/appmpower/src/RawDb.cs → frameworks/CSharp/appmpower/src/appMpower.Orm/RawDb.cs

@@ -1,34 +1,18 @@
-using System;
-using System.Collections.Generic;
 using System.Data;
 using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.Extensions.Caching.Memory;
-using appMpower.Data; 
+using appMpower.Orm.Data; 
+using appMpower.Orm.Objects;
 using PlatformBenchmarks;
 using PlatformBenchmarks;
 
 
-namespace appMpower
+namespace appMpower.Orm
 {
 {
    public static class RawDb
    public static class RawDb
    {
    {
       private const int MaxBatch = 500;
       private const int MaxBatch = 500;
 
 
-#if ADO      
-      private static ConcurrentRandom _random = new ConcurrentRandom();
-#else
       private static Random _random = new Random();
       private static Random _random = new Random();
-#endif
 
 
       private static string[] _queriesMultipleRows = new string[MaxBatch + 1];
       private static string[] _queriesMultipleRows = new string[MaxBatch + 1];
 
 
-      private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray();
-
-      private static readonly appMpower.Memory.MemoryCache _cache = new appMpower.Memory.MemoryCache(
-            new appMpower.Memory.MemoryCacheOptions()
-            {
-               ExpirationScanFrequency = TimeSpan.FromMinutes(60)
-            });
-
       public static async Task<World> LoadSingleQueryRow()
       public static async Task<World> LoadSingleQueryRow()
       {
       {
          using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
          using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
@@ -38,7 +22,22 @@ namespace appMpower
 
 
          using (dbCommand)
          using (dbCommand)
          {
          {
-            var world = await ReadSingleRow(dbCommand);
+            World world = await ReadSingleRow(dbCommand);
+
+            return world;
+         }
+      }
+
+      public static async Task<World> LoadSingleQueryRowById(int id)
+      {
+         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
+         await pooledConnection.OpenAsync();
+
+         var (dbCommand, _) = CreateReadCommandById(pooledConnection, id);
+
+         using (dbCommand)
+         {
+            World world = await ReadSingleRow(dbCommand);
 
 
             return world;
             return world;
          }
          }
@@ -76,21 +75,17 @@ namespace appMpower
 
 
          using (dbCommand)
          using (dbCommand)
          {
          {
-            var dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleResult & CommandBehavior.SequentialAccess);
+            IDataReader dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleResult & CommandBehavior.SequentialAccess);
 
 
             while (dataReader.Read())
             while (dataReader.Read())
             {
             {
                fortunes.Add(new Fortune
                fortunes.Add(new Fortune
                (
                (
-                   id: dataReader.GetInt32(0),
-#if MYSQL
-               //MariaDB ODBC connector does not correctly support Japanese characters in combination with default ADO.NET;
-               //as a solution we custom read this string
-                message: ReadColumn(dataReader, 1)
-#else
-                message: dataReader.GetString(1)
-#endif
-            ));
+                  id: dataReader.GetInt32(0),
+                  //MariaDB ODBC connector does not correctly support Japanese characters in combination with default ADO.NET;
+                  //as a solution we custom read this string
+                  message: (Constants.Dbms == Dbms.MySQL ? ReadColumn(dataReader, 1) : dataReader.GetString(1))
+               ));
             }
             }
 
 
             dataReader.Close();
             dataReader.Close();
@@ -106,7 +101,7 @@ namespace appMpower
       {
       {
          var worlds = new World[count];
          var worlds = new World[count];
 
 
-         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
+         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString, true);
          await pooledConnection.OpenAsync();
          await pooledConnection.OpenAsync();
 
 
          var (queryCommand, dbDataParameter) = CreateReadCommand(pooledConnection);
          var (queryCommand, dbDataParameter) = CreateReadCommand(pooledConnection);
@@ -120,14 +115,10 @@ namespace appMpower
             }
             }
          }
          }
 
 
-         using var updateCommand = new DbCommand(PlatformBenchmarks.BatchUpdateString.Query(count), pooledConnection);
+         using var updateCommand = new DbCommand(BatchUpdateString.Query(count), pooledConnection);
 
 
-         var ids = PlatformBenchmarks.BatchUpdateString.Ids;
-         var randoms = PlatformBenchmarks.BatchUpdateString.Randoms;
-
-#if !MYSQL
-         var jds = PlatformBenchmarks.BatchUpdateString.Jds;
-#endif      
+         var ids = BatchUpdateString.Ids;
+         var randoms = BatchUpdateString.Randoms;
 
 
          for (int i = 0; i < count; i++)
          for (int i = 0; i < count; i++)
          {
          {
@@ -139,30 +130,36 @@ namespace appMpower
             worlds[i].RandomNumber = randomNumber;
             worlds[i].RandomNumber = randomNumber;
          }
          }
 
 
-#if !MYSQL
-         for (int i = 0; i < count; i++)
+         if (Constants.Dbms != Dbms.MySQL)
          {
          {
-            updateCommand.CreateParameter(jds[i], DbType.Int32, worlds[i].Id);
+            var jds = BatchUpdateString.Jds;
+
+            for (int i = 0; i < count; i++)
+            {
+               updateCommand.CreateParameter(jds[i], DbType.Int32, worlds[i].Id);
+            }
          }
          }
-#endif
 
 
-         await updateCommand.ExecuteNonQueryAsync();
+         updateCommand.ExecuteNonQuery();
 
 
          return worlds;
          return worlds;
       }
       }
 
 
-      private static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommand(DbConnection pooledConnection)
+      internal static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommand(DbConnection pooledConnection)
       {
       {
-#if ADO         
-         var dbCommand = new DbCommand("SELECT * FROM world WHERE id=@Id", pooledConnection);
-#else         
-         var dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection);
-#endif         
+         DbCommand dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection);
 
 
          return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, _random.Next(1, 10001)));
          return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, _random.Next(1, 10001)));
       }
       }
 
 
-      private static async Task<World> ReadSingleRow(DbCommand dbCommand)
+      internal static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommandById(DbConnection pooledConnection, int id)
+      {
+         DbCommand dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection);
+
+         return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, id));
+      }
+
+      internal static async Task<World> ReadSingleRow(DbCommand dbCommand)
       {
       {
          var dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow & CommandBehavior.SequentialAccess);
          var dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow & CommandBehavior.SequentialAccess);
 
 
@@ -182,7 +179,7 @@ namespace appMpower
       public static async Task<World[]> ReadMultipleRows(int count)
       public static async Task<World[]> ReadMultipleRows(int count)
       {
       {
          int j = 0;
          int j = 0;
-         var ids = PlatformBenchmarks.BatchUpdateString.Ids;
+         var ids = BatchUpdateString.Ids;
          var worlds = new World[count];
          var worlds = new World[count];
          string queryString;
          string queryString;
 
 
@@ -192,14 +189,14 @@ namespace appMpower
          }
          }
          else
          else
          {
          {
-            var stringBuilder = PlatformBenchmarks.StringBuilderCache.Acquire();
+            var stringBuilder = StringBuilderCache.Acquire();
 
 
             for (int i = 0; i < count; i++)
             for (int i = 0; i < count; i++)
             {
             {
                stringBuilder.Append("SELECT * FROM world WHERE id=?;");
                stringBuilder.Append("SELECT * FROM world WHERE id=?;");
             }
             }
 
 
-            queryString = _queriesMultipleRows[count] = PlatformBenchmarks.StringBuilderCache.GetStringAndRelease(stringBuilder);
+            queryString = _queriesMultipleRows[count] = StringBuilderCache.GetStringAndRelease(stringBuilder);
          }
          }
 
 
          using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
          using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
@@ -249,83 +246,5 @@ namespace appMpower
 
 
          return System.Text.Encoding.Default.GetString(values);
          return System.Text.Encoding.Default.GetString(values);
       }
       }
-
-      public static async Task PopulateCache()
-      {
-         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
-         await pooledConnection.OpenAsync();
-
-         var (dbCommand, dbDataParameter) = CreateReadCommand(pooledConnection);
-
-         using (dbCommand)
-         {
-            var cacheKeys = _cacheKeys;
-            var cache = _cache;
-
-            for (var i = 1; i < 10001; i++)
-            {
-               dbDataParameter.Value = i;
-               cache.Set<CachedWorld>(cacheKeys[i], await ReadSingleRow(dbCommand));
-            }
-         }
-      }
-
-      public static Task<CachedWorld[]> LoadCachedQueries(int count)
-      {
-         var result = new CachedWorld[count];
-         var cacheKeys = _cacheKeys;
-         var cache = _cache;
-         var random = _random;
-
-         for (var i = 0; i < result.Length; i++)
-         {
-            var id = random.Next(1, 10001);
-            var key = cacheKeys[id];
-
-            if (cache.TryGetValue(key, out object cached))
-            {
-               result[i] = (CachedWorld)cached;
-            }
-            else
-            {
-               //return LoadUncachedQueries(id, i, count, this, result);
-               return LoadUncachedQueries(id, i, count, result);
-            }
-         }
-
-         return Task.FromResult(result);
-      }
-
-      static async Task<CachedWorld[]> LoadUncachedQueries(int id, int i, int count, CachedWorld[] result)
-      {
-         using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString);
-         await pooledConnection.OpenAsync();
-
-         var (dbCommand, dbDataParameter) = CreateReadCommand(pooledConnection);
-
-         using (dbCommand)
-         {
-            Func<ICacheEntry, Task<CachedWorld>> create = async (entry) =>
-            {
-               return await ReadSingleRow(dbCommand);
-            };
-
-            var cacheKeys = _cacheKeys;
-            var key = cacheKeys[id];
-
-            dbDataParameter.Value = id;
-
-            for (; i < result.Length; i++)
-            {
-               result[i] = await _cache.GetOrCreateAsync<CachedWorld>(key, create);
-
-               id = _random.Next(1, 10001);
-               dbDataParameter.Value = id;
-               key = cacheKeys[id];
-            }
-         }
-
-         return result;
-      }
    }
    }
 }
 }

Some files were not shown because too many files changed in this diff