From af1d5bd90e9d665f861f45e43ead2186945e5d57 Mon Sep 17 00:00:00 2001 From: ubuntu14 Date: Fri, 5 Feb 2016 10:10:24 +0800 Subject: [PATCH] improving performance and fixed some bugs --- acl_cpp_vc2012.sln | 66 ++ app/net_tools/mail/mime_builder.cpp | 10 +- app/wizard_demo/Makefile | 2 + app/wizard_demo/httpd_upload/Makefile | 5 + app/wizard_demo/httpd_upload/Makefile.in | 116 +++ app/wizard_demo/httpd_upload/http_servlet.cpp | 358 ++++++++ app/wizard_demo/httpd_upload/http_servlet.h | 49 ++ app/wizard_demo/httpd_upload/httpd_upload.cf | 136 +++ app/wizard_demo/httpd_upload/httpd_upload.sln | 27 + .../httpd_upload/httpd_upload.vcproj | 289 +++++++ .../httpd_upload/httpd_upload_vc2008.sln | 25 + .../httpd_upload/httpd_upload_vc2008.vcproj | 425 ++++++++++ .../httpd_upload/httpd_upload_vc2010.sln | 25 + .../httpd_upload/httpd_upload_vc2010.vcxproj | 202 +++++ .../httpd_upload_vc2010.vcxproj.filters | 45 + .../httpd_upload/httpd_upload_vc2012.sln | 37 + .../httpd_upload/httpd_upload_vc2012.vcxproj | 365 ++++++++ .../httpd_upload_vc2012.vcxproj.filters | 45 + app/wizard_demo/httpd_upload/main.cpp | 77 ++ .../httpd_upload/master_service.cpp | 129 +++ app/wizard_demo/httpd_upload/master_service.h | 94 +++ app/wizard_demo/httpd_upload/stdafx.cpp | 8 + app/wizard_demo/httpd_upload/stdafx.h | 19 + app/wizard_demo/httpd_upload/upload.html | 18 + app/wizard_demo/httpd_upload/valgrind.sh | 3 + lib_acl/changes.txt | 10 + lib_acl/include/stdlib/acl_define_unix.h | 2 + lib_acl/include/stdlib/acl_vbuf.h | 32 +- lib_acl/include/stdlib/acl_vstring.h | 28 +- lib_acl/include/xml/acl_xml2.h | 82 +- lib_acl/lib_acl_vc2012.vcxproj | 3 +- lib_acl/lib_acl_vc2012.vcxproj.filters | 5 +- lib_acl/samples/mmap_string/Makefile | 2 + lib_acl/samples/mmap_string/main.c | 110 +++ lib_acl/samples/mmap_string/valgrind.sh | 3 + lib_acl/samples/xml/xml3/test.sh | 11 + lib_acl/samples/xml/xml3/xml.c | 142 +++- lib_acl/samples/xml/xml3/xml.c.new | 778 ++++++++++++++++++ lib_acl/samples/xml/xml7/xml.c | 7 +- lib_acl/src/event/events_epoll_thr.c | 186 +++-- lib_acl/src/stdlib/acl_vstream.c | 8 +- lib_acl/src/stdlib/acl_vstring.c | 336 ++++++-- lib_acl/src/stdlib/memory/vstring_pool.c | 6 +- lib_acl/src/xml/acl_xml2.c | 233 ++---- lib_acl/src/xml/acl_xml2_parse.c | 502 +++++------ lib_acl/src/xml/acl_xml2_util.c | 296 ++----- lib_acl_cpp/changes.txt | 17 + .../include/acl_cpp/http/HttpCookie.hpp | 29 +- .../include/acl_cpp/http/HttpServlet.hpp | 25 +- .../acl_cpp/http/HttpServletRequest.hpp | 10 +- .../acl_cpp/http/HttpServletResponse.hpp | 10 +- .../include/acl_cpp/http/HttpSession.hpp | 3 +- .../include/acl_cpp/http/http_header.hpp | 20 +- .../include/acl_cpp/http/http_mime.hpp | 11 +- .../include/acl_cpp/session/session.hpp | 3 +- .../include/acl_cpp/stdlib/dbuf_pool.hpp | 6 +- lib_acl_cpp/include/acl_cpp/stdlib/json.hpp | 5 +- lib_acl_cpp/include/acl_cpp/stdlib/string.hpp | 11 + lib_acl_cpp/include/acl_cpp/stdlib/xml.hpp | 11 +- lib_acl_cpp/include/acl_cpp/stdlib/xml1.hpp | 1 + lib_acl_cpp/include/acl_cpp/stdlib/xml2.hpp | 41 +- lib_acl_cpp/samples/mime/mime/mime.cpp | 6 +- lib_acl_cpp/samples/mime/mime/test.sh | 124 +++ lib_acl_cpp/samples/rfc2047/main.cpp | 3 + lib_acl_cpp/samples/string/Makefile | 4 + lib_acl_cpp/samples/string/string5/Makefile | 3 + lib_acl_cpp/samples/string/string5/main.cpp | 120 +++ .../samples/string/string5/valgrind.sh | 3 + lib_acl_cpp/src/connpool/connect_manager.cpp | 12 + lib_acl_cpp/src/http/HttpCookie.cpp | 18 +- lib_acl_cpp/src/http/HttpServlet.cpp | 95 +-- lib_acl_cpp/src/http/HttpServletRequest.cpp | 87 +- lib_acl_cpp/src/http/HttpServletResponse.cpp | 24 +- lib_acl_cpp/src/http/http_header.cpp | 26 +- lib_acl_cpp/src/http/http_mime.cpp | 12 +- lib_acl_cpp/src/mime/internal/mime_state.cpp | 15 + lib_acl_cpp/src/mime/internal/mime_state.hpp | 5 + .../src/mime/internal/mime_state_parse.cpp | 113 +++ lib_acl_cpp/src/mime/mime.cpp | 16 +- lib_acl_cpp/src/stdlib/charset_conv.cpp | 6 +- lib_acl_cpp/src/stdlib/string.cpp | 18 + lib_acl_cpp/src/stdlib/xml.cpp | 16 +- lib_acl_cpp/src/stdlib/xml1.cpp | 59 +- lib_acl_cpp/src/stdlib/xml2.cpp | 117 +-- lib_acl_cpp/src/stream/istream.cpp | 5 +- 85 files changed, 5134 insertions(+), 1333 deletions(-) create mode 100644 app/wizard_demo/httpd_upload/Makefile create mode 100644 app/wizard_demo/httpd_upload/Makefile.in create mode 100644 app/wizard_demo/httpd_upload/http_servlet.cpp create mode 100644 app/wizard_demo/httpd_upload/http_servlet.h create mode 100644 app/wizard_demo/httpd_upload/httpd_upload.cf create mode 100644 app/wizard_demo/httpd_upload/httpd_upload.sln create mode 100644 app/wizard_demo/httpd_upload/httpd_upload.vcproj create mode 100644 app/wizard_demo/httpd_upload/httpd_upload_vc2008.sln create mode 100644 app/wizard_demo/httpd_upload/httpd_upload_vc2008.vcproj create mode 100644 app/wizard_demo/httpd_upload/httpd_upload_vc2010.sln create mode 100644 app/wizard_demo/httpd_upload/httpd_upload_vc2010.vcxproj create mode 100644 app/wizard_demo/httpd_upload/httpd_upload_vc2010.vcxproj.filters create mode 100644 app/wizard_demo/httpd_upload/httpd_upload_vc2012.sln create mode 100644 app/wizard_demo/httpd_upload/httpd_upload_vc2012.vcxproj create mode 100644 app/wizard_demo/httpd_upload/httpd_upload_vc2012.vcxproj.filters create mode 100644 app/wizard_demo/httpd_upload/main.cpp create mode 100644 app/wizard_demo/httpd_upload/master_service.cpp create mode 100644 app/wizard_demo/httpd_upload/master_service.h create mode 100644 app/wizard_demo/httpd_upload/stdafx.cpp create mode 100644 app/wizard_demo/httpd_upload/stdafx.h create mode 100644 app/wizard_demo/httpd_upload/upload.html create mode 100644 app/wizard_demo/httpd_upload/valgrind.sh create mode 100644 lib_acl/samples/mmap_string/Makefile create mode 100644 lib_acl/samples/mmap_string/main.c create mode 100644 lib_acl/samples/mmap_string/valgrind.sh create mode 100644 lib_acl/samples/xml/xml3/test.sh create mode 100644 lib_acl/samples/xml/xml3/xml.c.new create mode 100644 lib_acl_cpp/samples/mime/mime/test.sh create mode 100644 lib_acl_cpp/samples/string/string5/Makefile create mode 100644 lib_acl_cpp/samples/string/string5/main.cpp create mode 100644 lib_acl_cpp/samples/string/string5/valgrind.sh diff --git a/acl_cpp_vc2012.sln b/acl_cpp_vc2012.sln index 9c05f11d3..2479ddb13 100644 --- a/acl_cpp_vc2012.sln +++ b/acl_cpp_vc2012.sln @@ -690,6 +690,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "json12", "lib_acl_cpp\sampl {FE724EF7-3763-4E78-BDF5-BCBC075719FD} = {FE724EF7-3763-4E78-BDF5-BCBC075719FD} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net_tools", "app\net_tools\net_tools_vc2012.vcxproj", "{45276293-D169-4D73-8930-F255C09DA976}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpd_upload", "app\wizard_demo\httpd_upload\httpd_upload_vc2012.vcxproj", "{4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}" + ProjectSection(ProjectDependencies) = postProject + {6EC1F44E-6A6A-48E9-B699-D7E89B63C8DC} = {6EC1F44E-6A6A-48E9-B699-D7E89B63C8DC} + {B40213C2-507C-4C7F-A6E1-B850C9BDC27B} = {B40213C2-507C-4C7F-A6E1-B850C9BDC27B} + {FE724EF7-3763-4E78-BDF5-BCBC075719FD} = {FE724EF7-3763-4E78-BDF5-BCBC075719FD} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mixed Platforms = Debug|Mixed Platforms @@ -3314,6 +3323,61 @@ Global {20299269-7A1C-45CB-8807-861745A55F82}.Template|Win32.Build.0 = DebugDll|Win32 {20299269-7A1C-45CB-8807-861745A55F82}.Template|x64.ActiveCfg = DebugDll|x64 {20299269-7A1C-45CB-8807-861745A55F82}.Template|x64.Build.0 = DebugDll|x64 + {45276293-D169-4D73-8930-F255C09DA976}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Debug|Win32.ActiveCfg = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Debug|Win32.Build.0 = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Debug|x64.ActiveCfg = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.DebugDll|Mixed Platforms.ActiveCfg = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.DebugDll|Mixed Platforms.Build.0 = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.DebugDll|Win32.ActiveCfg = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.DebugDll|Win32.Build.0 = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.DebugDll|x64.ActiveCfg = Debug|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Release|Mixed Platforms.Build.0 = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Release|Win32.ActiveCfg = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Release|Win32.Build.0 = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Release|x64.ActiveCfg = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Releasedll|Mixed Platforms.ActiveCfg = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Releasedll|Mixed Platforms.Build.0 = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Releasedll|Win32.ActiveCfg = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Releasedll|Win32.Build.0 = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Releasedll|x64.ActiveCfg = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Template|Mixed Platforms.ActiveCfg = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Template|Mixed Platforms.Build.0 = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Template|Win32.ActiveCfg = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Template|Win32.Build.0 = Release|Win32 + {45276293-D169-4D73-8930-F255C09DA976}.Template|x64.ActiveCfg = Release|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Debug|Win32.ActiveCfg = Debug|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Debug|Win32.Build.0 = Debug|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Debug|x64.ActiveCfg = Debug|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Debug|x64.Build.0 = Debug|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.DebugDll|Mixed Platforms.ActiveCfg = DebugDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.DebugDll|Mixed Platforms.Build.0 = DebugDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.DebugDll|Win32.ActiveCfg = DebugDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.DebugDll|Win32.Build.0 = DebugDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.DebugDll|x64.ActiveCfg = DebugDll|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.DebugDll|x64.Build.0 = DebugDll|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Release|Mixed Platforms.Build.0 = Release|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Release|Win32.ActiveCfg = Release|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Release|Win32.Build.0 = Release|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Release|x64.ActiveCfg = Release|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Release|x64.Build.0 = Release|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Releasedll|Mixed Platforms.ActiveCfg = ReleaseDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Releasedll|Mixed Platforms.Build.0 = ReleaseDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Releasedll|Win32.ActiveCfg = ReleaseDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Releasedll|Win32.Build.0 = ReleaseDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Releasedll|x64.ActiveCfg = ReleaseDll|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Releasedll|x64.Build.0 = ReleaseDll|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Template|Mixed Platforms.ActiveCfg = DebugDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Template|Mixed Platforms.Build.0 = DebugDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Template|Win32.ActiveCfg = DebugDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Template|Win32.Build.0 = DebugDll|Win32 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Template|x64.ActiveCfg = DebugDll|x64 + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F}.Template|x64.Build.0 = DebugDll|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3392,6 +3456,7 @@ Global {84376B60-FF20-4FD0-967E-C568FC2FBC53} = {3CC8D45A-8E3F-4F5C-A7DF-4D8027E4EA9C} {C8535C82-3DCB-472E-9E8F-DA769D9375B1} = {3CC8D45A-8E3F-4F5C-A7DF-4D8027E4EA9C} {1C02A405-3726-4410-80DF-91D60736352B} = {3CC8D45A-8E3F-4F5C-A7DF-4D8027E4EA9C} + {45276293-D169-4D73-8930-F255C09DA976} = {3CC8D45A-8E3F-4F5C-A7DF-4D8027E4EA9C} {3C74E826-5E72-48A1-9DFD-777F4A7C9E1F} = {D232833B-57A9-4167-B37C-A4594953F93D} {B59C7CB6-5708-4522-B833-CEB160AA4817} = {D232833B-57A9-4167-B37C-A4594953F93D} {2DABFAD1-114B-4F96-9185-DC0C56A3662D} = {C799E376-2F01-4877-AF18-7F3CC8B95792} @@ -3420,6 +3485,7 @@ Global {2425D8B1-FE96-4D7F-BDB0-48C932935D96} = {B6BE4E77-F69D-43B0-BE8A-77A8AA61A89E} {AFC106A8-C78A-43C6-BA55-1B7EB541F559} = {B6BE4E77-F69D-43B0-BE8A-77A8AA61A89E} {1A38C49B-F712-4115-980B-6DBD632D25CF} = {1C02A405-3726-4410-80DF-91D60736352B} + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F} = {1C02A405-3726-4410-80DF-91D60736352B} {B2FAA9AA-0F95-4EAC-A95A-B1F8B476F81A} = {3C576B18-D253-4CA2-986E-7173C2978AC3} {ADEF5A5D-403A-4A2B-ACAA-FA022BBCA5C3} = {3C576B18-D253-4CA2-986E-7173C2978AC3} {BEAAA294-B25E-47D2-BF42-C8C833D3D238} = {3C576B18-D253-4CA2-986E-7173C2978AC3} diff --git a/app/net_tools/mail/mime_builder.cpp b/app/net_tools/mail/mime_builder.cpp index 58ead85ff..6090370fb 100644 --- a/app/net_tools/mail/mime_builder.cpp +++ b/app/net_tools/mail/mime_builder.cpp @@ -68,14 +68,16 @@ bool mime_builder::save_as(acl::ofstream& fp) acl::string buf; if (attachs_.empty()) { - header_.set_type(MIME_CTYPE_TEXT, body_html_ ? - MIME_STYPE_HTML : MIME_STYPE_PLAIN); + //header_.set_type(MIME_CTYPE_TEXT, body_html_ ? + // MIME_STYPE_HTML : MIME_STYPE_PLAIN); + header_.set_type("text", body_html_ ? "html" : "plain"); header_.add_header("Content-Transfer-Encoding", "base64"); } else { - header_.set_type(MIME_CTYPE_MULTIPART, - MIME_STYPE_MIXED); + //header_.set_type(MIME_CTYPE_MULTIPART, + // MIME_STYPE_MIXED); + header_.set_type("multipart", "mixed"); delimeter_.format("------=_Part_%d_%ld.%ld", getpid(), acl_pthread_self(), time(NULL)); header_.set_boundary(delimeter_.c_str()); diff --git a/app/wizard_demo/Makefile b/app/wizard_demo/Makefile index 109425d3a..0df74ca77 100644 --- a/app/wizard_demo/Makefile +++ b/app/wizard_demo/Makefile @@ -1,8 +1,10 @@ .PHONY = all clean all: + @(cd httpd_upload; make) @(cd httpd_download; make) clean: + @(cd httpd_upload; make clean) @(cd httpd_download; make clean) rb rebuild: clean all diff --git a/app/wizard_demo/httpd_upload/Makefile b/app/wizard_demo/httpd_upload/Makefile new file mode 100644 index 000000000..d595bc00d --- /dev/null +++ b/app/wizard_demo/httpd_upload/Makefile @@ -0,0 +1,5 @@ +include ./Makefile.in +ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD) + EXTLIBS += -L/usr/local/lib -liconv +endif +PROG = httpd_upload diff --git a/app/wizard_demo/httpd_upload/Makefile.in b/app/wizard_demo/httpd_upload/Makefile.in new file mode 100644 index 000000000..249f31f43 --- /dev/null +++ b/app/wizard_demo/httpd_upload/Makefile.in @@ -0,0 +1,116 @@ +CC = g++ + +CFLAGS = -c -g -W -Wall -Wcast-qual -Wcast-align \ +-Waggregate-return -Wno-long-long \ +-Wpointer-arith -Werror -Wshadow -O3 \ +-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D_USE_FAST_MACRO + +########################################################### +#Check system: +# Linux, SunOS, Solaris, BSD variants, AIX, HP-UX +SYSLIB = -lpthread -lz +CHECKSYSRES = @echo "Unknow system type!";exit 1 +UNIXNAME = $(shell uname -sm) +OSTYPE = $(shell uname -p) +RPATH = linux64 + +ifeq ($(CC),) + CC = gcc +endif + +# For FreeBSD +ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD) + ifeq ($(findstring gcc, $(CC)), gcc) + CFLAGS += -Wstrict-prototypes + endif + CFLAGS += -DFREEBSD -D_REENTRANT + SYSLIB = -lcrypt -lpthread -lz + RPATH = freebsd +endif + +# For Darwin +ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin) + CFLAGS += -DMACOSX -Wno-invalid-source-encoding \ + -Wno-extended-offsetof + UNIXTYPE = MACOSX + SYSLIB += -liconv -rdynamic + RPATH = macos +endif + +#Path for Linux +ifeq ($(findstring Linux, $(UNIXNAME)), Linux) + ifeq ($CC, "gcc") + CFLAGS += -Wstrict-prototypes + endif + ifeq ($(findstring i686, $(OSTYPE)), i686) + RPATH = linux32 + endif + ifeq ($(findstring x86_64, $(OSTYPE)), x86_64) + RPATH = linux64 + endif + CFLAGS += -DLINUX2 -D_REENTRANT + SYSLIB += -lcrypt +endif + +#Path for SunOS +ifeq ($(findstring SunOS, $(UNIXNAME)), SunOS) + ifeq ($(findstring 86, $(UNIXNAME)), 86) + SYSLIB += -lsocket -lnsl -lrt + endif + ifeq ($(findstring sun4u, $(UNIXNAME)), sun4u) + SYSLIB += -lsocket -lnsl -lrt + endif + ifeq ($CC, "gcc") + CFLAGS += -Wstrict-prototypes + endif + CFLAGS += -DSUNOS5 -D_REENTRANT + RPATH = sunos_x86 +endif + +#Path for HP-UX +ifeq ($(findstring HP-UX, $(UNIXNAME)), HP-UX) + ifeq ($CC, "gcc") + CFLAGS += -Wstrict-prototypes + endif + CFLAGS += -DHP_UX -DHPUX11 + PLAT_NAME=hp-ux +endif + +#Find system type. +ifneq ($(SYSPATH),) + CHECKSYSRES = @echo "System is $(shell uname -sm)" +endif +########################################################### + +CFLAGS += -I../../../lib_acl/include -I../../../lib_protocol/include -I../../../lib_acl_cpp/include +EXTLIBS = +LDFLAGS = -L../../../lib_acl_cpp/lib -l_acl_cpp -L../../../lib_protocol/lib -l_protocol -L../../../lib_acl/lib -l_acl \ + $(EXTLIBS) $(SYSLIB) + +COMPILE = $(CC) $(CFLAGS) +LINK = $(CC) $(OBJ) $(LDFLAGS) +########################################################### +OBJ_PATH = . + +#Project's objs +SRC = $(wildcard *.cpp) +OBJ = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(notdir $(SRC))) + +$(OBJ_PATH)/%.o: %.cpp + $(COMPILE) $< -o $@ + +.PHONY = all clean +all: RM $(OBJ) + $(LINK) -o $(PROG) + @echo "" + @echo "All ok! Output:$(PROG)" + @echo "" +RM: + rm -f $(PROG) +clean: + rm -f $(PROG) + rm -f $(OBJ) +install: + cp $(PROG) ../../../dist/master/libexec/$(RPATH)/ + cp $(PROG).cf ../../../dist/master/conf/service/ +########################################################### diff --git a/app/wizard_demo/httpd_upload/http_servlet.cpp b/app/wizard_demo/httpd_upload/http_servlet.cpp new file mode 100644 index 000000000..51be4f1cf --- /dev/null +++ b/app/wizard_demo/httpd_upload/http_servlet.cpp @@ -0,0 +1,358 @@ +#include "stdafx.h" +#include "master_service.h" +#include "http_servlet.h" + +http_servlet::http_servlet(acl::socket_stream* stream, acl::session* session) +: acl::HttpServlet(stream, session) +, read_body_(false) +, req_(NULL) +, res_(NULL) +, content_length_(0) +, read_length_(0) +, mime_(NULL) +{ + +} + +http_servlet::~http_servlet(void) +{ + +} + +bool http_servlet::doError(acl::HttpServletRequest&, + acl::HttpServletResponse& res) +{ + res.setStatus(400); + res.setContentType("text/html; charset="); + // 发送 http 响应头 + if (res.sendHeader() == false) + return false; + + // 发送 http 响应体 + acl::string buf; + buf.format("\r\n"); + (void) res.getOutputStream().write(buf); + return false; +} + +bool http_servlet::doOther(acl::HttpServletRequest&, + acl::HttpServletResponse& res, const char* method) +{ + res.setStatus(400); + res.setContentType("text/html; charset="); + // 发送 http 响应头 + if (res.sendHeader() == false) + return false; + // 发送 http 响应体 + acl::string buf; + buf.format("\r\n", method); + (void) res.getOutputStream().write(buf); + return false; +} + +bool http_servlet::run(void) +{ + if (read_body_ == false) + return doRun(); + else if (req_ == NULL) + { + logger_error("req_ null"); + return false; + } + else if (res_ == NULL) + { + logger_error("res_ null"); + return false; + } + else + return doBody(*req_, *res_); +} + +bool http_servlet::doGet(acl::HttpServletRequest& req, + acl::HttpServletResponse& res) +{ + return doPost(req, res); +} + +bool http_servlet::doPost(acl::HttpServletRequest& req, + acl::HttpServletResponse& res) +{ + res.setContentType("text/xml; charset=gbk") // 设置响应字符集 + .setKeepAlive(req.isKeepAlive()) // 设置是否保持长连接 + .setContentEncoding(true) // 自动支持压缩传输 + .setChunkedTransferEncoding(true); // 采用 chunk 传输方式 + + // 获得 HTTP 请求的数据类型,正常的参数类型,即 name&value 方式 + // 还是 MIME 数据类型,还是数据流类型 + acl::http_request_t request_type = req.getRequestType(); + if (request_type != acl::HTTP_REQUEST_MULTIPART_FORM) + { + acl::string buf; + buf.format("\r\n"); + (void) res.write(buf); + (void) res.write(NULL, 0); + return false; + } + + // 先获得 Content-Type 对应的 http_ctype 对象 + mime_ = req.getHttpMime(); + if (mime_ == NULL) + { + logger_error("http_mime null"); + (void) doReply(req, res, "http_mime null"); + return false; + } + + // 获得数据体的长度 + content_length_ = req.getContentLength(); + if (content_length_ <= 0) + { + logger_error("body empty"); + (void) doReply(req, res, "body empty"); + return false; + } + + acl::string filepath; +#if defined(_WIN32) || defined(_WIN64) + filepath.format("%s\\mime_file", var_cfg_var_path); +#else + filepath.format("%s/mime_file", var_cfg_var_path); +#endif + + if (fp_.open_write(filepath) == false) + { + logger_error("open %s error %s", + filepath.c_str(), acl::last_serror()); + (void) doReply(req, res, "open file error"); + return false; + } + + // 设置原始文件存入路径 + mime_->set_saved_path(filepath); + + req_ = &req; + res_ = &res; + read_body_ = true; + + // 直接返回,从而触发异步读 HTTP 数据体过程 + return true; +} + +void http_servlet::reset(void) +{ + read_body_ = false; + req_ = NULL; + res_ = NULL; + content_length_ = 0; + read_length_ = 0; + mime_ = NULL; + fp_.close(); +} + +bool http_servlet::doBody(acl::HttpServletRequest& req, + acl::HttpServletResponse& res) +{ + // 当未读完数据体时,需要异步读 HTTP 请求数据体 + if (content_length_ > read_length_) + { + if (doUpload(req, res) == false) + return false; + } + + if (content_length_ > read_length_) + return true; + + // 当已经读完 HTTP 请求数据体时,则开始分析上传的数据 + bool ret = doParse(req, res); + + // 处理完毕,需重置 HTTP 会话状态,以便于处理下一个 HTTP 请求 + reset(); + return ret; +} + +bool http_servlet::doUpload(acl::HttpServletRequest& req, + acl::HttpServletResponse& res) +{ + // 获得输入流 + acl::istream& in = req.getInputStream(); + acl::string buf; + bool finish = false; + + //logger(">>>>>>>>>>read: %lld, total: %lld<<<<<", + // read_length_, content_length_); + + // 读取 HTTP 客户端请求数据 + while (content_length_ > read_length_) + { + if (in.read_peek(buf, true) == false) + break; + //if (buf.empty()) + // break; +// printf(">>>size: %ld, space: %ld\r\n", +// (long) buf.size(), (long) buf.capacity()); + + if (fp_.write(buf) == -1) + { + logger_error("write error %s", acl::last_serror()); + (void) doReply(req, res, "write error"); + return false; + } + + read_length_ += buf.size(); + + // 将读得到的数据输入至解析器进行解析 + if (!finish && mime_->update(buf, buf.size()) == true) + finish = true; + } + + if (in.eof()) + { + logger_error("read error"); + return false; + } + + return true; +} + +bool http_servlet::doParse(acl::HttpServletRequest& req, + acl::HttpServletResponse& res) +{ + const char* ptr = req.getParameter("name1"); + if (ptr) + param1_ = ptr; + ptr = req.getParameter("name2"); + if (ptr) + param2_ = ptr; + ptr = req.getParameter("name3"); + if (ptr) + param3_ = ptr; + + acl::string path; + + // 遍历所有的 MIME 结点,找出其中为文件结点的部分进行转储 + const std::list& nodes = mime_->get_nodes(); + std::list::const_iterator cit = nodes.begin(); + for (; cit != nodes.end(); ++cit) + { + const char* name = (*cit)->get_name(); + if (name == NULL) + continue; + + acl::http_mime_t mime_type = (*cit)->get_mime_type(); + if (mime_type == acl::HTTP_MIME_FILE) + { + const char* filename = (*cit)->get_filename(); + if (filename == NULL) + { + logger("filename null"); + continue; + } + + // 有的浏览器(如IE)上传文件时会带着文件路径,所以 + // 需要先将路径去掉 + filename = acl_safe_basename(filename); +#if defined(_WIN32) || defined(_WIN64) + path.format("%s\\%s", var_cfg_var_path, filename); +#else + path.format("%s/%s", var_cfg_var_path, filename); +#endif + (void) (*cit)->save(path.c_str()); + + if (strcmp(name, "file1") == 0) + { + file1_ = filename; + fsize1_ = get_fsize(var_cfg_var_path, filename); + } + else if (strcmp(name, "file2") == 0) + { + file2_ = filename; + fsize2_ = get_fsize(var_cfg_var_path, filename); + } + else if (strcmp(name, "file3") == 0) + { + file3_ = filename; + fsize3_ = get_fsize(var_cfg_var_path, filename); + } + } + } + + // 查找上载的某个文件并转储 + const acl::http_mime_node* node = mime_->get_node("file1"); + if (node && node->get_mime_type() == acl::HTTP_MIME_FILE) + { + ptr = node->get_filename(); + if (ptr) + { + // 有的浏览器(如IE)上传文件时会带着文件路径,所以 + // 需要先将路径去掉 + ptr = acl_safe_basename(ptr); +#if defined(_WIN32) || defined(_WIN64) + path.format("%s\\1_%s", var_cfg_var_path, ptr); +#else + path.format("%s/1_%s", var_cfg_var_path, ptr); +#endif + (void) node->save(path.c_str()); + } + } + + return doReply(req, res, "OK"); +} + +bool http_servlet::doReply(acl::HttpServletRequest& req, + acl::HttpServletResponse& res, const char* info) +{ + // 创建 xml 格式的数据体 + acl::xml1 body; + + body.get_root().add_child("root", true) + .add_child("content_type", true) + .add_attr("type", (int) req.getRequestType()) + .get_parent() + .add_child("info", true) + .set_text(info) + .get_parent() + .add_child("params", true) + .add_child("param", true) + .add_attr("name1", param1_) + .get_parent() + .add_child("param", true) + .add_attr("name2", param2_) + .get_parent() + .add_child("param", true) + .add_attr("name3", param3_) + .get_parent() + .add_child("files", true) + .add_child("file", true) + .add_attr("filename", file1_) + .add_attr("fsize", fsize1_) + .get_parent() + .add_child("file", true) + .add_attr("filename", file2_) + .add_attr("fsize", fsize2_) + .get_parent() + .add_child("file", true) + .add_attr("filename", file3_) + .add_attr("fsize", fsize3_); + acl::string buf; + body.build_xml(buf); + + logger(">>%s<<", buf.c_str()); + return res.write(buf) && res.write(NULL, 0); +} + +long long http_servlet::get_fsize(const char* dir, const char* filename) +{ + acl::string path; +#if defined(_WIN32) || defined(_WIN64) + path.format("%s\\%s", dir, filename); +#else + path.format("%s/%s", dir, filename); +#endif + acl::ifstream in; + if (in.open_read(path) == false) + { + logger_error("open %s error %s", path.c_str(), acl::last_serror()); + return -1; + } + return in.fsize(); +} diff --git a/app/wizard_demo/httpd_upload/http_servlet.h b/app/wizard_demo/httpd_upload/http_servlet.h new file mode 100644 index 000000000..6753e5bf8 --- /dev/null +++ b/app/wizard_demo/httpd_upload/http_servlet.h @@ -0,0 +1,49 @@ +#pragma once + +class http_servlet : public acl::HttpServlet +{ +public: + http_servlet(acl::socket_stream* stream, acl::session* session); + ~http_servlet(); + + bool run(void); + +protected: + virtual bool doError(acl::HttpServletRequest&, + acl::HttpServletResponse& res); + virtual bool doOther(acl::HttpServletRequest&, + acl::HttpServletResponse& res, const char* method); + virtual bool doGet(acl::HttpServletRequest& req, + acl::HttpServletResponse& res); + virtual bool doPost(acl::HttpServletRequest& req, + acl::HttpServletResponse& res); + +private: + bool doBody(acl::HttpServletRequest&, acl::HttpServletResponse&); + bool doUpload(acl::HttpServletRequest&, acl::HttpServletResponse&); + bool doParse(acl::HttpServletRequest&, acl::HttpServletResponse&); + bool doReply(acl::HttpServletRequest&, acl::HttpServletResponse&, + const char* info); + void reset(void); + + long long get_fsize(const char* dir, const char* filename); + +private: + bool read_body_; + acl::HttpServletRequest* req_; + acl::HttpServletResponse* res_; + acl::ofstream fp_; + long long content_length_; + long long read_length_; + acl::http_mime* mime_; + + acl::string param1_; + acl::string param2_; + acl::string param3_; + acl::string file1_; + acl::string file2_; + acl::string file3_; + long long fsize1_; + long long fsize2_; + long long fsize3_; +}; diff --git a/app/wizard_demo/httpd_upload/httpd_upload.cf b/app/wizard_demo/httpd_upload/httpd_upload.cf new file mode 100644 index 000000000..3ac63f107 --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload.cf @@ -0,0 +1,136 @@ + +service httpd_upload { +# 进程是否禁止运行 + master_disable = no +# 服务地址及端口号 +# for master_type = inet +# master_service = 127.0.0.1:5001 +# for master_type = unix +# master_service = echo.sock +# for master_type = sock + master_service = 127.0.0.1:5001, 5002, :5003, echo.sock, echo2.sock + +# 服务监听为域套接口 +# master_service = aio_echo.sock +# 服务类型 +# master_type = inet +# master_type = unix + master_type = sock + +# 当子进程异常退出时,如果该值非空,则将子进程异常退出的消息通知该服务 +# master_notify_addr = 127.0.0.1:5801 +# 邮件通知接收者 +# master_notify_recipients = zhengshuxin@hotmail.com + +# 是否允许延迟接受客户端连接,如果为0则表示关闭该功能,如果大于0则表示打开此功能 +# 并且此值代表延迟接受连接的超时值,超过此值时如果客户端依然没有发来数据,则操作 +# 系统会在系统层直接关闭该连接 +# master_defer_accept = 0 +# 是否只允许私有访问, 如果为 y, 则域套接口创建在 {install_path}/var/log/private/ 目录下, +# 如果为 n, 则域套接口创建在 {install_path}/var/log/public/ 目录下, + master_private = n + master_unpriv = n +# 是否需要 chroot: n -- no, y -- yes + master_chroot = n +# 每隔多长时间触发一次,单位为秒(仅对 trigger 模式有效) + master_wakeup = - +# 最大进程数 + master_maxproc = 1 +# 预启动进程数,该值不得大于 master_maxproc +# master_prefork = 0 +# 进程程序名 + master_command = httpd_upload +# 进程日志记录文件 + master_log = {install_path}/var/log/httpd_upload +# 调试日志方式,格式:tag:level; tag:level; tab:level, 如:all:1; 101:2 +# master_debug = +# 进程启动参数,只能为: -u [是否允许以某普通用户的身份运行] +# master_args = +# 传递给服务子进程的环境变量, 可以通过 getenv("SERVICE_ENV") 获得此值 +# master_env = mempool_limit:512000000 +# master_env = logme:FALSE, priority:E_LOG_INFO, action:E_LOG_PER_DAY, flush:sync_flush, imit_size:512,\ +# sync_action:E_LOG_SEM, sem_name:/tmp/ioctl_echo.sem + +# 当启动多个子进程实例时,该开关控制多个子进程在接收连接时是否向 acl_master 发送消息报告自己的状态 +# master_status_notify = 1 +# 是否允许产生 core 文件 +# ioctl_enable_core = 1 +# 每个进程实例处理连接数的最大次数,超过此值后进程实例主动退出 + ioctl_use_limit = 100 +# 每个进程实例的空闲超时时间,超过此值后进程实例主动退出 + ioctl_idle_limit = 120 +# 记录进程PID的位置(对于多进程实例来说没有意义) + ioctl_pid_dir = {install_path}/var/pid +# 进程运行时所在的路径 + ioctl_queue_dir = {install_path}/var +# 读写超时时间, 单位为秒 + ioctl_rw_timeout = 120 +# 读缓冲区的缓冲区大小 + ioctl_buf_size = 8192 +# 每次 accept 时的循环接收的最大次数 + ioctl_max_accept = 25 +# 在并发访问量非常低的情况下,如访问量在 10 次/秒 以下时,可以找开此值(即赋为1), +# 以加速事件循环过程, 从而防止服务进程阻塞在 select 上的时间过长而影响访问速度 +# ioctl_enable_dog = 1 +# 进程运行时的用户身份 + ioctl_owner = root + +# 用 select 进行循环时的时间间隔 +# 单位为秒 + ioctl_delay_sec = 1 +# 单位为微秒 + ioctl_delay_usec = 500 + +# 采用事件循环的方式: select(default), poll, kernel(epoll/devpoll/kqueue) + ioctl_event_mode = kernel +# 事件引擎检查所有空闲描述符的时间间隔(毫秒) +# ioctl_check_inter = 100 +# 当启用 master_dispatch 连接分开服务后,该配置指定 master_dispatch 所监听的 +# 域套接口的全路径,这样本子进程就可以从 master_dispatch 获得客户端连接 +# ioctl_dispatch_addr = {install_path}/var/private/dispatch.sock +# 当 ioctl_dispatch_addr 开启后,下面参数控制本服务进程发给前端 master_dispatch 的服务标识信息 +# ioctl_dispatch_type = default + +# 线程池的最大线程数 + ioctl_max_threads = 250 +# 线程池中工作线程等待任务时间间隔(毫秒) +# ioctl_schedule_wait = 50 +# 线程任务调度的时间间隔大于此值(毫秒)后记警告日志 +# ioctl_schedule_warn = 100 +# 线程处理任务拥堵数超过此阀值后记警告日志,设为 0 则内部只有当拥堵任务数超过总线程数的 10 倍时才报警 +# ioctl_qlen_warn = 0 +# 线程的堆栈空间大小,单位为字节,0表示使用系统缺省值 + ioctl_stacksize = 0 +# 允许访问 udserver 的客户端IP地址范围 +# ioctl_access_allow = 127.0.0.1:255.255.255.255, 127.0.0.1:127.0.0.1 + ioctl_access_allow = all + +# 当 acl_master 退出时,如果该值置1则该程序不等所有连接处理完毕便立即退出 + ioctl_quick_abort = 1 + +############################################################################ +# 应用自己的配置选项 + +# mysql 服务地址 +# mysql_dbaddr = /tmp/mysql.sock +# mysql_dbaddr = 10.0.250.199:3306 +# 连接 mysql 数据库的连接池的最大值 +# mysql_dbmax = 200 +# ping mysql 连接的间隔时间, 以秒为单位 +# mysql_dbping = 10 +# mysql 连接空闲的时间间隔, 以秒为单位 +# mysql_dbtimeout = 30 + +# 数据库名称 +# mysql_dbname = ioctl_db +# 数据库访问用户 +# mysql_dbuser = ioctl_user +# 数据库用户访问密码 +# mysql_dbpass = 111111 + +# 是否输出当前内存的状态信息 +# debug_mem = 1 +# 是否在一个线程中连接读 +# loop_read = 1 +} + diff --git a/app/wizard_demo/httpd_upload/httpd_upload.sln b/app/wizard_demo/httpd_upload/httpd_upload.sln new file mode 100644 index 000000000..dab521f08 --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload.sln @@ -0,0 +1,27 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpd_upload", "httpd_upload.vcproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + DebugDll = DebugDll + Release = Release + ReleaseDll = ReleaseDll + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug.ActiveCfg = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug.Build.0 = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll.ActiveCfg = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll.Build.0 = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release.ActiveCfg = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release.Build.0 = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll.ActiveCfg = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll.Build.0 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/app/wizard_demo/httpd_upload/httpd_upload.vcproj b/app/wizard_demo/httpd_upload/httpd_upload.vcproj new file mode 100644 index 000000000..e023f4b5d --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload.vcproj @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/wizard_demo/httpd_upload/httpd_upload_vc2008.sln b/app/wizard_demo/httpd_upload/httpd_upload_vc2008.sln new file mode 100644 index 000000000..a30a31776 --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload_vc2008.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpd_upload", "httpd_upload_vc2008.vcproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + DebugDll|Win32 = DebugDll|Win32 + Release|Win32 = Release|Win32 + ReleaseDll|Win32 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.ActiveCfg = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.Build.0 = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.ActiveCfg = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.Build.0 = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.ActiveCfg = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.Build.0 = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.ActiveCfg = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.Build.0 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/app/wizard_demo/httpd_upload/httpd_upload_vc2008.vcproj b/app/wizard_demo/httpd_upload/httpd_upload_vc2008.vcproj new file mode 100644 index 000000000..330781e7a --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload_vc2008.vcproj @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/wizard_demo/httpd_upload/httpd_upload_vc2010.sln b/app/wizard_demo/httpd_upload/httpd_upload_vc2010.sln new file mode 100644 index 000000000..e656282e2 --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload_vc2010.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpd_upload", "httpd_upload_vc2010.vcxproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + DebugDll|Win32 = DebugDll|Win32 + Release|Win32 = Release|Win32 + ReleaseDll|Win32 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.ActiveCfg = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.Build.0 = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.ActiveCfg = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.Build.0 = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.ActiveCfg = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.Build.0 = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.ActiveCfg = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.Build.0 = ReleaseDll|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/app/wizard_demo/httpd_upload/httpd_upload_vc2010.vcxproj b/app/wizard_demo/httpd_upload/httpd_upload_vc2010.vcxproj new file mode 100644 index 000000000..2051fb43c --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload_vc2010.vcxproj @@ -0,0 +1,202 @@ +锘 + + + + DebugDll + Win32 + + + Debug + Win32 + + + ReleaseDll + Win32 + + + Release + Win32 + + + + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C} + Win32Proj + httpd_upload + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + true + Release\ + Release\ + false + $(Configuration)\ + $(Configuration)\ + false + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Use + Level3 + EditAndContinue + + + lib_acl_cpp_vc2010d.lib;lib_acl_vc2010d.lib;lib_protocol_vc2010d.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + $(OutDir)httpd_upload.pdb + Console + MachineX86 + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_vc2010.lib;lib_acl_vc2010.lib;lib_protocol_vc2010.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + MultiThreadedDLL + Use + Level3 + ProgramDatabase + + + lib_acl_cpp.lib;lib_acl.lib;lib_protocol.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + copy ..\..\..\dist\lib\win32\lib_acl.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_protocol.dll $(OutDir) /Y + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + lib_acl_cpp_d.lib;lib_acl_d.lib;lib_protocol_d.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + $(OutDir)httpd_upload.pdb + Console + MachineX86 + + + copy ..\..\..\dist\lib\win32\lib_acl_d.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_protocol_d.dll $(OutDir) /Y + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + diff --git a/app/wizard_demo/httpd_upload/httpd_upload_vc2010.vcxproj.filters b/app/wizard_demo/httpd_upload/httpd_upload_vc2010.vcxproj.filters new file mode 100644 index 000000000..043c20e3b --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload_vc2010.vcxproj.filters @@ -0,0 +1,45 @@ +锘 + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + + + + \ No newline at end of file diff --git a/app/wizard_demo/httpd_upload/httpd_upload_vc2012.sln b/app/wizard_demo/httpd_upload/httpd_upload_vc2012.sln new file mode 100644 index 000000000..ce756d232 --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload_vc2012.sln @@ -0,0 +1,37 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpd_upload", "httpd_upload_vc2012.vcxproj", "{58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + DebugDll|Win32 = DebugDll|Win32 + DebugDll|x64 = DebugDll|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseDll|Win32 = ReleaseDll|Win32 + ReleaseDll|x64 = ReleaseDll|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.ActiveCfg = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|Win32.Build.0 = Debug|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|x64.ActiveCfg = Debug|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Debug|x64.Build.0 = Debug|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.ActiveCfg = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|Win32.Build.0 = DebugDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|x64.ActiveCfg = DebugDll|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.DebugDll|x64.Build.0 = DebugDll|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.ActiveCfg = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|Win32.Build.0 = Release|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|x64.ActiveCfg = Release|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.Release|x64.Build.0 = Release|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.ActiveCfg = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|Win32.Build.0 = ReleaseDll|Win32 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|x64.ActiveCfg = ReleaseDll|x64 + {58FE3581-C997-4BD5-9AC6-AEEB54A43D2C}.ReleaseDll|x64.Build.0 = ReleaseDll|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/app/wizard_demo/httpd_upload/httpd_upload_vc2012.vcxproj b/app/wizard_demo/httpd_upload/httpd_upload_vc2012.vcxproj new file mode 100644 index 000000000..54e0089bf --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload_vc2012.vcxproj @@ -0,0 +1,365 @@ +锘 + + + + DebugDll + Win32 + + + DebugDll + x64 + + + Debug + Win32 + + + Debug + x64 + + + ReleaseDll + Win32 + + + ReleaseDll + x64 + + + Release + Win32 + + + Release + x64 + + + + {4A800922-CFB0-49B7-8A7B-A3C457BB2C7F} + Win32Proj + httpd_upload + + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + Application + v110 + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>11.0.50727.1 + + + .\ + Debug\ + true + + + true + .\ + Debug\ + + + Release\ + Release\ + false + + + false + .\ + Release\ + + + .\ + ReleaseDll\ + false + + + false + .\ + ReleaseDll\ + + + .\ + DebugDll\ + true + + + true + .\ + DebugDll\ + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Use + Level3 + EditAndContinue + + + lib_acl_cpp_vc2012d.lib;lib_acl_vc2012d.lib;lib_protocol_vc2012d.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + $(OutDir)httpd_upload.pdb + Console + MachineX86 + false + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_vc2012d.lib;lib_acl_vc2012d.lib;lib_protocol_vc2012d.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win64;%(AdditionalLibraryDirectories) + true + $(OutDir)httpd_upload.pdb + Console + false + 20240000 + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_vc2012.lib;lib_acl_vc2012.lib;lib_protocol_vc2012.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_vc2012.lib;lib_protocol_vc2012.lib;lib_acl_vc2012.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win64;%(AdditionalLibraryDirectories) + true + Console + true + true + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + MultiThreadedDLL + Use + Level3 + ProgramDatabase + + + lib_acl_cpp.lib;lib_acl.lib;lib_protocol.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + copy ..\..\..\dist\lib\win32\lib_acl.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_protocol.dll $(OutDir) /Y + + + + + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + MultiThreadedDLL + Use + Level3 + ProgramDatabase + + + lib_acl_cpp.lib;lib_acl.lib;lib_protocol.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win64;%(AdditionalLibraryDirectories) + true + Console + true + true + + + copy ..\..\..\dist\lib\win64\lib_acl.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win64\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win64\lib_protocol.dll $(OutDir) /Y + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + EditAndContinue + + + lib_acl_cpp_d.lib;lib_acl_d.lib;lib_protocol_d.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win32;%(AdditionalLibraryDirectories) + true + $(OutDir)httpd_upload.pdb + Console + MachineX86 + + + copy ..\..\..\dist\lib\win32\lib_acl_d.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win32\lib_protocol_d.dll $(OutDir) /Y + + + + + Disabled + ..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_CONSOLE;ACL_CPP_DLL;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Use + Level3 + ProgramDatabase + + + lib_acl_cpp_d.lib;lib_acl_d.lib;lib_protocol_d.lib;%(AdditionalDependencies) + $(OutDir)httpd_upload.exe + ..\..\..\dist\lib\win64;%(AdditionalLibraryDirectories) + true + $(OutDir)httpd_upload.pdb + Console + + + copy ..\..\..\dist\lib\win64\lib_acl_d.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win64\lib_acl_cpp.dll $(OutDir) /Y +copy ..\..\..\dist\lib\win64\lib_protocol_d.dll $(OutDir) /Y + + + + + + + + Create + Create + Create + Create + Create + Create + Create + Create + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/wizard_demo/httpd_upload/httpd_upload_vc2012.vcxproj.filters b/app/wizard_demo/httpd_upload/httpd_upload_vc2012.vcxproj.filters new file mode 100644 index 000000000..ba027f281 --- /dev/null +++ b/app/wizard_demo/httpd_upload/httpd_upload_vc2012.vcxproj.filters @@ -0,0 +1,45 @@ +锘 + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + + + + diff --git a/app/wizard_demo/httpd_upload/main.cpp b/app/wizard_demo/httpd_upload/main.cpp new file mode 100644 index 000000000..e62964f25 --- /dev/null +++ b/app/wizard_demo/httpd_upload/main.cpp @@ -0,0 +1,77 @@ +#include "stdafx.h" +#include "master_service.h" + +int main(int argc, char* argv[]) +{ + // 初始化 acl 库 + acl::acl_cpp_init(); + + master_service& ms = acl::singleton2::get_instance(); + + // 设置配置参数表 + ms.set_cfg_int(var_conf_int_tab); + ms.set_cfg_int64(var_conf_int64_tab); + ms.set_cfg_str(var_conf_str_tab); + ms.set_cfg_bool(var_conf_bool_tab); + + // 开始运行 + + if (argc >= 2 && strcmp(argv[1], "alone") == 0) + { + // 日志输出至标准输出 + acl::log::stdout_open(true); + + // 监听的地址列表,格式:ip:port1,ip:port2,... + const char* addrs = ":8888"; + printf("listen on: %s\r\n", addrs); + + // 测试时设置该值 > 0 则指定服务器处理客户端连接过程的 + // 会话总数(一个连接从接收到关闭称之为一个会话),当 + // 处理的连接会话数超过此值,测试过程结束;如果该值设 + // 为 0,则测试过程永远不结束 + unsigned int count = 5; + + // 测试过程中指定线程池最大线程个数 + unsigned int max_threads = 100; + + // 单独运行方式 + + if (argc >= 3) + ms.run_alone(addrs, argv[2], count, max_threads); + else + ms.run_alone(addrs, NULL, count, max_threads); + + printf("Enter any key to exit now\r\n"); + getchar(); + } + else + { +#ifdef WIN32 + // 日志输出至标准输出 + acl::log::stdout_open(true); + + // 监听的地址列表,格式:ip:port1,ip:port2,... + const char* addrs = "127.0.0.1:8888"; + printf("listen on: %s\r\n", addrs); + + // 测试时设置该值 > 0 则指定服务器处理客户端连接过程的 + // 会话总数(一个连接从接收到关闭称之为一个会话),当 + // 处理的连接会话数超过此值,测试过程结束;如果该值设 + // 为 0,则测试过程永远不结束 + unsigned int count = 0; + + // 测试过程中指定线程池最大线程个数 + unsigned int max_threads = 100; + + // 单独运行方式 + ms.run_alone(addrs, NULL, count, max_threads); + printf("Enter any key to exit now\r\n"); + getchar(); +#else + // acl_master 控制模式运行 + ms.run_daemon(argc, argv); +#endif + } + + return 0; +} diff --git a/app/wizard_demo/httpd_upload/master_service.cpp b/app/wizard_demo/httpd_upload/master_service.cpp new file mode 100644 index 000000000..1a25c4b29 --- /dev/null +++ b/app/wizard_demo/httpd_upload/master_service.cpp @@ -0,0 +1,129 @@ +#include "stdafx.h" +#include "http_servlet.h" +#include "master_service.h" + +////////////////////////////////////////////////////////////////////////////// +// 配置内容项 + +char *var_cfg_var_path; +char *var_cfg_redis_addrs; +acl::master_str_tbl var_conf_str_tab[] = { + { "var_path", "var", &var_cfg_var_path }, + { "redis_addrs", "127.0.0.1:6379", &var_cfg_redis_addrs }, + + { 0, 0, 0 } +}; + +int var_cfg_use_redis_session; +acl::master_bool_tbl var_conf_bool_tab[] = { + { "use_redis_session", 1, &var_cfg_use_redis_session }, + + { 0, 0, 0 } +}; + +int var_cfg_conn_timeout; +int var_cfg_rw_timeout; +int var_cfg_max_threads; +acl::master_int_tbl var_conf_int_tab[] = { + { "rw_timeout", 120, &var_cfg_rw_timeout, 0, 0 }, + { "ioctl_max_threads", 128, &var_cfg_max_threads, 0, 0 }, + + { 0, 0 , 0 , 0, 0 } +}; + +long long int var_cfg_int64; +acl::master_int64_tbl var_conf_int64_tab[] = { + { "int64", 120, &var_cfg_int64, 0, 0 }, + + { 0, 0 , 0 , 0, 0 } +}; + +////////////////////////////////////////////////////////////////////////////// + +master_service::master_service() +{ + redis_ = NULL; +} + +master_service::~master_service() +{ +} + +bool master_service::thread_on_read(acl::socket_stream* conn) +{ + http_servlet* servlet = (http_servlet*) conn->get_ctx(); + if (servlet == NULL) + logger_fatal("servlet null!"); + + return servlet->run(); +} + +bool master_service::thread_on_accept(acl::socket_stream* conn) +{ + logger("connect from %s, fd: %d", conn->get_peer(true), + conn->sock_handle()); + conn->set_rw_timeout(var_cfg_rw_timeout); + + acl::session* session; + if (var_cfg_use_redis_session) + session = new acl::redis_session(*redis_, var_cfg_max_threads); + else + session = new acl::memcache_session("127.0.0.1:11211"); + + http_servlet* servlet = new http_servlet(conn, session); + conn->set_ctx(servlet); + + return true; +} + +bool master_service::thread_on_timeout(acl::socket_stream* conn) +{ + logger("read timeout from %s, fd: %d", conn->get_peer(), + conn->sock_handle()); + return false; +} + +void master_service::thread_on_close(acl::socket_stream* conn) +{ + logger("disconnect from %s, fd: %d", conn->get_peer(), + conn->sock_handle()); + + http_servlet* servlet = (http_servlet*) conn->get_ctx(); + acl::session* session = &servlet->getSession(); + delete session; + delete servlet; +} + +void master_service::thread_on_init() +{ +} + +void master_service::thread_on_exit() +{ +} + +void master_service::proc_on_init() +{ + // create redis cluster for session cluster + redis_ = new acl::redis_client_cluster; + redis_->init(NULL, var_cfg_redis_addrs, var_cfg_max_threads, + var_cfg_conn_timeout, var_cfg_rw_timeout); + acl_make_dirs(var_cfg_var_path, 0755); +} + +void master_service::proc_on_exit() +{ + delete redis_; +} + +bool master_service::proc_exit_timer(size_t nclients, size_t nthreads) +{ + if (nclients == 0) + { + logger("clients count: %d, threads count: %d", + (int) nclients, (int) nthreads); + return true; + } + + return false; +} diff --git a/app/wizard_demo/httpd_upload/master_service.h b/app/wizard_demo/httpd_upload/master_service.h new file mode 100644 index 000000000..857c247eb --- /dev/null +++ b/app/wizard_demo/httpd_upload/master_service.h @@ -0,0 +1,94 @@ +#pragma once + +//////////////////////////////////////////////////////////////////////////////// +// 配置内容项 + +extern char *var_cfg_var_path; + +extern acl::master_str_tbl var_conf_str_tab[]; +extern acl::master_bool_tbl var_conf_bool_tab[]; +extern acl::master_int_tbl var_conf_int_tab[]; +extern acl::master_int64_tbl var_conf_int64_tab[]; + +//////////////////////////////////////////////////////////////////////////////// + +//class acl::socket_stream; + +class master_service : public acl::master_threads +{ +public: + master_service(); + ~master_service(); + +protected: + /** + * 纯虚函数:当某个客户端连接有数据可读或关闭或出错时调用此函数 + * @param stream {socket_stream*} + * @return {bool} 返回 false 则表示当函数返回后需要关闭连接, + * 否则表示需要保持长连接,如果该流出错,则应用应该返回 false + */ + virtual bool thread_on_read(acl::socket_stream* stream); + + /** + * 当线程池中的某个线程获得一个连接时的回调函数, + * 子类可以做一些初始化工作 + * @param stream {socket_stream*} + * @return {bool} 如果返回 false 则表示子类要求关闭连接,而不 + * 必将该连接再传递至 thread_main 过程 + */ + virtual bool thread_on_accept(acl::socket_stream* stream); + + /** + * 当某个网络连接的 IO 读写超时时的回调函数,如果该函数返回 true 则表示继续等待下一次 + * 读写,否则则希望关闭该连接 + * @param stream {socket_stream*} + * @return {bool} 如果返回 false 则表示子类要求关闭连接,而不 + * 必将该连接再传递至 thread_main 过程 + */ + virtual bool thread_on_timeout(acl::socket_stream* stream); + + /** + * 当与某个线程绑定的连接关闭时的回调函数 + * @param stream {socket_stream*} + */ + virtual void thread_on_close(acl::socket_stream* stream); + + /** + * 当线程池中一个新线程被创建时的回调函数 + */ + virtual void thread_on_init(); + + /** + * 当线程池中一个线程退出时的回调函数 + */ + virtual void thread_on_exit(); + + /** + * 当进程切换用户身份后调用的回调函数,此函数被调用时,进程 + * 的权限为普通受限级别 + */ + virtual void proc_on_init(); + + /** + * 当子进程需要退出时框架将回调此函数,框架决定子进程是否退出取决于: + * 1) 如果此函数返回 true 则子进程立即退出,否则: + * 2) 如果该子进程所有客户端连接都已关闭,则子进程立即退出,否则: + * 3) 查看配置文件中的配置项(ioctl_quick_abort),如果该配置项非 0 则 + * 子进程立即退出,否则: + * 4) 等所有客户端连接关闭后才退出 + * @param ncleints {size_t} 当前连接的客户端个数 + * @param nthreads {size_t} 当前线程池中繁忙的工作线程个数 + * @return {bool} 返回 false 表示当前子进程还不能退出,否则表示当前 + * 子进程可以退出了 + */ + virtual bool proc_exit_timer(size_t nclients, size_t nthreads); + + /** + * 当进程退出前调用的回调函数 + */ + virtual void proc_on_exit(); + +private: + // redis 集群对象 + acl::redis_client_cluster* redis_; +}; diff --git a/app/wizard_demo/httpd_upload/stdafx.cpp b/app/wizard_demo/httpd_upload/stdafx.cpp new file mode 100644 index 000000000..f01a2ff42 --- /dev/null +++ b/app/wizard_demo/httpd_upload/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : 只包括标准包含文件的源文件 +// master_threads.pch 将成为预编译头 +// stdafx.obj 将包含预编译类型信息 + +#include "stdafx.h" + +// TODO: 在 STDAFX.H 中 +//引用任何所需的附加头文件,而不是在此文件中引用 diff --git a/app/wizard_demo/httpd_upload/stdafx.h b/app/wizard_demo/httpd_upload/stdafx.h new file mode 100644 index 000000000..88376f8ad --- /dev/null +++ b/app/wizard_demo/httpd_upload/stdafx.h @@ -0,0 +1,19 @@ +// stdafx.h : 标准系统包含文件的包含文件, +// 或是常用但不常更改的项目特定的包含文件 +// + +#pragma once + + +//#include +//#include + +// TODO: 在此处引用程序要求的附加头文件 + +#include "acl_cpp/lib_acl.hpp" +#include "lib_acl.h" + +#ifdef WIN32 +#define snprintf _snprintf +#endif + diff --git a/app/wizard_demo/httpd_upload/upload.html b/app/wizard_demo/httpd_upload/upload.html new file mode 100644 index 000000000..3d9d2fbdb --- /dev/null +++ b/app/wizard_demo/httpd_upload/upload.html @@ -0,0 +1,18 @@ + + + + + +
+ +
+
+文件一:
+文件二:
+文件三:
+

+
+ + diff --git a/app/wizard_demo/httpd_upload/valgrind.sh b/app/wizard_demo/httpd_upload/valgrind.sh new file mode 100644 index 000000000..d90ea729c --- /dev/null +++ b/app/wizard_demo/httpd_upload/valgrind.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +valgrind --tool=memcheck --leak-check=yes -v ./httpd_upload alone httpd_upload.cf diff --git a/lib_acl/changes.txt b/lib_acl/changes.txt index b138d25ec..1a88a6270 100644 --- a/lib_acl/changes.txt +++ b/lib_acl/changes.txt @@ -1,6 +1,16 @@ 修改历史列表: ------------------------------------------------------------------------ +528) 2016.2.1 +528.1) feature: acl_vstring.c, 优化代码结构 + +527) 2016.1.30 +527.1) feature: acl_vstring.c 增加了 acl_vstring_mmap_alloc,用于支持以内存 +文件映射方式管理内存 +527.2) feature&safety: acl_vstring.c 真正支持限定最大使用空间功能 +527.3) samples/mmap_string: 该示例用于测试以内存文件映射方式使用 acl_vstring +的功能 + 526) 2016.1.17 526.1) feature: acl_default_malloc.c,函数 acl_default_realloc 当输入的地址为 NULL,则自动切换至 acl_default_malloc 过程 diff --git a/lib_acl/include/stdlib/acl_define_unix.h b/lib_acl/include/stdlib/acl_define_unix.h index 98cf28254..43823c161 100644 --- a/lib_acl/include/stdlib/acl_define_unix.h +++ b/lib_acl/include/stdlib/acl_define_unix.h @@ -39,6 +39,8 @@ #ifdef ACL_UNIX # include +# include + # ifndef acl_assert # define acl_assert assert # endif diff --git a/lib_acl/include/stdlib/acl_vbuf.h b/lib_acl/include/stdlib/acl_vbuf.h index 25b21f5a3..10f0fb6e7 100644 --- a/lib_acl/include/stdlib/acl_vbuf.h +++ b/lib_acl/include/stdlib/acl_vbuf.h @@ -10,13 +10,13 @@ extern "C" { typedef struct ACL_VBUF ACL_VBUF; typedef int (*ACL_VBUF_GET_READY_FN) (ACL_VBUF *); typedef int (*ACL_VBUF_PUT_READY_FN) (ACL_VBUF *); -typedef int (*ACL_VBUF_SPACE_FN) (ACL_VBUF *, int); +typedef int (*ACL_VBUF_SPACE_FN) (ACL_VBUF *, ssize_t); struct ACL_VBUF { - int flags; /* status, see below */ + unsigned flags; /* status, see below */ unsigned char *data; /* variable-length buffer */ - int len; /* buffer length */ - int cnt; /* bytes left to read/write */ + ssize_t len; /* buffer length */ + ssize_t cnt; /* bytes left to read/write */ unsigned char *ptr; /* read/write position */ ACL_VBUF_GET_READY_FN get_ready; /* read buffer empty action */ ACL_VBUF_PUT_READY_FN put_ready; /* write buffer full action */ @@ -41,26 +41,29 @@ struct ACL_VBUF { #define ACL_VBUF_FLAG_ERR (1<<0) /* some I/O error */ #define ACL_VBUF_FLAG_EOF (1<<1) /* end of data */ #define ACL_VBUF_FLAG_TIMEOUT (1<<2) /* timeout error */ -#define ACL_VBUF_FLAG_BAD (ACL_VBUF_FLAG_ERR | ACL_VBUF_FLAG_EOF | ACL_VBUF_FLAG_TIMEOUT) +#define ACL_VBUF_FLAG_BAD \ + (ACL_VBUF_FLAG_ERR | ACL_VBUF_FLAG_EOF | ACL_VBUF_FLAG_TIMEOUT) #define ACL_VBUF_FLAG_FIXED (1<<3) /* fixed-size buffer */ -#define acl_vbuf_error(v) ((v)->flags & ACL_VBUF_FLAG_ERR) -#define acl_vbuf_eof(v) ((v)->flags & ACL_VBUF_FLAG_EOF) +#define acl_vbuf_error(v) ((v)->flags & ACL_VBUF_FLAG_BAD) +#define acl_vbuf_eof(v) ((v)->flags & ACL_VBUF_FLAG_EOF) #define acl_vbuf_timeout(v) ((v)->flags & ACL_VBUF_FLAG_TIMEOUT) -#define acl_vbuf_clearerr(v) ((v)->flags &= ~ACL_VBUF_FLAG_BAD) +#define acl_vbuf_clearerr(v) ((v)->flags &= ~ACL_VBUF_FLAG_BAD) /* * Buffer I/O-like operations and results. */ -#define ACL_VBUF_GET(v) ((v)->cnt < 0 ? ++(v)->cnt, \ - (int) *(v)->ptr++ : acl_vbuf_get(v)) -#define ACL_VBUF_PUT(v,c) ((v)->cnt > 0 ? --(v)->cnt, \ - (int) (*(v)->ptr++ = (c)) : acl_vbuf_put((v),(c))) +#define ACL_VBUF_GET(v) ((v)->cnt < 0 ? ++(v)->cnt, \ + (int) *(v)->ptr++ : acl_vbuf_get(v)) + +#define ACL_VBUF_PUT(v,c) ((v)->cnt > 0 ? --(v)->cnt, \ + (int) (*(v)->ptr++ = (c)) : acl_vbuf_put((v),(c))) + #define ACL_VBUF_SPACE(v,n) ((v)->space((v),(n))) -#define ACL_VBUF_CHARAT(v, offset) ((int) (v).data[offset]) +#define ACL_VBUF_CHARAT(v, offset) ((int) (v).data[offset]) -#define ACL_VBUF_EOF (-1) /* no more space or data */ +#define ACL_VBUF_EOF (-1) /* no more space or data */ ACL_API int acl_vbuf_get(ACL_VBUF *); ACL_API int acl_vbuf_put(ACL_VBUF *, int); @@ -73,4 +76,3 @@ ACL_API int acl_vbuf_write(ACL_VBUF *, const char *, int); #endif #endif - diff --git a/lib_acl/include/stdlib/acl_vstring.h b/lib_acl/include/stdlib/acl_vstring.h index 8411d8306..b0cb78479 100644 --- a/lib_acl/include/stdlib/acl_vstring.h +++ b/lib_acl/include/stdlib/acl_vstring.h @@ -15,10 +15,11 @@ extern "C" { * 封装了 ACL_VBUF,ACL_VSTRING 结构类型定义 */ typedef struct ACL_VSTRING { - ACL_VBUF vbuf; - int maxlen; + ACL_VBUF vbuf; + ssize_t maxlen; ACL_SLICE_POOL *slice; - ACL_DBUF_POOL *dbuf; + ACL_DBUF_POOL *dbuf; + ACL_FILE_HANDLE fd; } ACL_VSTRING; /** @@ -61,6 +62,16 @@ ACL_API ACL_VSTRING *acl_vstring_slice_alloc(ACL_SLICE_POOL *slice, size_t len); */ ACL_API ACL_VSTRING *acl_vstring_dbuf_alloc(ACL_DBUF_POOL *dbuf, size_t len); +/** + * 采用内存映射文件方式分配内存时,调用此函数创建 ACL_VSTRING 动态缓冲区对象 + * @param fd {ACL_FILE_HANDLE} 有效的文件句柄 + * @param max_len {ssize_t} 所映射的最大内存大小 + * @param init_len {ssize_t} 初始化时的内存映射大小 + * @return {ACL_VSTRING*} 新创建的 ACL_VSTRING 对象 + */ +ACL_API ACL_VSTRING *acl_vstring_mmap_alloc(ACL_FILE_HANDLE fd, + ssize_t max_len, ssize_t init_len); + /** * 设置 ACL_VSTRING 对象的属性, 目前该函数的功能还不够完善 * @param vp {ACL_VSTRING*} @@ -373,8 +384,14 @@ ACL_API const ACL_VSTRING *acl_buffer_gets(ACL_VSTRING *vp, */ #define ACL_VSTRING_TERMINATE(vp) { \ if ((vp)->vbuf.cnt <= 0) \ - ACL_VSTRING_SPACE((vp),1); \ - *(vp)->vbuf.ptr = 0; \ + ACL_VSTRING_SPACE((vp), 1); \ + if ((vp)->vbuf.cnt > 0) \ + *(vp)->vbuf.ptr = 0; \ + else if ((vp)->vbuf.ptr > (vp)->vbuf.data) { \ + (vp)->vbuf.ptr--; \ + *(vp)->vbuf.ptr = 0; \ + (vp)->vbuf.cnt++; \ + } \ } /** @@ -385,6 +402,7 @@ ACL_API const ACL_VSTRING *acl_buffer_gets(ACL_VSTRING *vp, #define ACL_VSTRING_RESET(vp) { \ (vp)->vbuf.ptr = (vp)->vbuf.data; \ (vp)->vbuf.cnt = (vp)->vbuf.len; \ + acl_vbuf_clearerr(&(vp)->vbuf); \ } /** diff --git a/lib_acl/include/xml/acl_xml2.h b/lib_acl/include/xml/acl_xml2.h index 9c35c64f3..a740afa0a 100644 --- a/lib_acl/include/xml/acl_xml2.h +++ b/lib_acl/include/xml/acl_xml2.h @@ -22,8 +22,8 @@ struct ACL_XML2_ATTR { char *name; /**< 属性名 */ char *value; /**< 属性值 */ - size_t name_size; /**< 属性名长度 */ - size_t value_size; /**< 属性值长度 */ + ssize_t name_size; /**< 属性名长度 */ + ssize_t value_size; /**< 属性值长度 */ /* private */ int quote; /**< 非 0 表示 ' 或 " */ @@ -34,12 +34,12 @@ struct ACL_XML2_ATTR { struct ACL_XML2_NODE { char *ltag; /**< 左标签名 */ char *rtag; /**< 右标签名 */ - size_t ltag_size; /**< 左标签名长度 */ - size_t rtag_size; /**< 右标签名长度 */ + ssize_t ltag_size; /**< 左标签名长度 */ + ssize_t rtag_size; /**< 右标签名长度 */ const char *id; /**< ID标识符, 只有在 xml->id_table 存在的节点的 id 才非空 */ char *text; /**< 文本显示内容 */ - size_t text_size; /**< 文件数据长度 */ + ssize_t text_size; /**< 文件数据长度 */ ACL_ARRAY *attr_list; /**< 属性(ACL_XML2_ATTR)列表 */ ACL_XML2_NODE *parent; /**< 父节点 */ @@ -111,17 +111,10 @@ struct ACL_XML2 { ACL_XML2_NODE *root; /**< XML 根节点 */ /* private */ - char *addr; /**< 内存起始地址 */ - char *ptr; /**< 内存地址 */ - size_t size; /**< addr 内存映射区的大小 */ - size_t len; /**< addr 内存映射区剩余大小 */ - - char *mm_file; /**< 非空时指定内存映射文件名 */ - char *mm_addr; /**< 内存映射起始地址 */ - ACL_FILE_HANDLE fd; /**< 采用内存映射方式时的文件句柄 */ - size_t off; /**< 当前内存映射文件的实际映射大小 */ - size_t block; /**< len 自增时的自增块长度大小 */ - int keep_open; /**< 文件句柄是否一直打开 */ + ACL_FILE_HANDLE fd; /** 保存由本对象打开的文件句柄 */ + ACL_VSTRING *vbuf; /**< 基于内存映射文件的缓冲区 */ + ACL_VSTRING *vbuf_inner; /**< 内部创建的缓冲区对象 */ + char dummy[1]; ACL_HTABLE *id_table; /**< id 标识符哈希表 */ ACL_XML2_NODE *curr_node; /**< 当前正在处理的 XML 节点 */ @@ -179,73 +172,44 @@ ACL_API int acl_xml2_is_complete(ACL_XML2 *xml, const char *tag); /** * 创建一个 xml 对象 - * @param addr {char*} 内存映射起始地址 - * @param size {ssize_t} addr 内存映射地址大小 + * @param vbuf {ACL_VSTRING*} 内存映射缓冲区对象 * @return {ACL_XML2*} 新创建的 xml 对象 */ -ACL_API ACL_XML2 *acl_xml2_alloc(char *addr, size_t size); +ACL_API ACL_XML2 *acl_xml2_alloc(ACL_VSTRING *vbuf); /** * 创建一个 xml 对象,该 xml 对象及所有的内部内存分配都在该内存池上进行分配 - * @param addr {char*} 内存映射起始地址 - * @param size {ssize_t} addr 内存映射地址大小 + * @param vbuf {ACL_VSTRING*} 内存映射缓冲区对象 * @param dbuf {ACL_DBUF_POOL*} 内存池对象,当该针对非 NULL 时,则 xml 对象 * 及所属节点内存在其基础上进行分配,否则,内部自动创建隶属于 xml 的内存池 * @return {ACL_XML2*} 新创建的 xml 对象 */ -ACL_API ACL_XML2 *acl_xml2_dbuf_alloc(char *addr, size_t size, - ACL_DBUF_POOL *dbuf); +ACL_API ACL_XML2 *acl_xml2_dbuf_alloc(ACL_VSTRING *vbuf, ACL_DBUF_POOL *dbuf); /** * 创建一个 xml 对象,其 xml 节点的创建的内存区建立在内存映射文件上 * @param filepath {const char*} 内存映射文件的文件名 - * @param size {size_t} 所映射的文件大小 - * @param block {size_t} 每次进行空间大小扩充时的单位长度,在扩充时最大长度 - * 不会超过指定的 size 大小 - * @param keep_open {int} 是否一直保持文件被打开至 xml 对象释放,如果否,则 - * 当映射文件自动扩充时需要重新反复打开,会影响解析效率 + * @param max_len {size_t} 所映射的文件大小 + * @param init_len {size_t} 映射内存初始化时的大小 * @param dbuf {ACL_DBUF_POOL*} 内存池对象,当该针对非 NULL 时,则 xml 对象 * 及所属节点内存在其基础上进行分配,否则,内部自动创建隶属于 xml 的内存池 * @return {ACL_XML2*} 新创建的 xml 对象 */ -ACL_API ACL_XML2 *acl_xml2_mmap_file(const char *filepath, size_t size, - size_t block, int keep_open, ACL_DBUF_POOL *dbuf); +ACL_API ACL_XML2 *acl_xml2_mmap_file(const char *filepath, size_t max_len, + size_t init_len, ACL_DBUF_POOL *dbuf); /** * 创建一个 xml 对象,其 xml 节点的创建的内存区建立在内存映射文件上 - * @param fd {ACL_FILE_HANDLE} 内存映射文件的文件句柄,当创建 xml 对象成功后,该句柄 - * 需在 xml 对象释放后才关闭 - * @param size {size_t} 所映射的文件大小 - * @param block {size_t} 每次进行空间大小扩充时的单位长度,在扩充时最大长度 - * 不会超过指定的 size 大小 + * @param fd {ACL_FILE_HANDLE} 内存映射文件的文件句柄,当创建 xml 对象成功后, + * 该句柄需在 xml 对象释放后才关闭 + * @param max_len {size_t} 所映射的文件大小 + * @param init_len {size_t} 映射内存初始化时的大小 * @param dbuf {ACL_DBUF_POOL*} 内存池对象,当该针对非 NULL 时,则 xml 对象 * 及所属节点内存在其基础上进行分配,否则,内部自动创建隶属于 xml 的内存池 * @return {ACL_XML2*} 新创建的 xml 对象 */ -ACL_API ACL_XML2 *acl_xml2_mmap_fd(ACL_FILE_HANDLE fd, size_t size, - size_t block, ACL_DBUF_POOL *dbuf); - -/** - * 当采用内存文件映射方式时,此函数用来扩充映射文件的空间大小,因为在初始化时 - * 仅分配较小的空间,在使用过程中如果发现空间不足,则内部自动调用此函数扩展 - * 文件大小,这样既可以满足实际需求,又可以节省磁盘空间 - * @param xml {ACL_XML2*} 采用 acl_xml2_mmap_alloc 方式创建的 xml 对象 - * @return {size_t} 扩充后新增加的空间大小,如果返回值为 0,则表示出错或已经 - * 达到空间分配上限购 - */ -ACL_API size_t acl_xml2_mmap_extend(ACL_XML2 *xml); - -/** - * 当采用内存文件映射方式时,此函数用来扩充映射文件的空间大小,因为在初始化时 - * 仅分配较小的空间,在使用过程中如果发现空间不足,则内部自动调用此函数扩展 - * 文件大小,这样既可以满足实际需求,又可以节省磁盘空间 - * @param xml {ACL_XML2*} 采用 acl_xml2_mmap_alloc 方式创建的 xml 对象 - * @param n {size_t} 希望本次扩充的空间大小,如果该值超过最大限制,则返回实际 - * 扩充的空间大小 - * @return {size_t} 扩充后新增加的空间大小,如果返回值为 0,则表示出错或已经 - * 达到空间分配上限购 - */ -ACL_API size_t acl_xml2_mmap_extend_size(ACL_XML2 *xml, size_t n); +ACL_API ACL_XML2 *acl_xml2_mmap_fd(ACL_FILE_HANDLE fd, size_t max_len, + size_t init_len, ACL_DBUF_POOL *dbuf); /** * 将某一个 ACL_XML2_NODE 节点作为一个 XML 对象的根节点,从而可以方便地遍历出该 diff --git a/lib_acl/lib_acl_vc2012.vcxproj b/lib_acl/lib_acl_vc2012.vcxproj index 031d4f3f6..1f3ffc3f6 100644 --- a/lib_acl/lib_acl_vc2012.vcxproj +++ b/lib_acl/lib_acl_vc2012.vcxproj @@ -729,6 +729,7 @@ copy $(TargetName).pdb ..\dist\lib\win64\$(TargetName).pdb /Y + @@ -885,4 +886,4 @@ copy $(TargetName).pdb ..\dist\lib\win64\$(TargetName).pdb /Y - + \ No newline at end of file diff --git a/lib_acl/lib_acl_vc2012.vcxproj.filters b/lib_acl/lib_acl_vc2012.vcxproj.filters index 7fa7ecf2c..53897da03 100644 --- a/lib_acl/lib_acl_vc2012.vcxproj.filters +++ b/lib_acl/lib_acl_vc2012.vcxproj.filters @@ -1533,6 +1533,9 @@ Header Files\xml + + Header Files\code + @@ -1545,4 +1548,4 @@ doc - + \ No newline at end of file diff --git a/lib_acl/samples/mmap_string/Makefile b/lib_acl/samples/mmap_string/Makefile new file mode 100644 index 000000000..3589772ff --- /dev/null +++ b/lib_acl/samples/mmap_string/Makefile @@ -0,0 +1,2 @@ +include ../Makefile.in +PROG = string diff --git a/lib_acl/samples/mmap_string/main.c b/lib_acl/samples/mmap_string/main.c new file mode 100644 index 000000000..b48592f00 --- /dev/null +++ b/lib_acl/samples/mmap_string/main.c @@ -0,0 +1,110 @@ +#include "lib_acl.h" + +static void incr_string(ACL_VSTRING *vp, int len, const char* s, int debug) +{ + int i; + + printf("max: %ld, len: %ld, cnt: %ld\r\n", (long) vp->maxlen, + vp->vbuf.len, vp->vbuf.cnt); + + for (i = 0; i < len; i++) + ACL_VSTRING_ADDCH(vp, 'x'); + + if (s && *s) + acl_vstring_sprintf_append(vp, "%s", s); + else + ACL_VSTRING_TERMINATE(vp); + + if (debug) + printf("[%s]\r\n", acl_vstring_str(vp)); + + printf("len: %ld, %ld, max: %ld\r\n", (long) strlen(acl_vstring_str(vp)), + (long) ACL_VSTRING_LEN(vp), (long) vp->maxlen); + + printf("Enter any key to continue ...\r\n\r\n"); + getchar(); + + ACL_VSTRING_RESET(vp); +} + +static void test_string(ACL_FILE_HANDLE fd, ssize_t max, int debug) +{ + ACL_VSTRING *vp = acl_vstring_mmap_alloc(fd, 1, max); + const char *s = "hello world!"; + + printf("-------------------------------------------------------\r\n"); + incr_string(vp, max - 1, NULL, debug); + + printf("-------------------------------------------------------\r\n"); + incr_string(vp, max - 1 - strlen(s), s, debug); + + printf("-------------------------------------------------------\r\n"); + incr_string(vp, max, NULL, debug); + + printf("-------------------------------------------------------\r\n"); + incr_string(vp, max + 2, NULL, debug); + + printf("-------------------------------------------------------\r\n"); + acl_vstring_strcat(vp, s); + incr_string(vp, max - strlen(s) - 1, NULL, debug); + + printf("-------------------------------------------------------\r\n"); + acl_vstring_strcat(vp, s); + incr_string(vp, max, NULL, debug); + + printf("-------------------------------------------------------\r\n"); + acl_vstring_strcat(vp, s); + incr_string(vp, max + 10, NULL, debug); + + acl_vstring_free(vp); +} + +static void usage(const char* procname) +{ + printf("usage: %s -h[help] -f filename -n max_size -d [debug]\r\n", procname); +} + +int main(int argc, char *argv[]) +{ + char filename[256]; + int ch, debug = 0; + ssize_t max = 8192; + ACL_FILE_HANDLE fd; + + snprintf(filename, sizeof(filename), "mmap.local"); + + while ((ch = getopt(argc, argv, "hf:n:d")) > 0) { + switch (ch) { + case 'h': + usage(argv[0]); + return 0; + case 'f': + snprintf(filename, sizeof(filename), "%s", optarg); + break; + case 'n': + max = atol(optarg); + break; + case 'd': + debug = 1; + break; + default: + break; + } + } + + acl_msg_stdout_enable(1); + + printf("filename: %s, max size: %ld\r\n", filename, (long) max); + + fd = acl_file_open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600); + + if (fd == ACL_FILE_INVALID) { + printf("open %s error %s\r\n", filename, acl_last_serror()); + return 1; + } + + test_string(fd, max, debug); + + acl_file_close(fd); + return 0; +} diff --git a/lib_acl/samples/mmap_string/valgrind.sh b/lib_acl/samples/mmap_string/valgrind.sh new file mode 100644 index 000000000..b6319373d --- /dev/null +++ b/lib_acl/samples/mmap_string/valgrind.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +valgrind --tool=memcheck --leak-check=yes -v ./string -n 102400 diff --git a/lib_acl/samples/xml/xml3/test.sh b/lib_acl/samples/xml/xml3/test.sh new file mode 100644 index 000000000..f5d93c75e --- /dev/null +++ b/lib_acl/samples/xml/xml3/test.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +./xml -s -d data1 -P +./xml -s -d data2 -P +./xml -s -d data3 -P +./xml -s -d data4 -P +./xml -s -d data5 -P +./xml -s -d data6 -P +./xml -s -d data7 -P +./xml -s -d data8 -P +./xml -s -d data9 -P diff --git a/lib_acl/samples/xml/xml3/xml.c b/lib_acl/samples/xml/xml3/xml.c index ecdec4dcf..8a1f82b1c 100644 --- a/lib_acl/samples/xml/xml3/xml.c +++ b/lib_acl/samples/xml/xml3/xml.c @@ -73,8 +73,8 @@ static const char* __data4 = "\r\n" " \r\n" " \r\n" " \r\n" - " \r\n" - " \r\n" + " \r\n" + " \r\n" " \r\n" " \r\n" " \r\n" @@ -133,12 +133,16 @@ static const char* __data7 = "\r\n" static const char* __data8 = "\r\n" " hello world! \r\n"; +static const char *__data9 = + "\r\n" + "\r\n"; + static void parse_xml_benchmark(int once, int max, const char *data) { int i; size_t size = strlen(data) * 4; const char *mmap_file = "./local.map"; - ACL_XML2 *xml = acl_xml2_mmap_file(mmap_file, size, 1024, 1, NULL); + ACL_XML2 *xml = acl_xml2_mmap_file(mmap_file, size, 1, NULL); acl_xml2_slash(xml, 1); @@ -202,7 +206,7 @@ static int parse_xml_file(const char *filepath) } len *= 4; - xml = acl_xml2_mmap_file(mmap_file, len, 1024, 1, NULL); + xml = acl_xml2_mmap_file(mmap_file, len, 1, NULL); ACL_METER_TIME("-------------begin--------------"); while (1) { @@ -244,8 +248,8 @@ static void walk_xml(ACL_XML2* xml) for (i = 1; i < node->depth; i++) printf("\t"); - printf("tag->%s, size: %ld\n", node->ltag, - (long) node->ltag_size); + printf("%s(%d): tag->%s, size: %ld\n", __FUNCTION__, __LINE__, + node->ltag, (long) node->ltag_size); /* 遍历 xml 结点的属性 */ acl_foreach(iter2, node->attr_list) { @@ -254,13 +258,14 @@ static void walk_xml(ACL_XML2* xml) for (i = 1; i < node->depth + 1; i++) printf("\t"); - printf("attr->%s=\"%s\"\n", attr->name, attr->value); + printf("%s(%d): attr->%s=\"%s\"\n", __FUNCTION__, + __LINE__, attr->name, attr->value); } for (i = 1; i < node->depth + 1; i++) printf("\t"); - printf("text->%s, size: %ld\n", node->text, - (long) node->text_size); + printf("%s(%d): text->%s, size: %ld\n", __FUNCTION__, + __LINE__, node->text, (long) node->text_size); } printf("-------------- walk_xml end -------------------\r\n"); @@ -280,9 +285,26 @@ static void xml_node_attrs(ACL_XML2_NODE* node, int n) for (i = 0; i < n; i++) printf("\t"); - printf("attr->%s(%ld)=\"%s(%ld)\"\n", - attr->name, (long) attr->name_size, - attr->value, (long) attr->value_size); + printf("%s(%d): attr->%s(%ld, %ld)=\"%s(%ld, %ld)\"\n", + __FUNCTION__, __LINE__, attr->name, + (long) attr->name_size, (long) strlen(attr->name), + attr->value, (long) attr->value_size, + (long) strlen(attr->value)); + + if ((size_t) attr->name_size != strlen(attr->name)) { + printf("%s(%d): name_size invalie: %ld, %ld, %s\r\n", + __FUNCTION__, __LINE__, + (long) attr->name_size, + (long) strlen(attr->name), attr->name); + assert(0); + } + if ((size_t) attr->value_size != strlen(attr->value)) { + printf("%s(%d): value_size invalie, value: %s, " + "len: %ld, %ld\r\n", __FUNCTION__, __LINE__, + attr->value, (long) attr->value_size, + (long) strlen(attr->value)); + assert(0); + } } } @@ -299,16 +321,33 @@ static void walk_xml_node(ACL_XML2_NODE *node, int n) for (i = 0; i < n; i++) printf("\t"); - printf("tag->%s, size: %ld\n", child->ltag, - (long) child->ltag_size); + printf("%s(%d): tag->%s, size: %ld, %ld\n", __FUNCTION__, + __LINE__, child->ltag, (long) child->ltag_size, + (long) strlen(child->ltag)); + + if ((size_t) child->ltag_size != strlen(child->ltag)) { + printf("%s(%d): ltag_size invalid, ltag: %s, " + "len: %ld, %ld\r\n", __FUNCTION__, __LINE__, + child->ltag, (long) child->ltag_size, + (long) strlen(child->ltag)); + assert(0); + } xml_node_attrs(child, n + 1); for (i = 0; i < n + 1; i++) printf("\t"); - printf("text->%s, size: %ld\n", child->text, - (long) child->text_size); + printf("%s(%d): text->%s, size: %ld, %ld\n", __FUNCTION__, + __LINE__, child->text, (long) child->text_size, + (long) strlen(child->text)); + if ((size_t) child->text_size != strlen(child->text)) { + printf("%s(%d): text_size invalid: %ld, %ld, " + "text: %s\r\n", __FUNCTION__, __LINE__, + (long) child->text_size, + (long) strlen(child->text), child->text); + assert(0); + } walk_xml_node(child, n + 1); } @@ -321,7 +360,8 @@ static void list_xml_tags(ACL_XML2 *xml) printf("-------------- list xml's all tags --------------------\r\n"); acl_foreach(iter, xml) { ACL_XML2_NODE *node = (ACL_XML2_NODE*) iter.data; - printf(">>tag: %s\n", node->ltag); + printf("%s(%d): tag: %s\n", __FUNCTION__, __LINE__, + node->ltag); } printf("-------------- list xml's all tags end ----------------\r\n"); @@ -406,7 +446,7 @@ static ACL_XML2 *get_xml(int once, const char *data, const char* root, int multi_root) { size_t size = strlen(data) * 4; - char *addr = (char*) acl_mymalloc(size); + ACL_VSTRING *vbuf = acl_vstring_alloc(size); ACL_XML2 *xml; const char *left; @@ -416,7 +456,7 @@ static ACL_XML2 *get_xml(int once, const char *data, printf("Enter any key to continue ...\r\n"); getchar(); - xml = acl_xml2_alloc(addr, size); + xml = acl_xml2_alloc(vbuf); acl_xml2_multi_root(xml, multi_root); acl_xml2_decode_enable(xml, 1); acl_xml2_slash(xml, 1); @@ -506,11 +546,19 @@ static void parse_xml(int once, const char *data, printf("----------------- build xml -------------------------\r\n"); ptr = acl_xml2_build(xml); - printf("%s\r\n", ptr); + printf("%s, len: %ld, %ld\r\n", ptr, (long) strlen(ptr), + (long) (acl_vstring_end(xml->vbuf) - ptr)); + if (strlen(ptr) != (size_t) (acl_vstring_end(xml->vbuf) - ptr)) { + printf("%s(%d): invalid xml size: %ld, %ld\r\n", __FUNCTION__, + __LINE__, (long) strlen(ptr), + (long) (acl_vstring_end(xml->vbuf) - ptr)); + assert(0); + } + printf("----------------- build xml end ---------------------\r\n"); /* 释放 xml 对象 */ - acl_myfree(xml->addr); + acl_vstring_free(xml->vbuf); left = acl_xml2_free(xml); printf("Free all node ok, total(%d), left is: %d\n", total, left); @@ -532,10 +580,10 @@ static void test1(void) ACL_XML2_NODE *node; const char *encoding, *type, *href; size_t size = strlen(data) * 3; - char *addr = acl_mymalloc(size); + ACL_VSTRING *buf = acl_vstring_alloc(size); const char *ptr; - xml = acl_xml2_alloc(addr, size); + xml = acl_xml2_alloc(buf); printf("------------------------------------------------------\r\n"); @@ -575,17 +623,22 @@ static void test1(void) ptr = acl_xml2_build(xml); printf("%s\r\n", ptr); printf("----------------- build xml end ---------------------\r\n"); - acl_myfree(addr); + acl_vstring_free(buf); acl_xml2_free(xml); } static void build_xml(void) { - size_t size = 1024; - char *addr = acl_mymalloc(size); - ACL_XML2 *xml = acl_xml2_alloc(addr, size); + size_t size = 2000; + ACL_VSTRING *vbuf = acl_vstring_alloc(size); + ACL_XML2 *xml = acl_xml2_alloc(vbuf); ACL_XML2_NODE *node1, *node2, *node3; const char *buf; + const char* pp = "text1text11text111text2text3"; + + /* + vbuf->maxlen = size; + */ node1 = acl_xml2_create_node(xml, "users", "text1"); acl_xml2_node_add_child(xml->root, node1); @@ -609,10 +662,28 @@ static void build_xml(void) printf("--------------------xml string-------------------\r\n"); buf = acl_xml2_build(xml); - printf("%s\n", buf); + printf("[%s]\n", buf); + + if (strlen(buf) != (size_t) (acl_vstring_end(xml->vbuf) - buf)) { + printf("invalid length: %ld, %ld, %p\r\n", (long) strlen(buf), + (long) (acl_vstring_end(xml->vbuf) - buf), + acl_vstring_end(xml->vbuf)); + assert(0); + } + printf("length: %ld, %ld\r\n", (long) strlen(buf), + (long) (acl_vstring_end(xml->vbuf) - buf)); + + if (strcmp(pp, buf) == 0) + printf(">>>>>>>>OK<<<<<<<<<<<\r\n"); + else { + printf(">>>>>>>>Error<<<<<<<<\r\n"); + assert(0); + } + printf("--------------------xml string end---------------\r\n"); - acl_myfree(addr); + + acl_vstring_free(vbuf); acl_xml2_free(xml); printf("Enter any key to continue ...\r\n"); @@ -630,7 +701,7 @@ static void usage(const char *procname) " -m[if enable multiple root xml node, default: no]\r\n" " -p[print] data1|data2|data3|data4|data5|data6|data7\r\n" " -P [if parse one xml with one data]\r\n" - " -d[parse] data1|data2|data3|data4|data5|data6|data7\r\n", + " -d[parse] data1|data2|data3|data4|data5|data6|data7|data8|data9\r\n", procname); } @@ -646,7 +717,7 @@ int main(int argc, char *argv[]) const char* root = "root"; char filepath[256]; - acl_msg_stdout_enable(1); +// acl_msg_stdout_enable(1); filepath[0] = 0; @@ -695,6 +766,9 @@ int main(int argc, char *argv[]) } else if (strcasecmp(optarg, "data8") == 0) { data = __data8; root = "root"; + } else if (strcasecmp(optarg, "data9") == 0) { + data = __data9; + root = "root"; } break; case 'p': @@ -714,6 +788,8 @@ int main(int argc, char *argv[]) printf("%s\n", __data7); else if (strcasecmp(optarg, "data8") == 0) printf("%s\n", __data8); + else if (strcasecmp(optarg, "data9") == 0) + printf("%s\n", __data9); return (0); case 'f': snprintf(filepath, sizeof(filepath), "%s", optarg); @@ -744,9 +820,7 @@ int main(int argc, char *argv[]) if (build) build_xml(); -#ifdef ACL_MS_WINDOWS - printf("ok, enter any key to exit ...\n"); + printf("----OK, ENTER ANY KEY TO EXIT ----\n"); getchar(); -#endif return 0; } diff --git a/lib_acl/samples/xml/xml3/xml.c.new b/lib_acl/samples/xml/xml3/xml.c.new new file mode 100644 index 000000000..c24d38aa6 --- /dev/null +++ b/lib_acl/samples/xml/xml3/xml.c.new @@ -0,0 +1,778 @@ +#include +#include +#include "lib_acl.h" + +static const char *__data1 = + "\r\n" + "\r\n" + "\txmllint\">\r\n" + "]>\r\n" + "\r\n" + " user zsx11 \r\n" + " user zsx12 \r\n" + " my age\r\n" + " \r\n" + " " + " " + " mobile number " + " office number " + " " + " " + " \r\n" + " user zsx13 \r\n" + "\r\n" + "\r\n" + " user zsx21 \r\n" + " user zsx22 \r\n" + " \r\n" + " my age\r\n" + " \r\n" + " user zsx23 \r\n" + "\r\n" + "\r\n" + " user zsx31 \r\n" + " user zsx32 \r\n" + " user zsx33 \r\n" + " bao bao \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " user zsx34 \r\n" + "\r\n"; + +static const char *__data2 = + "\r\n" + "\r\n" + "xmllint\">\r\n" + "]>\r\n" + "test\r\n" + " - -->\r\n" + " zsx\r\n" + " 38\r\n" + " \r\n" + "\r\n" + " -->\r\n" + "\r\n" + "\r\n" + "test\r\n"; + +static const char *__data3 = \ + "hello hi
\r\n"; + +static const char* __data4 = "\r\n" + "\r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + "\r\n" + "\r\n" + "\r\n" + "\r\n"; + +static const char* __data5 = "\r\n" + "\r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + "\r\n"; + +static const char* __data6 = "\r\n" + "\r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + "\r\n"; + +static const char* __data7 = "\r\n" + "\r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + " \r\n" + "\r\n"; + + static const char* __data8 = "\r\n" + " hello world! \r\n"; + +static void parse_xml_benchmark(int once, int max, const char *data) +{ + int i; + size_t size = strlen(data) * 4; + const char *mmap_file = "./local.map"; + ACL_XML2 *xml = acl_xml2_mmap_file(mmap_file, size, 1, NULL); + + acl_xml2_slash(xml, 1); + + ACL_METER_TIME("-------------bat begin--------------"); + for (i = 0; i < max; i++) { + const char *ptr = data; + + if (once) { + acl_xml2_parse(xml, ptr); + } else { + /* 每次仅输入一个字节来分析 xml 数据 */ + while (*ptr != 0) { + char ch2[2]; + + ch2[0] = *ptr; + ch2[1] = 0; + acl_xml2_parse(xml, ch2); + ptr++; + } + } + /* + if (i < 2 || i == 4) { + printf("--------- dump xml --------------\n"); + acl_xml_dump(xml, ACL_VSTREAM_OUT); + printf("--------- data src --------------\n"); + printf("%s", data); + printf("--------- dump end --------------\n"); + } + */ + + acl_xml2_reset(xml); + } + + ACL_METER_TIME("-------------bat end--------------"); + acl_xml2_free(xml); + + printf("--------------benchmark_max: %d--------------\r\n", max); + + printf("Enter any key to continue ...\r\n"); + getchar(); +} + +static int parse_xml_file(const char *filepath) +{ + int n; + acl_int64 len; + char buf[10240]; + ACL_VSTREAM *fp = acl_vstream_fopen(filepath, O_RDONLY, 0600, 8192); + ACL_XML2 *xml; + const char *mmap_file = "./local.map"; + + if (fp == NULL) { + printf("open %s error %s\r\n", filepath, acl_last_serror()); + return -1; + } + len = acl_vstream_fsize(fp); + if (len <= 0) { + printf("fsize %s error %s\r\n", filepath, acl_last_serror()); + acl_vstream_close(fp); + return -1; + } + len *= 4; + + xml = acl_xml2_mmap_file(mmap_file, len, 1, NULL); + + ACL_METER_TIME("-------------begin--------------"); + while (1) { + n = acl_vstream_read(fp, buf, sizeof(buf) - 1); + if (n == ACL_VSTREAM_EOF) + break; + buf[n] = 0; + acl_xml2_update(xml, buf); + } + ACL_METER_TIME("-------------end--------------"); + + acl_vstream_close(fp); + + if (acl_xml2_is_complete(xml, "root")) + printf("Xml is complete OK, filepath: %s\r\n", filepath); + else + printf("Xml is not complete, filepath: %s\r\n", filepath); + acl_xml2_free(xml); + + printf("Enter any key to continue ...\r\n"); + getchar(); + + return 0; +} + +static void walk_xml(ACL_XML2* xml) +{ + ACL_ITER iter1; + + /* 从根结点开始遍历 xml 对象的所有结点 */ + + printf("-------------- walk_xml -----------------------\r\n"); + + acl_foreach(iter1, xml) { + int i; + ACL_ITER iter2; + ACL_XML2_NODE *node = (ACL_XML2_NODE*) iter1.data; + + for (i = 1; i < node->depth; i++) + printf("\t"); + + printf("tag->%s, size: %ld\n", node->ltag, + (long) node->ltag_size); + + /* 遍历 xml 结点的属性 */ + acl_foreach(iter2, node->attr_list) { + ACL_XML2_ATTR *attr = (ACL_XML2_ATTR*) iter2.data; + + for (i = 1; i < node->depth + 1; i++) + printf("\t"); + + printf("attr->%s=\"%s\"\n", attr->name, attr->value); + } + + for (i = 1; i < node->depth + 1; i++) + printf("\t"); + printf("text->%s, size: %ld\n", node->text, + (long) node->text_size); + } + + printf("-------------- walk_xml end -------------------\r\n"); + + printf("Enter any key to continue ...\r\n"); + getchar(); +} + +static void xml_node_attrs(ACL_XML2_NODE* node, int n) +{ + int i; + ACL_ITER iter; + + acl_foreach(iter, node->attr_list) { + ACL_XML2_ATTR *attr = (ACL_XML2_ATTR*) iter.data; + + for (i = 0; i < n; i++) + printf("\t"); + + printf("attr->%s(%ld)=\"%s(%ld)\"\n", + attr->name, (long) attr->name_size, + attr->value, (long) attr->value_size); + if (attr->name_size != strlen(attr->name)) { + printf("%s(%d): name_size invalie\r\n", + __FUNCTION__, __LINE__); + exit (1); + } + } +} + +static void walk_xml_node(ACL_XML2_NODE *node, int n) +{ + ACL_ITER iter; + + /* 遍历结点的子结点 */ + + acl_foreach(iter, node) { + int i; + ACL_XML2_NODE *child = (ACL_XML2_NODE*) iter.data; + + for (i = 0; i < n; i++) + printf("\t"); + + printf("tag->%s, size: %ld, %ld\n", child->ltag, + (long) child->ltag_size, (long) strlen(child->ltag)); + + if (child->ltag_size != strlen(child->ltag)) { + printf("%s(%d): ltag_size invalid\r\n", + __FUNCTION__, __LINE__); + exit (1); + } + + xml_node_attrs(child, n + 1); + + for (i = 0; i < n + 1; i++) + printf("\t"); + + printf("text->%s, size: %ld, %ld\n", child->text, + (long) child->text_size, (long) strlen(child->text)); + if (child->text_size != strlen(child->text)) { + printf("%s(%d): text_size invalid\r\n", + __FUNCTION__, __LINE__); + exit (1); + } + + walk_xml_node(child, n + 1); + } +} + +static void list_xml_tags(ACL_XML2 *xml) +{ + ACL_ITER iter; + + printf("-------------- list xml's all tags --------------------\r\n"); + acl_foreach(iter, xml) { + ACL_XML2_NODE *node = (ACL_XML2_NODE*) iter.data; + printf(">>tag: %s\n", node->ltag); + } + + printf("-------------- list xml's all tags end ----------------\r\n"); + + printf("Enter any key to continue ...\r\n"); + getchar(); +} + +static void test_getElementsByTagName(ACL_XML2 *xml, const char *tag) +{ + ACL_ARRAY *a; + ACL_ITER iter; + + printf("--------- acl_xml2_getElementsByTagName ------------\n"); + + a = acl_xml2_getElementsByTagName(xml, tag); + if (a) { + /* 遍历结果集 */ + acl_foreach(iter, a) { + ACL_XML2_NODE *node = (ACL_XML2_NODE*) iter.data; + printf("tag->%s, text: %s\n", node->ltag, node->text); + xml_node_attrs(node, 1); + walk_xml_node(node, 1); + } + + /* 释放数组对象 */ + acl_xml2_free_array(a); + } + else + printf(">>> not exist, tag: %s\r\n", tag); + + printf("--------- acl_xml2_getElementsByTagName end --------\n"); + + printf("Enter any key to continue ...\r\n"); + getchar(); +} + +static ACL_XML2_NODE *test_getElementById(ACL_XML2 *xml, const char *id) +{ + ACL_ITER iter1; + ACL_XML2_NODE *node = acl_xml2_getElementById(xml, id); + + printf("--------------- acl_xml2_getElementById ---------------\r\n"); + if (node == NULL) { + printf(">>>id: %s not found\r\n", id); + return NULL; + } + + printf("tag-> %s, text: %s\n", node->ltag, node->text); + + /* 遍历该 xml 结点的属性 */ + acl_foreach(iter1, node->attr_list) { + ACL_XML2_ATTR *attr = (ACL_XML2_ATTR*) iter1.data; + printf("\tattr_name: %s, attr_value: %s\n", + attr->name, attr->value); + } + + printf("----------- the id2_2's next node is ------------\n"); + + node = acl_xml2_node_next(node); + + if (node) { + printf("-------------- walk node ----------------\n"); + + /* 遍历该 xml 结点的属性 */ + acl_foreach(iter1, node->attr_list) { + ACL_XML2_ATTR *attr = (ACL_XML2_ATTR*) iter1.data; + printf("\tattr_name: %s, attr_value: %s\n", + attr->name, attr->value); + } + + } else + printf("-------------- null node ----------------\n"); + + printf("Enter any key to continue ...\r\n"); + getchar(); + + return node; +} + +static ACL_XML2 *get_xml(int once, const char *data, + const char* root, int multi_root) +{ + size_t size = strlen(data) * 4; + ACL_VSTRING *vbuf = acl_vstring_alloc(size); + ACL_XML2 *xml; + const char *left; + + printf("--------------------- xml data ------------------------\r\n"); + printf("{%s}\r\n", data); + printf("--------------------- xml data end --------------------\r\n"); + printf("Enter any key to continue ...\r\n"); + getchar(); + + xml = acl_xml2_alloc(vbuf); + acl_xml2_multi_root(xml, multi_root); + acl_xml2_decode_enable(xml, 1); + acl_xml2_slash(xml, 1); + + if (once) { + /* 一次性地分析完整 xml 数据 */ + ACL_METER_TIME("-------------once begin--------------"); + left = acl_xml2_parse(xml, data); + } else { + /* 每次仅输入一个字节来分析 xml 数据 */ + ACL_METER_TIME("-------------stream begin--------------"); + while (*data != 0) { + char ch2[2]; + + ch2[0] = *data; + ch2[1] = 0; + left = acl_xml2_parse(xml, ch2); + data++; + } + } + + ACL_METER_TIME("-------------end--------------"); + printf("---------------- left data ----------------------------\r\n"); + printf("{%s}\r\n", left ? left : "empty"); + printf("---------------- left data end ------------------------\r\n"); + + printf("Enter any key to continue ...\r\n"); + getchar(); + + if (acl_xml2_is_complete(xml, root)) + printf(">> Yes, the xml complete\n"); + else + printf(">> No, the xml not complete, root tag: %s\n", root); + + printf("Enter any key to continue ...\r\n"); + getchar(); + + return xml; +} + +static void parse_xml(int once, const char *data, + const char* root, int multi_root) +{ + ACL_XML2 *xml = get_xml(once, data, root, multi_root); + ACL_XML2_NODE *node; + int total = xml->node_cnt, left; + const char *ptr; + + /* 遍历所有 xml 节点 */ + walk_xml(xml); + + /* 递归遍历 root 节点的所有子节点 */ + printf("-------------------- walk root node -------------------\r\n"); + walk_xml_node(xml->root, 0); + printf("-------------------- walk root node end ---------------\r\n"); + + printf("Enter any key to continue ...\r\n"); + getchar(); + + /* 根据标签名获得 xml 结点集合 */ + + /* 查询属性名为 name, 属性值为 user 的所有 xml 结点的集合 */ + test_getElementsByTagName(xml, "user"); + + /* 查询属性名为 name, 属性值为 user2_1 的所有 xml 结点的集合 */ + test_getElementsByTagName(xml, "user2_1"); + + /* 查询属性名为 id, 属性值为 id2_2 的所有 xml 结点集合 */ + (void) test_getElementById(xml, "id2_2"); + + /* 查询属性名为 id, 属性值为 id2_3 的所有 xml 结点集合 */ + node = test_getElementById(xml, "id2_3"); + if (node) { + int ndel = 0, node_cnt; + + /* 删除该结点及其子结点 */ + printf(">>>before delete %s, total: %d\n", + node->ltag, xml->node_cnt); + ndel = acl_xml2_node_delete(node); + node_cnt = xml->node_cnt; + printf(">>>after delete id2_3(%d deleted), total: %d\n", + ndel, node_cnt); + } + node = test_getElementById(xml, "id2_3"); + + list_xml_tags(xml); + + printf("----------------- build xml -------------------------\r\n"); + (void) ptr; + //ptr = acl_xml2_build(xml); + //printf("%s, len: %ld, %ld\r\n", ptr, (long) strlen(ptr), + // (long) (acl_vstring_end(xml->vbuf) - ptr)); + printf("----------------- build xml end ---------------------\r\n"); + + /* 释放 xml 对象 */ + acl_vstring_free(xml->vbuf); + left = acl_xml2_free(xml); + + printf("Free all node ok, total(%d), left is: %d\n", total, left); + printf("Enter any key to continue ...\r\n"); + getchar(); +} + +static void test1(void) +{ + const char* data = "\r\n" + "\r\n" + "xmllint\">\r\n" + "]>\r\n" + "hello world!\r\n"; + ACL_XML2 *xml; + ACL_XML2_NODE *node; + const char *encoding, *type, *href; + size_t size = strlen(data) * 3; + ACL_VSTRING *vbuf = acl_vstring_alloc(size); + const char *ptr; + + xml = acl_xml2_alloc(vbuf); + + printf("------------------------------------------------------\r\n"); + + printf("%s\r\n", data); + + acl_xml2_update(xml, data); + + printf("--------------- walk_xml_node ------------------------\r\n"); + + walk_xml_node(xml->root, 0); + + printf("--------------- walk_xml_node end --------------------\r\n"); + + printf("Enter any key to continue ...\r\n"); + getchar(); + + printf("----------------- lookup meta data -------------------\r\n"); + encoding = acl_xml2_getEncoding(xml); + type = acl_xml2_getType(xml); + node = acl_xml2_getElementMeta(xml, "xml-stylesheet"); + if (node) + href = acl_xml2_getElementAttrVal(node, "href"); + else + href = NULL; + + printf("xml encoding: %s\r\n", encoding ? encoding : "null"); + printf("xml type: %s\r\n", type ? type : "null"); + printf("xml href: %s\r\n", href ? href : "null"); + + printf("----------------- lookup meta data end ---------------\r\n"); + + printf("Enter any key to continue ...\r\n"); + getchar(); + test_getElementsByTagName(xml, "root"); + + printf("----------------- build xml -------------------------\r\n"); + (void) ptr; + //ptr = acl_xml2_build(xml); + //printf("%s\r\n", ptr); + printf("----------------- build xml end ---------------------\r\n"); + acl_vstring_free(vbuf); + acl_xml2_free(xml); +} + +#if 0 +static void build_xml(void) +{ + size_t size = 1024; + char *addr = acl_mymalloc(size); + ACL_XML2 *xml = acl_xml2_alloc(addr, size); + ACL_XML2_NODE *node1, *node2, *node3; + const char *buf; + + node1 = acl_xml2_create_node(xml, "users", "text1"); + acl_xml2_node_add_child(xml->root, node1); + (void) acl_xml2_node_add_attr(node1, "name", "users list"); + + node2 = acl_xml2_create_node(xml, "user", "text11"); + acl_xml2_node_add_child(node1, node2); + acl_xml2_node_add_attrs(node2, "name", "user11", "value", "zsx11", NULL); + + node3 = acl_xml2_create_node(xml, "age", "text111"); + acl_xml2_node_add_child(node2, node3); + acl_xml2_node_add_attrs(node3, "name", "user111", "value", "zsx111", NULL); + + node2 = acl_xml2_create_node(xml, "user", "text2"); + acl_xml2_node_add_child(node1, node2); + acl_xml2_node_add_attrs(node2, "name", "value2", "value", "zsx2", NULL); + + node2 = acl_xml2_create_node(xml, "user", "text3"); + acl_xml2_node_add_child(node1, node2); + acl_xml2_node_add_attrs(node2, "name", "value3", "value", "zsx3", NULL); + + printf("--------------------xml string-------------------\r\n"); + buf = acl_xml2_build(xml); + printf("%s\n", buf); + printf("length: %ld, %ld\r\n", (long) strlen(buf), + (long) (xml->ptr - buf)); + printf("--------------------xml string end---------------\r\n"); + + acl_myfree(addr); + acl_xml2_free(xml); + + printf("Enter any key to continue ...\r\n"); + getchar(); +} + +#endif + +static void usage(const char *procname) +{ + printf("usage: %s -h[help]\r\n" + " -s[parse once]\r\n" + " -b benchmark_max\r\n" + " -B build_xml\r\n" + " -t [if test one xml]\r\n" + " -f xml_file\r\n" + " -m[if enable multiple root xml node, default: no]\r\n" + " -p[print] data1|data2|data3|data4|data5|data6|data7\r\n" + " -P [if parse one xml with one data]\r\n" + " -d[parse] data1|data2|data3|data4|data5|data6|data7\r\n", + procname); +} + +#ifdef WIN32 +#define snprintf _snprintf +#endif + +int main(int argc, char *argv[]) +{ + int ch, once = 0, multi_root = 0, benchmark_max = 0; + int parse_one = 0, build = 0, test_one = 0; + const char *data = __data1; + const char* root = "root"; + char filepath[256]; + + acl_msg_stdout_enable(1); + + filepath[0] = 0; + + while ((ch = getopt(argc, argv, "hsp:d:mb:f:PBt")) > 0) { + switch (ch) { + case 'h': + usage(argv[0]); + return (0); + case 't': + test_one = 1; + break; + case 'm': + multi_root = 1; + break; + case 's': + once = 1; + break; + case 'b': + benchmark_max = atoi(optarg); + break; + case 'P': + parse_one = 1; + break; + case 'B': + build = 1; + break; + case 'd': + if (strcasecmp(optarg, "data2") == 0) { + data = __data2; + root = "root"; + } else if (strcasecmp(optarg, "data3") == 0) { + data = __data3; + root = "root"; + } else if (strcasecmp(optarg, "data4") == 0) { + data = __data4; + root = "request"; + } else if (strcasecmp(optarg, "data5") == 0) { + data = __data5; + root = "request"; + } else if (strcasecmp(optarg, "data6") == 0) { + data = __data6; + root = "request"; + } else if (strcasecmp(optarg, "data7") == 0) { + data = __data7; + root = "request"; + } else if (strcasecmp(optarg, "data8") == 0) { + data = __data8; + root = "root"; + } + break; + case 'p': + if (strcasecmp(optarg, "data1") == 0) + printf("%s\n", __data1); + else if (strcasecmp(optarg, "data2") == 0) + printf("%s\n", __data2); + else if (strcasecmp(optarg, "data3") == 0) + printf("%s\n", __data3); + else if (strcasecmp(optarg, "data4") == 0) + printf("%s\n", __data4); + else if (strcasecmp(optarg, "data5") == 0) + printf("%s\n", __data5); + else if (strcasecmp(optarg, "data6") == 0) + printf("%s\n", __data6); + else if (strcasecmp(optarg, "data7") == 0) + printf("%s\n", __data7); + else if (strcasecmp(optarg, "data8") == 0) + printf("%s\n", __data8); + return (0); + case 'f': + snprintf(filepath, sizeof(filepath), "%s", optarg); + break; + default: + break; + } + } + + if (benchmark_max > 0) + parse_xml_benchmark(once, benchmark_max, data); + + if (test_one) + { + test1(); + + printf("Enter any key to continue ...\r\n"); + getchar(); + } + + + if (parse_one) + parse_xml(once, data, root, multi_root); + + if (filepath[0] != 0) + parse_xml_file(filepath); + + if (build) + { + //build_xml(); + } + +#ifdef ACL_MS_WINDOWS + printf("ok, enter any key to exit ...\n"); + getchar(); +#endif + return 0; +} diff --git a/lib_acl/samples/xml/xml7/xml.c b/lib_acl/samples/xml/xml7/xml.c index d350ed52f..eb2481bf2 100644 --- a/lib_acl/samples/xml/xml7/xml.c +++ b/lib_acl/samples/xml/xml7/xml.c @@ -38,7 +38,7 @@ static int parse_xml_file(const char *filepath) len *= 4; - xml = acl_xml2_mmap_file(mmap_file, len, 10, 1, NULL); + xml = acl_xml2_mmap_file(mmap_file, len, 10, NULL); len = 0; while (1) { @@ -58,8 +58,9 @@ static int parse_xml_file(const char *filepath) if (ptr == NULL) printf("acl_xml2_build error\r\n"); - len = xml->ptr - ptr; - acl_vstream_printf(">>>build xml's size:%lld\r\n", len); + len = acl_vstring_end(xml->vbuf) - ptr; + acl_vstream_printf(">>>build xml's size:%lld, strlen: %ld\r\n", + len, (long) strlen(ptr)); acl_vstream_printf(">>> ptr: {%s}\r\n", ptr); if (acl_vstream_writen(out, ptr, len) == ACL_VSTREAM_EOF) { diff --git a/lib_acl/src/event/events_epoll_thr.c b/lib_acl/src/event/events_epoll_thr.c index e3ad3b695..dd1a50404 100644 --- a/lib_acl/src/event/events_epoll_thr.c +++ b/lib_acl/src/event/events_epoll_thr.c @@ -22,6 +22,7 @@ #include "stdlib/acl_msg.h" #include "stdlib/acl_ring.h" #include "stdlib/acl_vstream.h" +#include "net/acl_sane_socket.h" #include "event/acl_events.h" #endif @@ -42,36 +43,34 @@ typedef struct EVENT_EPOLL_THR { int handle; } EVENT_EPOLL_THR; -static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream, +static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *fp, int timeout, ACL_EVENT_NOTIFY_RDWR callback, void *context) { const char *myname = "event_enable_read"; - EVENT_EPOLL_THR *event_thr = (EVENT_EPOLL_THR *) eventp; + EVENT_EPOLL_THR *evthr = (EVENT_EPOLL_THR *) eventp; ACL_EVENT_FDTABLE *fdp; - ACL_SOCKET sockfd; + ACL_SOCKET fd; struct epoll_event ev; int fd_ready; - if (ACL_VSTREAM_BFRD_CNT(stream) > 0 - || (stream->flag & ACL_VSTREAM_FLAG_BAD)) - { + if (ACL_VSTREAM_BFRD_CNT(fp) > 0 || (fp->flag & ACL_VSTREAM_FLAG_BAD)) { fd_ready = 1; } else fd_ready = 0; - sockfd = ACL_VSTREAM_SOCK(stream); - fdp = (ACL_EVENT_FDTABLE*) stream->fdp; + fd = ACL_VSTREAM_SOCK(fp); + fdp = (ACL_EVENT_FDTABLE*) fp->fdp; if (fdp == NULL) { fdp = event_fdtable_alloc(); fdp->listener = 0; - fdp->stream = stream; - stream->fdp = (void *) fdp; + fdp->stream = fp; + fp->fdp = (void *) fdp; } else if (fdp->flag & EVENT_FDTABLE_FLAG_WRITE) acl_msg_panic("%s(%d), %s: fd %d: multiple I/O request", - __FILE__, __LINE__, myname, sockfd); + __FILE__, __LINE__, myname, fd); else { fdp->listener = 0; - fdp->stream = stream; + fdp->stream = fp; } if (fdp->r_callback != callback || fdp->r_context != context) { @@ -93,7 +92,7 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream, return; } - stream->nrefer++; + fp->nrefer++; fdp->flag = EVENT_FDTABLE_FLAG_READ | EVENT_FDTABLE_FLAG_EXPT; #if 0 @@ -104,67 +103,76 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream, ev.data.u64 = 0; /* avoid valgrind warning */ ev.data.ptr = fdp; - THREAD_LOCK(&event_thr->event.tb_mutex); + THREAD_LOCK(&evthr->event.tb_mutex); fdp->fdidx = eventp->fdcnt; eventp->fdtabs[eventp->fdcnt++] = fdp; if (fd_ready) { - if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, - sockfd, &ev) < 0) - { + if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) { if (errno == EEXIST) acl_msg_warn("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); - else - acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); + myname, acl_last_serror(), fd); + else if (errno == EBADF && acl_getsocktype(fd) < 0) { + acl_msg_error("%s: epool_ctl: %s, fd: %d", + myname, acl_last_serror(), fd); + ACL_VSTREAM_SET_SOCK(fp, ACL_SOCKET_INVALID); + fp->flag |= ACL_VSTREAM_FLAG_ERR; + } else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d, " + "epfd: %d", myname, acl_last_serror(), + fd, evthr->handle); } - THREAD_UNLOCK(&event_thr->event.tb_mutex); + THREAD_UNLOCK(&evthr->event.tb_mutex); - if (event_thr->event.blocked && event_thr->event.evdog - && event_dog_client(event_thr->event.evdog) != stream) + if (evthr->event.blocked && evthr->event.evdog + && event_dog_client(evthr->event.evdog) != fp) { - event_dog_notify(event_thr->event.evdog); + event_dog_notify(evthr->event.evdog); } - } else { - THREAD_UNLOCK(&event_thr->event.tb_mutex); - if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, - sockfd, &ev) < 0) - { - if (errno == EEXIST) - acl_msg_warn("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); - else - acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); - } + return; + } + + THREAD_UNLOCK(&evthr->event.tb_mutex); + + if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) { + if (errno == EEXIST) + acl_msg_warn("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), fd); + else if (errno == EBADF && acl_getsocktype(fd) < 0) { + acl_msg_error("%s: epool_ctl: %s, fd: %d", + myname, acl_last_serror(), fd); + ACL_VSTREAM_SET_SOCK(fp, ACL_SOCKET_INVALID); + fp->flag |= ACL_VSTREAM_FLAG_ERR; + } else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d, epfd: %d", + myname, acl_last_serror(), fd, evthr->handle); } } -static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *stream, +static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *fp, int timeout, ACL_EVENT_NOTIFY_RDWR callback, void *context) { const char *myname = "event_enable_listen"; - EVENT_EPOLL_THR *event_thr = (EVENT_EPOLL_THR *) eventp; + EVENT_EPOLL_THR *evthr = (EVENT_EPOLL_THR *) eventp; ACL_EVENT_FDTABLE *fdp; - ACL_SOCKET sockfd; + ACL_SOCKET fd; struct epoll_event ev; - sockfd = ACL_VSTREAM_SOCK(stream); - fdp = (ACL_EVENT_FDTABLE*) stream->fdp; + fd = ACL_VSTREAM_SOCK(fp); + fdp = (ACL_EVENT_FDTABLE*) fp->fdp; if (fdp == NULL) { fdp = event_fdtable_alloc(); - fdp->stream = stream; + fdp->stream = fp; fdp->listener = 1; - stream->fdp = (void *) fdp; + fp->fdp = (void *) fdp; } else if (fdp->flag & EVENT_FDTABLE_FLAG_WRITE) acl_msg_panic("%s(%d)->%s: fd %d: multiple I/O request", - __FILE__, __LINE__, myname, sockfd); + __FILE__, __LINE__, myname, fd); else { - fdp->stream = stream; + fdp->stream = fp; fdp->listener = 1; } @@ -185,57 +193,57 @@ static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *stream, return; fdp->flag = EVENT_FDTABLE_FLAG_READ | EVENT_FDTABLE_FLAG_EXPT; - stream->nrefer++; + fp->nrefer++; ev.events = EPOLLIN | EPOLLHUP | EPOLLERR; ev.data.u64 = 0; /* avoid valgrind warning */ ev.data.ptr = fdp; - THREAD_LOCK(&event_thr->event.tb_mutex); + THREAD_LOCK(&evthr->event.tb_mutex); fdp->fdidx = eventp->fdcnt; eventp->fdtabs[eventp->fdcnt++] = fdp; - THREAD_UNLOCK(&event_thr->event.tb_mutex); + THREAD_UNLOCK(&evthr->event.tb_mutex); - if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, sockfd, &ev) < 0) { + if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) { if (errno == EEXIST) acl_msg_warn("%s: epool_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); + myname, acl_last_serror(), fd); else acl_msg_fatal("%s: epool_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); + myname, acl_last_serror(), fd); } } -static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream, +static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *fp, int timeout, ACL_EVENT_NOTIFY_RDWR callback, void *context) { const char *myname = "event_enable_write"; - EVENT_EPOLL_THR *event_thr = (EVENT_EPOLL_THR *) eventp; + EVENT_EPOLL_THR *evthr = (EVENT_EPOLL_THR *) eventp; ACL_EVENT_FDTABLE *fdp; - ACL_SOCKET sockfd; + ACL_SOCKET fd; struct epoll_event ev; int fd_ready; - if ((stream->flag & ACL_VSTREAM_FLAG_BAD)) + if ((fp->flag & ACL_VSTREAM_FLAG_BAD)) fd_ready = 1; else fd_ready = 0; - sockfd = ACL_VSTREAM_SOCK(stream); - fdp = (ACL_EVENT_FDTABLE*) stream->fdp; + fd = ACL_VSTREAM_SOCK(fp); + fdp = (ACL_EVENT_FDTABLE*) fp->fdp; if (fdp == NULL) { fdp = event_fdtable_alloc(); fdp->listener = 0; - fdp->stream = stream; - stream->fdp = (void *) fdp; + fdp->stream = fp; + fp->fdp = (void *) fdp; } else if (fdp->flag & EVENT_FDTABLE_FLAG_READ) acl_msg_panic("%s(%d)->%s: fd %d: multiple I/O request", - __FILE__, __LINE__, myname, sockfd); + __FILE__, __LINE__, myname, fd); else { fdp->listener = 0; - fdp->stream = stream; + fdp->stream = fp; } if (fdp->w_callback != callback || fdp->w_context != context) { @@ -255,43 +263,51 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream, return; fdp->flag = EVENT_FDTABLE_FLAG_WRITE | EVENT_FDTABLE_FLAG_EXPT; - stream->nrefer++; + fp->nrefer++; ev.events = EPOLLIN | EPOLLHUP | EPOLLERR; ev.data.u64 = 0; /* avoid valgrind warning */ ev.data.ptr = fdp; - THREAD_LOCK(&event_thr->event.tb_mutex); + THREAD_LOCK(&evthr->event.tb_mutex); fdp->fdidx = eventp->fdcnt; eventp->fdtabs[eventp->fdcnt++] = fdp; if (fd_ready) { - if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, - sockfd, &ev) < 0) - { + if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) { if (errno == EEXIST) acl_msg_warn("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); - else - acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); + myname, acl_last_serror(), fd); + else if (errno == EBADF && acl_getsocktype(fd) < 0) { + acl_msg_error("%s: epool_ctl: %s, fd: %d", + myname, acl_last_serror(), fd); + ACL_VSTREAM_SET_SOCK(fp, ACL_SOCKET_INVALID); + fp->flag |= ACL_VSTREAM_FLAG_ERR; + } else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d, " + "epfd: %d", myname, acl_last_serror(), + fd, evthr->handle); } - THREAD_UNLOCK(&event_thr->event.tb_mutex); - } else { - THREAD_UNLOCK(&event_thr->event.tb_mutex); + THREAD_UNLOCK(&evthr->event.tb_mutex); + return; + } - if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, - sockfd, &ev) < 0) - { - if (errno == EEXIST) - acl_msg_warn("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); - else - acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); - } + THREAD_UNLOCK(&evthr->event.tb_mutex); + + if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) { + if (errno == EEXIST) + acl_msg_warn("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), fd); + else if (errno == EBADF && acl_getsocktype(fd) < 0) { + acl_msg_error("%s: epool_ctl: %s, fd: %d", + myname, acl_last_serror(), fd); + ACL_VSTREAM_SET_SOCK(fp, ACL_SOCKET_INVALID); + fp->flag |= ACL_VSTREAM_FLAG_ERR; + } else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d, epfd: %d", + myname, acl_last_serror(), fd, evthr->handle); } } @@ -356,7 +372,7 @@ static void event_disable_readwrite(ACL_EVENT *eventp, ACL_VSTREAM *stream) acl_msg_warn("%s: epoll_ctl: %s, fd: %d", myname, acl_last_serror(), sockfd); else - acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", + acl_msg_error("%s: epoll_ctl: %s, fd: %d", myname, acl_last_serror(), sockfd); } diff --git a/lib_acl/src/stdlib/acl_vstream.c b/lib_acl/src/stdlib/acl_vstream.c index 185085aab..0b2b7940e 100644 --- a/lib_acl/src/stdlib/acl_vstream.c +++ b/lib_acl/src/stdlib/acl_vstream.c @@ -1035,7 +1035,7 @@ int acl_vstream_gets_peek(ACL_VSTREAM *fp, ACL_VSTRING *buf, int *ready) if (fp->read_ready) { if (read_once(fp) <= 0) { n = (int) LEN(buf) - n; - return n > 0 ? n : ACL_VSTREAM_EOF; + return n >= 0 ? n : ACL_VSTREAM_EOF; } } @@ -1106,7 +1106,7 @@ int acl_vstream_gets_nonl_peek(ACL_VSTREAM *fp, ACL_VSTRING *buf, int *ready) if (read_once(fp) <= 0) { n = (int) LEN(buf) - n; - return n > 0 ? n : ACL_VSTREAM_EOF; + return n >= 0 ? n : ACL_VSTREAM_EOF; } } @@ -1168,7 +1168,7 @@ int acl_vstream_readn_peek(ACL_VSTREAM *fp, ACL_VSTRING *buf, if (fp->read_ready) { if (read_once(fp) <= 0) { int n = cnt_saved - cnt; - return n > 0 ? n : ACL_VSTREAM_EOF; + return n >= 0 ? n : ACL_VSTREAM_EOF; } } @@ -1219,7 +1219,7 @@ int acl_vstream_read_peek(ACL_VSTREAM *fp, ACL_VSTRING *buf) if (fp->read_ready) { if (read_once(fp) <= 0) { n = (int) LEN(buf) - n; - return n > 0 ? n : ACL_VSTREAM_EOF; + return n >= 0 ? n : ACL_VSTREAM_EOF; } } diff --git a/lib_acl/src/stdlib/acl_vstring.c b/lib_acl/src/stdlib/acl_vstring.c index b9009cb0e..185f97544 100644 --- a/lib_acl/src/stdlib/acl_vstring.c +++ b/lib_acl/src/stdlib/acl_vstring.c @@ -17,9 +17,14 @@ #include "stdlib/acl_mymalloc.h" #include "stdlib/acl_msg.h" +#include "stdlib/acl_sys_patch.h" #include "stdlib/acl_vbuf_print.h" #include "stdlib/acl_vstring.h" +#ifdef ACL_UNIX +#include +#endif + #endif #include "charmap.h" @@ -28,25 +33,41 @@ /* vstring_extend - variable-length string buffer extension policy */ -static void vstring_extend(ACL_VBUF *bp, int incr) +static int vstring_extend(ACL_VBUF *bp, ssize_t incr) { const char *myname = "vstring_extend"; - unsigned used = (unsigned) (bp->ptr - bp->data); - int new_len; - ACL_VSTRING *vp = (ACL_VSTRING *) bp->ctx; + ssize_t used = (unsigned) (bp->ptr - bp->data), new_len; + ACL_VSTRING *vp = (ACL_VSTRING *) bp; - if (vp->maxlen > 0 && (int) ACL_VSTRING_LEN(vp) > vp->maxlen) - acl_msg_warn("%s(%d), %s: reached the maxlen: %d", - __FILE__, __LINE__, myname, vp->maxlen); + if (vp->maxlen > 0 && (ssize_t) ACL_VSTRING_LEN(vp) >= vp->maxlen) { + ACL_VSTRING_AT_OFFSET(vp, vp->maxlen - 1); + ACL_VSTRING_TERMINATE(vp); + acl_msg_warn("%s(%d), %s: overflow maxlen: %ld, %ld", + __FILE__, __LINE__, myname, (long) vp->maxlen, + (long) ACL_VSTRING_LEN(vp)); + bp->flags |= ACL_VBUF_FLAG_EOF; + return ACL_VBUF_EOF; + } + +#ifdef ACL_WINDOWS + if (vp->fd == ACL_FILE_INVALID && (bp->flags & ACL_VBUF_FLAG_FIXED)) +#else + if (vp->fd < 0 && (bp->flags & ACL_VBUF_FLAG_FIXED)) +#endif + { + acl_msg_warn("%s(%d), %s: can't extend fixed buffer", + __FILE__, __LINE__, myname); + return ACL_VBUF_EOF; + } /* * Note: vp->vbuf.len is the current buffer size (both on entry and on * exit of this routine). We round up the increment size to the buffer * size to avoid silly little buffer increments. With really large - * strings we might want to abandon the length doubling strategy, and go - * to fixed increments. + * strings we might want to abandon the length doubling strategy, and + * go to fixed increments. */ - /* new_len = bp->len + (bp->len > incr ? bp->len : incr); */ +#ifdef INCR_NO_DOUBLE /* below come from redis-server/sds.c/sdsMakeRoomFor, which can * avoid memory double growing too large --- 2015.2.2, zsx */ @@ -55,6 +76,12 @@ static void vstring_extend(ACL_VBUF *bp, int incr) new_len *= 2; else new_len += MAX_PREALLOC; +#else + new_len = bp->len + (bp->len > incr ? bp->len : incr); +#endif + + if (vp->maxlen > 0 && new_len > vp->maxlen) + new_len = vp->maxlen; if (vp->slice) bp->data = (unsigned char *) acl_slice_pool_realloc( @@ -65,11 +92,24 @@ static void vstring_extend(ACL_VBUF *bp, int incr) vp->dbuf, new_len); memcpy(bp->data, data, used); acl_dbuf_pool_free(vp->dbuf, data); + } else if (vp->fd != ACL_FILE_INVALID) { + acl_off_t off = new_len - 1; + if (acl_lseek(vp->fd, off, SEEK_SET) != (acl_off_t) off) + acl_msg_fatal("lseek failed: %s, off: %lld", + acl_last_serror(), off); + if (acl_file_write(vp->fd, "\0", 1, 0, NULL, NULL) + == ACL_VSTREAM_EOF) + { + acl_msg_fatal("write error: %s", acl_last_serror()); + } } else bp->data = (unsigned char *) acl_myrealloc(bp->data, new_len); + bp->len = new_len; bp->ptr = bp->data + used; bp->cnt = bp->len - used; + + return 0; } /* vstring_buf_get_ready - vbuf callback for read buffer empty condition */ @@ -84,21 +124,21 @@ static int vstring_buf_get_ready(ACL_VBUF *buf acl_unused) static int vstring_buf_put_ready(ACL_VBUF *bp) { - vstring_extend(bp, 0); - return 0; + return vstring_extend(bp, 0); } /* vstring_buf_space - vbuf callback to reserve space */ -static int vstring_buf_space(ACL_VBUF *bp, int len) +static int vstring_buf_space(ACL_VBUF *bp, ssize_t len) { - int need; + ssize_t need; if (len < 0) - acl_msg_panic("vstring_buf_space: bad length %d", len); + acl_msg_panic("vstring_buf_space: bad length %ld", (long) len); if ((need = len - bp->cnt) > 0) - vstring_extend(bp, need); - return 0; + return vstring_extend(bp, need); + else + return 0; } void acl_vstring_init(ACL_VSTRING *vp, size_t len) @@ -117,7 +157,7 @@ void acl_vstring_init(ACL_VSTRING *vp, size_t len) vp->vbuf.get_ready = vstring_buf_get_ready; vp->vbuf.put_ready = vstring_buf_put_ready; vp->vbuf.space = vstring_buf_space; - vp->vbuf.ctx = vp; + vp->vbuf.ctx = NULL; vp->maxlen = 0; vp->slice = NULL; } @@ -129,6 +169,14 @@ void acl_vstring_free_buf(ACL_VSTRING *vp) if (vp->slice) acl_slice_pool_free(__FILE__, __LINE__, vp->vbuf.data); +#ifdef ACL_UNIX + if (vp->fd != ACL_FILE_INVALID) { + if (vp->maxlen > 0 && munmap(vp->vbuf.data, vp->maxlen) < 0) + acl_msg_error("%s(%d), %s: munmap error %s", + __FILE__, __LINE__, __FUNCTION__, + acl_last_serror()); + } +#endif else if (vp->dbuf == NULL) acl_myfree(vp->vbuf.data); vp->vbuf.data = NULL; @@ -162,6 +210,7 @@ ACL_VSTRING *acl_vstring_slice_alloc(ACL_SLICE_POOL *slice, size_t len) vp->vbuf.data = (unsigned char *) acl_mymalloc(len); } + vp->fd = ACL_FILE_INVALID; vp->vbuf.flags = 0; vp->vbuf.len = (int) len; ACL_VSTRING_RESET(vp); @@ -169,8 +218,9 @@ ACL_VSTRING *acl_vstring_slice_alloc(ACL_SLICE_POOL *slice, size_t len) vp->vbuf.get_ready = vstring_buf_get_ready; vp->vbuf.put_ready = vstring_buf_put_ready; vp->vbuf.space = vstring_buf_space; - vp->vbuf.ctx = vp; + vp->vbuf.ctx = NULL; vp->maxlen = 0; + return vp; } @@ -179,12 +229,14 @@ ACL_VSTRING *acl_vstring_dbuf_alloc(ACL_DBUF_POOL *dbuf, size_t len) ACL_VSTRING *vp; if (len < 1) - acl_msg_panic("acl_vstring_alloc: bad length %d", (int) len); + len = 64; + if (dbuf) { vp = (ACL_VSTRING*) acl_dbuf_pool_alloc(dbuf, sizeof(*vp)); vp->dbuf = dbuf; vp->slice = NULL; - vp->vbuf.data = (unsigned char *) acl_dbuf_pool_alloc(dbuf, len); + vp->vbuf.data = (unsigned char *) + acl_dbuf_pool_alloc(dbuf, len); } else { vp = (ACL_VSTRING *) acl_mymalloc(sizeof(*vp)); vp->slice = NULL; @@ -192,6 +244,7 @@ ACL_VSTRING *acl_vstring_dbuf_alloc(ACL_DBUF_POOL *dbuf, size_t len) vp->vbuf.data = (unsigned char *) acl_mymalloc(len); } + vp->fd = ACL_FILE_INVALID; vp->vbuf.flags = 0; vp->vbuf.len = (int) len; ACL_VSTRING_RESET(vp); @@ -199,8 +252,60 @@ ACL_VSTRING *acl_vstring_dbuf_alloc(ACL_DBUF_POOL *dbuf, size_t len) vp->vbuf.get_ready = vstring_buf_get_ready; vp->vbuf.put_ready = vstring_buf_put_ready; vp->vbuf.space = vstring_buf_space; - vp->vbuf.ctx = vp; + vp->vbuf.ctx = NULL; vp->maxlen = 0; + + return vp; +} + +static void vstring_buf_init(ACL_VSTRING *vp, ssize_t init_len) +{ + if (acl_lseek(vp->fd, init_len, SEEK_SET) != init_len) + acl_msg_fatal("lseek failed: %s, off: %ld", + acl_last_serror(), (long) init_len); + if (acl_file_write(vp->fd, "\0", 1, 0, NULL, NULL) == ACL_VSTREAM_EOF) + acl_msg_fatal("write error: %s", acl_last_serror()); + +#ifdef ACL_UNIX + vp->vbuf.data = (unsigned char*) mmap(NULL, vp->maxlen, + PROT_READ | PROT_WRITE, MAP_SHARED, vp->fd, 0); + if (vp->vbuf.data == MAP_FAILED) + acl_msg_fatal("mmap error: %s", acl_last_serror()); +#else + acl_msg_fatal("%s: not supported yet!", __FUNCTION__); +#endif +} + +ACL_VSTRING *acl_vstring_mmap_alloc(ACL_FILE_HANDLE fd, + ssize_t max_len, ssize_t init_len) +{ + const char *myname = "acl_vstring_mmap_alloc"; + ACL_VSTRING *vp; + + if (init_len < 1) + acl_msg_panic("%s: bad length %ld", myname, (long) init_len); + + if (max_len < init_len) + max_len = init_len; + + vp = (ACL_VSTRING *) acl_mymalloc(sizeof(*vp)); + + vp->fd = fd; + vp->slice = NULL; + vp->dbuf = NULL; + + vp->vbuf.flags = 0; + vp->vbuf.len = init_len; + vp->vbuf.get_ready = vstring_buf_get_ready; + vp->vbuf.put_ready = vstring_buf_put_ready; + vp->vbuf.space = vstring_buf_space; + vp->vbuf.ctx = NULL; + vp->maxlen = max_len; + + vstring_buf_init(vp, init_len); + + ACL_VSTRING_RESET(vp); + vp->vbuf.data[0] = 0; return vp; } @@ -208,15 +313,16 @@ ACL_VSTRING *acl_vstring_dbuf_alloc(ACL_DBUF_POOL *dbuf, size_t len) void acl_vstring_free(ACL_VSTRING *vp) { - if (vp->slice) { - if (vp->vbuf.data) - acl_slice_pool_free(__FILE__, __LINE__, vp->vbuf.data); + acl_vstring_free_buf(vp); + + if (vp->slice) acl_slice_pool_free(__FILE__, __LINE__, vp); - } else if (vp->dbuf == NULL) { - if (vp->vbuf.data) - acl_myfree(vp->vbuf.data); +#ifdef ACL_UNIX + else if (vp->fd != ACL_FILE_INVALID) + acl_myfree(vp); +#endif + else if (vp->dbuf == NULL) acl_myfree(vp); - } } /* acl_vstring_ctl - modify memory management policy */ @@ -235,8 +341,8 @@ void acl_vstring_ctl(ACL_VSTRING *vp,...) case ACL_VSTRING_CTL_MAXLEN: vp->maxlen = va_arg(ap, int); if (vp->maxlen < 0) - acl_msg_panic("%s: bad max length %d", - myname, vp->maxlen); + acl_msg_panic("%s: bad max length %ld", + myname, (long) vp->maxlen); break; } } @@ -258,52 +364,36 @@ ACL_VSTRING *acl_vstring_truncate(ACL_VSTRING *vp, size_t len) ACL_VSTRING *acl_vstring_strcpy(ACL_VSTRING *vp, const char *src) { - ACL_VSTRING_RESET(vp); - - while (*src) { - ACL_VSTRING_ADDCH(vp, *src); - src++; - } - ACL_VSTRING_TERMINATE(vp); - return vp; + return acl_vstring_memcpy(vp, src, strlen(src)); } /* acl_vstring_strncpy - copy string of limited length */ ACL_VSTRING *acl_vstring_strncpy(ACL_VSTRING *vp, const char *src, size_t len) { - ACL_VSTRING_RESET(vp); + size_t n = strlen(src); - while (len-- > 0 && *src) { - ACL_VSTRING_ADDCH(vp, *src); - src++; - } - ACL_VSTRING_TERMINATE(vp); - return vp; + if (n > len) + n = len; + return acl_vstring_memcpy(vp, src, n); } /* acl_vstring_strcat - append string */ ACL_VSTRING *acl_vstring_strcat(ACL_VSTRING *vp, const char *src) { - while (*src) { - ACL_VSTRING_ADDCH(vp, *src); - src++; - } - ACL_VSTRING_TERMINATE(vp); - return vp; + return acl_vstring_memcat(vp, src, strlen(src)); } /* acl_vstring_strncat - append string of limited length */ ACL_VSTRING *acl_vstring_strncat(ACL_VSTRING *vp, const char *src, size_t len) { - while (len-- > 0 && *src) { - ACL_VSTRING_ADDCH(vp, *src); - src++; - } - ACL_VSTRING_TERMINATE(vp); - return vp; + size_t n = strlen(src); + + if (n > len) + n = len; + return acl_vstring_memcat(vp, src, n); } /* acl_vstring_memcpy - copy buffer of limited length */ @@ -313,10 +403,27 @@ ACL_VSTRING *acl_vstring_memcpy(ACL_VSTRING *vp, const char *src, size_t len) ACL_VSTRING_RESET(vp); if (len > 0) { - ACL_VSTRING_SPACE(vp, (int) len); - memcpy(acl_vstring_str(vp), src, len); - ACL_VSTRING_AT_OFFSET(vp, (int) len); + ssize_t n; + + ACL_VSTRING_SPACE(vp, (ssize_t) len); + + n = acl_vstring_avail(vp); + + if ((size_t) n >= len) + n = (ssize_t) len; + else + acl_msg_warn("%s(%d): space not enough, avail: %ld, " + "len: %ld", __FUNCTION__, __LINE__, + (long) n, (long) len); + + if (n > 0) { + memcpy(acl_vstring_str(vp), src, n); + ACL_VSTRING_AT_OFFSET(vp, n); + } else + acl_msg_warn("%s(%d): no space, avail: 0, len: %ld", + __FUNCTION__, __LINE__, (long) len); } + ACL_VSTRING_TERMINATE(vp); return vp; } @@ -336,19 +443,34 @@ ACL_VSTRING *acl_vstring_memmove(ACL_VSTRING *vp, const char *src, size_t len) ACL_VSTRING_AT_OFFSET(vp, (int) len); ACL_VSTRING_TERMINATE(vp); return vp; - } else { - /* 说明不是同一内存区间的数据移动 */ - char *ptr = acl_mymalloc(len); - - memcpy(ptr, src, len); - acl_myfree(vp->vbuf.data); - vp->vbuf.data = (unsigned char *) ptr; - vp->vbuf.len = (int) len; - ACL_VSTRING_AT_OFFSET(vp, (int) len); - ACL_VSTRING_TERMINATE(vp); - vp->maxlen = 0; - return vp; } + + /* 说明不是同一内存区间的数据移动 */ + + acl_vstring_free_buf(vp); + + if (vp->slice != NULL) + vp->vbuf.data = (unsigned char *) acl_slice_pool_alloc( + __FILE__, __LINE__, vp->slice, len); + else if (vp->dbuf != NULL) + vp->vbuf.data = (unsigned char *) + acl_dbuf_pool_alloc(vp->dbuf, len); +#ifdef ACL_UNIX + else if (vp->fd != ACL_FILE_INVALID) { + if (len > (size_t) vp->maxlen) + vp->maxlen = (ssize_t) len; + vstring_buf_init(vp, len); + } +#endif + else + vp->vbuf.data = acl_mymalloc(len); + + memcpy(vp->vbuf.data, src, len); + vp->vbuf.len = (ssize_t) len; + ACL_VSTRING_AT_OFFSET(vp, len); + ACL_VSTRING_TERMINATE(vp); + + return vp; } /* acl_vstring_memcat - append buffer of limited length */ @@ -356,11 +478,28 @@ ACL_VSTRING *acl_vstring_memmove(ACL_VSTRING *vp, const char *src, size_t len) ACL_VSTRING *acl_vstring_memcat(ACL_VSTRING *vp, const char *src, size_t len) { if (len > 0) { - ACL_VSTRING_SPACE(vp, (int) len); - memcpy(acl_vstring_end(vp), src, len); - len += ACL_VSTRING_LEN(vp); - ACL_VSTRING_AT_OFFSET(vp, (int) len); + ssize_t n; + + ACL_VSTRING_SPACE(vp, (ssize_t) len); + + n = acl_vstring_avail(vp); + + if ((size_t) n >= len) + n = (ssize_t) len; + else + acl_msg_warn("%s(%d): space not enough, avail: %ld, " + "len: %ld", __FUNCTION__, __LINE__, + (long) n, (long) len); + + if (n > 0 ) { + memcpy(acl_vstring_end(vp), src, n); + n += ACL_VSTRING_LEN(vp); + ACL_VSTRING_AT_OFFSET(vp, n); + } else + acl_msg_warn("%s(%d): no space, avail: 0, len: %ld", + __FUNCTION__, __LINE__, (long) len); } + ACL_VSTRING_TERMINATE(vp); return vp; } @@ -509,7 +648,7 @@ ACL_VSTRING *acl_vstring_insert(ACL_VSTRING *vp, size_t start, const char *buf, size_t len) { const char *myname = "acl_vstring_insert"; - size_t new_len; + size_t new_len, n; /* * Sanity check. @@ -522,13 +661,21 @@ ACL_VSTRING *acl_vstring_insert(ACL_VSTRING *vp, size_t start, * Move the existing content and copy the new content. */ new_len = ACL_VSTRING_LEN(vp) + len; - ACL_VSTRING_SPACE(vp, (int) len); - memmove(acl_vstring_str(vp) + start + len, - acl_vstring_str(vp) + start, - ACL_VSTRING_LEN(vp) - start); - memcpy(acl_vstring_str(vp) + start, buf, len); - ACL_VSTRING_AT_OFFSET(vp, (int) new_len); - ACL_VSTRING_TERMINATE(vp); + ACL_VSTRING_SPACE(vp, (ssize_t) len); + + n = acl_vstring_avail(vp); + if (len > (size_t) n) + len = n; + + if (len > 0) { + memmove(acl_vstring_str(vp) + start + len, + acl_vstring_str(vp) + start, + ACL_VSTRING_LEN(vp) - start); + memcpy(acl_vstring_str(vp) + start, buf, len); + ACL_VSTRING_AT_OFFSET(vp, (int) new_len); + ACL_VSTRING_TERMINATE(vp); + } + return vp; } @@ -536,17 +683,26 @@ ACL_VSTRING *acl_vstring_insert(ACL_VSTRING *vp, size_t start, ACL_VSTRING *acl_vstring_prepend(ACL_VSTRING *vp, const char *buf, size_t len) { - ssize_t new_len; + ssize_t new_len, n; /* * Move the existing content and copy the new content. */ new_len = (ssize_t) (ACL_VSTRING_LEN(vp) + len); ACL_VSTRING_SPACE(vp, (int) len); - memmove(acl_vstring_str(vp) + len, acl_vstring_str(vp), ACL_VSTRING_LEN(vp)); - memcpy(acl_vstring_str(vp), buf, len); - ACL_VSTRING_AT_OFFSET(vp, new_len); - ACL_VSTRING_TERMINATE(vp); + + n = acl_vstring_avail(vp); + if (len > (size_t) n) + len = (size_t) n; + + if (len > 0) { + memmove(acl_vstring_str(vp) + len, acl_vstring_str(vp), + ACL_VSTRING_LEN(vp)); + memcpy(acl_vstring_str(vp), buf, len); + ACL_VSTRING_AT_OFFSET(vp, new_len); + ACL_VSTRING_TERMINATE(vp); + } + return vp; } diff --git a/lib_acl/src/stdlib/memory/vstring_pool.c b/lib_acl/src/stdlib/memory/vstring_pool.c index 2bcfc2b3f..91ab4d4d1 100644 --- a/lib_acl/src/stdlib/memory/vstring_pool.c +++ b/lib_acl/src/stdlib/memory/vstring_pool.c @@ -57,12 +57,12 @@ static int vstring_buf_put_ready(ACL_VBUF *bp) return (0); } -static int vstring_buf_space(ACL_VBUF *bp, int len) +static int vstring_buf_space(ACL_VBUF *bp, ssize_t len) { - int need; + ssize_t need; if (len < 0) - acl_msg_panic("vstring_buf_space: bad length %d", len); + acl_msg_panic("vstring_buf_space: bad length %ld", (long) len); if ((need = len - bp->cnt) > 0) vstring_extend(bp, need); return (0); diff --git a/lib_acl/src/xml/acl_xml2.c b/lib_acl/src/xml/acl_xml2.c index 8422200af..f2a52c479 100644 --- a/lib_acl/src/xml/acl_xml2.c +++ b/lib_acl/src/xml/acl_xml2.c @@ -32,9 +32,9 @@ ACL_XML2_ATTR *acl_xml2_attr_alloc(ACL_XML2_NODE *node) acl_dbuf_pool_calloc(node->xml->dbuf, sizeof(ACL_XML2_ATTR)); attr->node = node; - attr->name = node->xml->addr; + attr->name = node->xml->dummy; attr->name_size = 0; - attr->value = node->xml->addr; + attr->value = node->xml->dummy; attr->value_size = 0; attr->quote = 0; attr->backslash = 0; @@ -132,12 +132,12 @@ ACL_XML2_NODE *acl_xml2_node_alloc(ACL_XML2 *xml) node->xml = xml; node->status = ACL_XML2_S_NXT; - node->ltag = xml->addr; - node->rtag = xml->addr; + node->ltag = xml->dummy; + node->rtag = xml->dummy; node->ltag_size = 0; node->rtag_size = 0; - node->text = xml->addr; + node->text = xml->dummy; node->text_size = 0; node->attr_list = acl_array_dbuf_create(100, xml->dbuf); @@ -396,13 +396,8 @@ void acl_xml2_decode_enable(ACL_XML2 *xml, int on) xml->flag &= ~ACL_XML2_FLAG_XML_DECODE; } -ACL_XML2 *acl_xml2_alloc(char *buf, size_t size) -{ - return acl_xml2_dbuf_alloc(buf, size, NULL); -} - -ACL_XML2 *acl_xml2_mmap_file(const char *filepath, size_t size, size_t block, - int keep_open, ACL_DBUF_POOL *dbuf) +ACL_XML2 *acl_xml2_mmap_file(const char *filepath, size_t max_len, + size_t init_len, ACL_DBUF_POOL *dbuf) { const char *myname = "acl_xml2_mmap_alloc"; ACL_FILE_HANDLE fd; @@ -417,157 +412,45 @@ ACL_XML2 *acl_xml2_mmap_file(const char *filepath, size_t size, size_t block, return NULL; } - xml = acl_xml2_mmap_fd(fd, size, block, dbuf); + xml = acl_xml2_mmap_fd(fd, max_len, init_len, dbuf); if (xml == NULL) { acl_file_close(fd); return NULL; } - if (!keep_open) { - acl_file_close(fd); - fd = ACL_FILE_INVALID; - } - - xml->keep_open = keep_open; - xml->mm_file = acl_dbuf_pool_strdup(xml->dbuf, filepath); + /* save the fd will be closed in acl_vstring_free */ + xml->fd = fd; return xml; } -ACL_XML2 *acl_xml2_mmap_fd(ACL_FILE_HANDLE fd, size_t size, - size_t block, ACL_DBUF_POOL *dbuf) +ACL_XML2 *acl_xml2_mmap_fd(ACL_FILE_HANDLE fd, size_t max_len, + size_t init_len, ACL_DBUF_POOL *dbuf) { -#ifdef ACL_UNIX - size_t off = block - 1; ACL_XML2 *xml; - char *addr; + ACL_VSTRING *vbuf = acl_vstring_mmap_alloc(fd, max_len, init_len); - acl_assert(size > 0); - acl_assert(block > 0); - - if (block > size) - block = size; - if (acl_lseek(fd, off, SEEK_SET) != (acl_off_t) off) { - acl_msg_error("%s(%d), %s: lseek error: %s, block: %lu", - __FILE__, __LINE__, __FUNCTION__, acl_last_serror(), - (unsigned long) off); + if (vbuf == NULL) return NULL; - } - - if (acl_file_write(fd, "\0", 1, 0, NULL, NULL) == ACL_VSTREAM_EOF) - { - acl_msg_error("%s(%d), %s: write error: %s", - __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); - return NULL; - } - - addr = (char*) mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (addr == MAP_FAILED) { - acl_msg_error("%s(%d), %s: mmap error: %s, size: %lu", - __FILE__, __LINE__, __FUNCTION__, - acl_last_serror(), (unsigned long) size); - return NULL; - } - - xml = acl_xml2_dbuf_alloc(addr, size, dbuf); - xml->mm_file = NULL; - xml->fd = fd; - xml->mm_addr = addr; - xml->block = block; - xml->off = off; - xml->keep_open = 1; - xml->len = xml->off + 1; + xml = acl_xml2_dbuf_alloc(vbuf, dbuf); + xml->vbuf_inner = vbuf; return xml; +} + +ACL_XML2 *acl_xml2_alloc(ACL_VSTRING *buf) +{ +#ifdef ACL_WINDOWS + if (buf->fd == ACL_FILE_INVALID) #else - (void) fd; - (void) size; - (void) block; - (void) dbuf; - - acl_msg_error("%s(%d), %s: not implement yet!", - __FILE__, __LINE__, __FUNCTION__); - return NULL; + if (buf->fd < 0) #endif + buf->vbuf.flags |= ACL_VBUF_FLAG_FIXED; + + return acl_xml2_dbuf_alloc(buf, NULL); } -size_t acl_xml2_mmap_extend(ACL_XML2 *xml) -{ - const char *myname = "acl_xml2_mmap_extend"; - size_t n; - - if (xml->ptr >= xml->addr + xml->size) - return 0; - - if (xml->block == 0) - return 0; - - if (xml->fd == ACL_FILE_INVALID) { - if (xml->mm_file == NULL || *xml->mm_file == 0) - return 0; - - xml->fd = acl_file_open(xml->mm_file, O_CREAT | O_RDWR, 0600); - if (xml->fd == ACL_FILE_INVALID) { - acl_msg_error("%s(%d), %s: open %s error: %s", - __FILE__, __LINE__, myname, - xml->mm_file, acl_last_serror()); - return 0; - } - } - - n = xml->size - xml->len; - if (n > xml->block) - n = xml->block; - - return acl_xml2_mmap_extend_size(xml, n); -} - -size_t acl_xml2_mmap_extend_size(ACL_XML2 *xml, size_t size) -{ - const char *myname = "acl_xml2_mmap_extend_size"; - size_t n; - - if (size == 0) - size = xml->block; - - if (xml->ptr >= xml->addr + xml->size) - return 0; - - n = xml->size - xml->len; - if (n > size) - n = size; - - xml->len += n; - xml->off += n; - - if (acl_lseek(xml->fd, xml->off, SEEK_SET) != (acl_off_t) xml->off) - { - acl_msg_error("%s(%d), %s: lseek error: %s", - __FILE__, __LINE__, myname, acl_last_serror()); - acl_file_close(xml->fd); - xml->fd = ACL_FILE_INVALID; - return 0; - } - - if (acl_file_write(xml->fd, "\0", 1, 0, NULL, NULL) == ACL_VSTREAM_EOF) - { - acl_msg_error("%s(%d), %s: write error: %s", - __FILE__, __LINE__, myname, acl_last_serror()); - acl_file_close(xml->fd); - xml->fd = ACL_FILE_INVALID; - return 0; - } - - if (!xml->keep_open) { - acl_file_close(xml->fd); - xml->fd = ACL_FILE_INVALID; - } - - return n; -} - -ACL_XML2 *acl_xml2_dbuf_alloc(char *buf, size_t size, ACL_DBUF_POOL *dbuf) +ACL_XML2 *acl_xml2_dbuf_alloc(ACL_VSTRING *vbuf, ACL_DBUF_POOL *dbuf) { ACL_XML2 *xml; @@ -580,54 +463,41 @@ ACL_XML2 *acl_xml2_dbuf_alloc(char *buf, size_t size, ACL_DBUF_POOL *dbuf) xml->dbuf_inner = NULL; } - xml->dbuf = dbuf; - xml->dbuf_keep = sizeof(ACL_XML2); - xml->addr = buf; - xml->size = size; - xml->len = size; - xml->ptr = xml->addr; - *xml->ptr++ = 0; - xml->flag |= ACL_XML2_FLAG_MULTI_ROOT; + xml->fd = ACL_FILE_INVALID; + xml->dbuf = dbuf; + xml->vbuf = vbuf; + xml->vbuf_inner = NULL; + xml->dummy[0] = '\0'; + xml->dbuf_keep = sizeof(ACL_XML2); + xml->flag |= ACL_XML2_FLAG_MULTI_ROOT; - xml->mm_file = NULL; - xml->fd = ACL_FILE_INVALID; - xml->off = size - 1; - xml->block = size; + xml->iter_head = xml_iter_head; + xml->iter_next = xml_iter_next; + xml->iter_tail = xml_iter_tail; + xml->iter_prev = xml_iter_prev; - xml->iter_head = xml_iter_head; - xml->iter_next = xml_iter_next; - xml->iter_tail = xml_iter_tail; - xml->iter_prev = xml_iter_prev; - - xml->id_table = acl_htable_create(100, 0); - xml->root = acl_xml2_node_alloc(xml); - xml->node_cnt = 1; + xml->id_table = acl_htable_create(100, 0); + xml->root = acl_xml2_node_alloc(xml); + xml->node_cnt = 1; return xml; } int acl_xml2_free(ACL_XML2 *xml) { - const char *myname = "acl_xml2_free"; int node_cnt = xml->node_cnt; acl_htable_free(xml->id_table, NULL); - if (xml->fd != ACL_FILE_INVALID) { - acl_file_close(xml->fd); - xml->fd = ACL_FILE_INVALID; - } - -#ifdef ACL_UNIX - if (xml->mm_addr != NULL && munmap(xml->mm_addr, xml->size) < 0) - acl_msg_error("%s(%d), %s: munmap error: %s", - __FILE__, __LINE__, myname, acl_last_serror()); +#ifdef ACL_UNIX + if (xml->fd >= 0) +#else + if (xml->fd != ACL_FILE_INVALID) #endif + acl_file_close(xml->fd); - if (xml->mm_file != NULL) { - acl_dbuf_pool_free(xml->dbuf, xml->mm_file); - xml->mm_file = NULL; - } + if (xml->vbuf_inner != NULL) + acl_vstring_free(xml->vbuf_inner); if (xml->dbuf_inner != NULL) acl_dbuf_pool_destroy(xml->dbuf_inner); @@ -642,12 +512,7 @@ void acl_xml2_reset(ACL_XML2 *xml) if (xml->dbuf_inner != NULL) acl_dbuf_pool_reset(xml->dbuf_inner, xml->dbuf_keep); - if (xml->fd != ACL_FILE_INVALID || xml->mm_file != NULL) - xml->len = xml->off + 1; - else - xml->len = xml->size; - - xml->ptr = xml->addr; + ACL_VSTRING_RESET(xml->vbuf); xml->root = acl_xml2_node_alloc(xml); xml->depth = 0; xml->node_cnt = 1; diff --git a/lib_acl/src/xml/acl_xml2_parse.c b/lib_acl/src/xml/acl_xml2_parse.c index c545e5a6f..721221c2c 100644 --- a/lib_acl/src/xml/acl_xml2_parse.c +++ b/lib_acl/src/xml/acl_xml2_parse.c @@ -14,6 +14,8 @@ #include "stdlib/acl_mystring.h" #include "stdlib/acl_msg.h" #include "stdlib/acl_sys_patch.h" +#include "stdlib/acl_vbuf.h" +#include "stdlib/acl_vstring.h" #include "code/acl_xmlcode.h" #include "xml/acl_xml2.h" @@ -35,6 +37,14 @@ #define SKIP_WHILE(cond, ptr) { while(*(ptr) && (cond)) (ptr)++; } #define SKIP_SPACE(ptr) { while(IS_SPACE(*(ptr))) (ptr)++; } +#define STR acl_vstring_str +#define LEN ACL_VSTRING_LEN +#define END(x) acl_vstring_end((x)->vbuf) +#define ADD(x, ch) ACL_VSTRING_ADDCH((x)->vbuf, (ch)) +#define APPEND(x, y) acl_vstring_strcat((x)->vbuf, (y)) +#define TERM(x) ACL_VSTRING_TERMINATE((x)->vbuf) +#define NO_SPACE(x) acl_vbuf_eof(&((x)->vbuf->vbuf)) + /* 状态机数据结构类型 */ struct XML_STATUS_MACHINE { @@ -45,8 +55,6 @@ struct XML_STATUS_MACHINE { const char *(*callback) (ACL_XML2*, const char*); }; -#define MIN_LEN 2 - static void xml_parse_check_self_closed(ACL_XML2 *xml) { if ((xml->curr_node->flag & ACL_XML2_F_LEAF) == 0) { @@ -115,14 +123,13 @@ static const char *xml_parse_left_em(ACL_XML2 *xml, const char *data) data++; } else { if (xml->curr_node->meta[1] == '-') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - if (xml->curr_node->ltag == xml->addr) - xml->curr_node->ltag = xml->ptr; + if (xml->curr_node->ltag == xml->dummy) + xml->curr_node->ltag = END(xml); - xml->len--; - *xml->ptr++ = '-'; + ADD(xml, '-'); xml->curr_node->meta[1] = 0; } @@ -139,6 +146,9 @@ static const char *xml_parse_cdata(ACL_XML2 *xml, const char *data) int ch; while ((ch = *data) != 0) { + if (NO_SPACE(xml)) + return data; + data++; if (ch == '>') { @@ -147,112 +157,48 @@ static const char *xml_parse_cdata(ACL_XML2 *xml, const char *data) { curr_node->status = ACL_XML2_S_MEND; curr_node->text_size = - xml->ptr - curr_node->text; - - if (xml->len > MIN_LEN) { - *xml->ptr++ = 0; - xml->len--; - } + END(xml) - curr_node->text; + ADD(xml, '\0'); return data; } if (curr_node->meta[0] == ']') { - if (xml->len > MIN_LEN) { - *xml->ptr++ = curr_node->meta[0]; - xml->len--; - } + ADD(xml, curr_node->meta[0]); curr_node->meta[0] = 0; } if (curr_node->meta[1] == ']') { - if (xml->len > MIN_LEN) { - *xml->ptr++ = curr_node->meta[1]; - xml->len--; - } + ADD(xml, curr_node->meta[1]); curr_node->meta[1] = 0; } } else if (ch == ']') { if (curr_node->meta[0] == ']') { if (curr_node->meta[1] == ']') { - if (xml->len < MIN_LEN) - return data; - *xml->ptr++ = ']'; - xml->len--; + ADD(xml, ']'); } else curr_node->meta[1] = ']'; } else if (curr_node->meta[1] == ']') { curr_node->meta[0] = ']'; curr_node->meta[1] = 0; - if (xml->len < MIN_LEN) - return data; - *xml->ptr++ = ']'; - xml->len--; + ADD(xml, ']'); } else curr_node->meta[0] = ']'; } else if (curr_node->meta[0] == ']') { - if (xml->len < MIN_LEN) - return data; - *xml->ptr++ = ']'; - xml->len--; + ADD(xml, ']'); curr_node->meta[0] = 0; if (curr_node->meta[1] == ']') { - if (xml->len < MIN_LEN) - return data; - *xml->ptr++ = ']'; - xml->len--; + ADD(xml, ']'); curr_node->meta[1] = 0; } } else { - if (xml->len < MIN_LEN) - return data; - *xml->ptr++ = ch; - xml->len--; + ADD(xml, ch); } } - *xml->ptr = 0; + TERM(xml); + return data; } -static void cdata_prepare(ACL_XML2 *xml) -{ - size_t cdata_len = sizeof("[CDATA[") - 1, len, max, i; - ACL_XML2_NODE *curr_node = xml->curr_node; - char *src, *dst; - - if (xml->len <= MIN_LEN || curr_node->ltag_size < cdata_len) - return; - - /* compute the max bytes for data copying */ - max = xml->len - MIN_LEN; - len = curr_node->ltag_size - cdata_len; - if (len > max) - len = max; - - src = curr_node->ltag + cdata_len; /* src is at the end of ltag */ - curr_node->text = src + 1; /* one space for '\0' of ltag */ - - /* moving data reverse in the same memory won't override the data */ - - dst = src + len; /* one space after the data end */ - src = dst - 1; - xml->ptr = dst + 1; - xml->len -= len; - - for (i = 0; i < len; i++) - *dst-- = *src--; - - /* terminate the ltag string */ - curr_node->ltag_size = cdata_len; - curr_node->ltag[curr_node->ltag_size] = 0; - -#if 0 - if (xml->len < MIN_LEN) - return; - *xml->ptr++ = last_ch; - xml->len--; -#endif -} - #define CDATA_SIZE (sizeof("[CDATA[") - 1) #define IS_CDATA(x) (*(x) == '[' \ && (*(x + 1) == 'C' || *(x + 1) == 'c') \ @@ -269,61 +215,35 @@ static const char *xml_parse_meta_tag(ACL_XML2 *xml, const char *data) if (*data == 0) return data; - if (xml->curr_node->ltag == xml->addr) - xml->curr_node->ltag = xml->ptr; + if (xml->curr_node->ltag == xml->dummy) + xml->curr_node->ltag = END(xml); while ((ch = *data) != 0) { -#if 0 - if (IS_SPACE(ch) || ch == '>') { - if (xml->len < MIN_LEN) - return data; - data++; - xml->curr_node->ltag_size = - xml->ptr - xml->curr_node->ltag; - - if (IS_CDATA(xml->curr_node->ltag)) { - cdata_prepare(xml, ch); - xml->curr_node->status = ACL_XML2_S_CDATA; - xml->curr_node->flag |= ACL_XML2_F_CDATA; - } else { - if (xml->len < MIN_LEN) - return data; - *xml->ptr++ = 0; - xml->len--; - xml->curr_node->status = ACL_XML2_S_MTXT; - } - break; - } -#else - - if (xml->ptr - xml->curr_node->ltag >= (ssize_t) CDATA_SIZE + if (END(xml) - xml->curr_node->ltag >= (ssize_t) CDATA_SIZE && IS_CDATA(xml->curr_node->ltag)) { xml->curr_node->ltag_size = - xml->ptr - xml->curr_node->ltag; - cdata_prepare(xml); + END(xml) - xml->curr_node->ltag; + ADD(xml, '\0'); + xml->curr_node->text = END(xml); xml->curr_node->status = ACL_XML2_S_CDATA; xml->curr_node->flag |= ACL_XML2_F_CDATA; break; } else if (IS_SPACE(ch) || ch == '>') { xml->curr_node->ltag_size = - xml->ptr - xml->curr_node->ltag; - if (xml->len < MIN_LEN) + END(xml) - xml->curr_node->ltag; + if (NO_SPACE(xml)) return data; + ADD(xml, '\0'); data++; - *xml->ptr++ = 0; - xml->len--; xml->curr_node->status = ACL_XML2_S_MTXT; break; } -#endif - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - + ADD(xml, ch); data++; - xml->len--; - *xml->ptr++ = ch; } return data; @@ -332,13 +252,12 @@ static const char *xml_parse_meta_tag(ACL_XML2 *xml, const char *data) static char *xml_meta_attr_name(ACL_XML2_ATTR *attr, char *data) { int ch; - ACL_XML2 *xml = attr->node->xml; SKIP_SPACE(data); if (*data == 0) return data; - if (attr->name == xml->addr) + if (attr->name == attr->node->xml->dummy) attr->name = data; while ((ch = *data) != 0) { @@ -370,7 +289,7 @@ static char *xml_meta_attr_value(ACL_XML2_ATTR *attr, char *data) if (*data == 0) return data; - if (attr->value == xml->addr) + if (attr->value == xml->dummy) attr->value = data; while ((ch = *data) != 0) { @@ -387,14 +306,13 @@ static char *xml_meta_attr_value(ACL_XML2_ATTR *attr, char *data) data++; } - if ((xml->flag & ACL_XML2_FLAG_XML_DECODE) && attr->value_size > 0 - && xml->len > 0) - { + if ((xml->flag & ACL_XML2_FLAG_XML_DECODE) && attr->value_size > 0) { const char *ptr = attr->value; - attr->value = xml->ptr; - (void) acl_xml_decode2(ptr, &xml->ptr, &xml->len); - attr->value_size = xml->ptr - attr->value - 1; + attr->value = END(xml); + (void) acl_xml_decode(ptr, xml->vbuf); + attr->value_size = END(xml) - attr->value; + ADD(xml, '\0'); /* skip one byte */ } return data; @@ -406,7 +324,7 @@ static void xml_meta_attr(ACL_XML2_NODE *node) char *ptr; int ch; - if (node->text == node->xml->addr || *node->text == 0) + if (node->text == node->xml->dummy || *node->text == 0) return; ptr = node->text; @@ -425,7 +343,7 @@ static void xml_meta_attr(ACL_XML2_NODE *node) break; } - node->text = node->xml->addr; + node->text = node->xml->dummy; node->text_size = 0; } @@ -433,58 +351,54 @@ static const char *xml_parse_meta_text(ACL_XML2 *xml, const char *data) { int ch; - if (xml->curr_node->text == xml->addr) + if (xml->curr_node->text == xml->dummy) SKIP_SPACE(data); if (*data == 0) return data; - if (xml->curr_node->text == xml->addr) - xml->curr_node->text = xml->ptr; + if (xml->curr_node->text == xml->dummy) + xml->curr_node->text = END(xml); while ((ch = *data) != 0) { if (xml->curr_node->quote) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; if (ch == xml->curr_node->quote) xml->curr_node->quote = 0; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } else if (IS_QUOTE(ch)) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; if (xml->curr_node->quote == 0) xml->curr_node->quote = ch; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } else if (ch == '<') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; xml->curr_node->nlt++; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } else if (ch != '>') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } else if (xml->curr_node->nlt == 0) { char *last; - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - data++; - xml->len--; - xml->curr_node->text_size = xml->ptr - - xml->curr_node->text; - *xml->ptr++ = 0; + xml->curr_node->text_size = + END(xml) - xml->curr_node->text; xml->curr_node->status = ACL_XML2_S_MEND; + ADD(xml, '\0'); + data++; + if ((xml->curr_node->flag & ACL_XML2_F_META_QM) == 0) break; - last = xml->ptr - 1; + last = END(xml) - 1; while (last > xml->curr_node->text) { if (*last == '?') { *last = 0; @@ -500,11 +414,10 @@ static const char *xml_parse_meta_text(ACL_XML2 *xml, const char *data) xml_meta_attr(xml->curr_node); break; } else { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; xml->curr_node->nlt--; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } data++; @@ -512,14 +425,14 @@ static const char *xml_parse_meta_text(ACL_XML2 *xml, const char *data) if (xml->curr_node->status == ACL_XML2_S_MEND && (xml->flag & ACL_XML2_FLAG_XML_DECODE) - && xml->curr_node->text_size > 0 && xml->len > 0) + && xml->curr_node->text_size > 0 && !NO_SPACE(xml)) { const char *txt = xml->curr_node->text; - xml->curr_node->text = xml->ptr; - (void) acl_xml_decode2(txt, &xml->ptr, &xml->len); - xml->curr_node->text_size = xml->ptr - - xml->curr_node->text - 1; + xml->curr_node->text = END(xml); + (void) acl_xml_decode(txt, xml->vbuf); + xml->curr_node->text_size = END(xml) - xml->curr_node->text; + ADD(xml, '\0'); /* skip one byte */ } return data; @@ -529,68 +442,60 @@ static const char *xml_parse_meta_comment(ACL_XML2 *xml, const char *data) { int ch; - if (xml->curr_node->text == xml->addr) + if (xml->curr_node->text == xml->dummy) SKIP_SPACE(data); if (*data == 0) return data; - if (xml->curr_node->text == xml->addr) - xml->curr_node->text = xml->ptr; + if (xml->curr_node->text == xml->dummy) + xml->curr_node->text = END(xml); while ((ch = *data) != 0) { if (xml->curr_node->quote) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; if (ch == xml->curr_node->quote) xml->curr_node->quote = 0; - else { - xml->len--; - *xml->ptr++ = ch; - } + else + ADD(xml, ch); } else if (IS_QUOTE(ch)) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; if (xml->curr_node->quote == 0) xml->curr_node->quote = ch; - else { - xml->len--; - *xml->ptr++ = ch; - } + else + ADD(xml, ch); } else if (ch == '<') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; xml->curr_node->nlt++; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } else if (ch == '>') { if (xml->curr_node->nlt == 0 && xml->curr_node->meta[0] == '-' && xml->curr_node->meta[1] == '-') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - xml->curr_node->text_size = xml->ptr - - xml->curr_node->text; - *xml->ptr++ = 0; + xml->curr_node->text_size = + END(xml) - xml->curr_node->text; + ADD(xml, '\0'); xml->curr_node->status = ACL_XML2_S_MEND; break; } xml->curr_node->nlt--; - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } else if (xml->curr_node->nlt > 0) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } else if (ch == '-') { if (xml->curr_node->meta[0] != '-') xml->curr_node->meta[0] = '-'; @@ -598,24 +503,21 @@ static const char *xml_parse_meta_comment(ACL_XML2 *xml, const char *data) xml->curr_node->meta[1] = '-'; } else { if (xml->curr_node->meta[0] == '-') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = '-'; + ADD(xml, '-'); xml->curr_node->meta[0] = 0; } if (xml->curr_node->meta[1] == '-') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = '-'; + ADD(xml, '-'); xml->curr_node->meta[1] = 0; } - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } data++; @@ -624,14 +526,14 @@ static const char *xml_parse_meta_comment(ACL_XML2 *xml, const char *data) if (xml->curr_node->status == ACL_XML2_S_MEND && (xml->flag & ACL_XML2_FLAG_XML_DECODE) && xml->curr_node->text_size > 0 - && xml->len > 0) + && !NO_SPACE(xml)) { const char *txt = xml->curr_node->text; - xml->curr_node->text = xml->ptr; - (void) acl_xml_decode2(txt, &xml->ptr, &xml->len); - xml->curr_node->text_size = xml->ptr - - xml->curr_node->text - 1; + xml->curr_node->text = END(xml); + (void) acl_xml_decode(txt, xml->vbuf); + xml->curr_node->text_size = END(xml) - xml->curr_node->text; + ADD(xml, '\0'); /* skip one byte */ } return data; @@ -648,55 +550,55 @@ static const char *xml_parse_left_tag(ACL_XML2 *xml, const char *data) { int ch; - if (xml->curr_node->ltag == xml->addr) + if (xml->curr_node->ltag == xml->dummy) SKIP_SPACE(data); if (*data == 0) return data; - if (xml->curr_node->ltag == xml->addr) - xml->curr_node->ltag = xml->ptr; + if (xml->curr_node->ltag == xml->dummy) + xml->curr_node->ltag = END(xml); while ((ch = *data) != 0) { if (ch == '>') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; + xml->curr_node->ltag_size = + END(xml) - xml->curr_node->ltag; + ADD(xml, '\0'); data++; - xml->len--; - xml->curr_node->ltag_size = xml->ptr - - xml->curr_node->ltag; - *xml->ptr++ = 0; xml_parse_check_self_closed(xml); if ((xml->curr_node->flag & ACL_XML2_F_SELF_CL) && xml->curr_node->last_ch == '/') { - size_t n = xml->curr_node->ltag_size; - if (n >= 2) - xml->curr_node->ltag[n - 2] = 0; - xml->curr_node->status = ACL_XML2_S_RGT; + if (xml->curr_node->ltag_size > 0) { + size_t n; + xml->curr_node->ltag_size--; + n = xml->curr_node->ltag_size; + xml->curr_node->ltag[n] = 0; + } + xml->curr_node->status = ACL_XML2_S_RGT; } else xml->curr_node->status = ACL_XML2_S_LGT; break; } else if (IS_SPACE(ch)) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - xml->curr_node->ltag_size = xml->ptr - - xml->curr_node->ltag; - *xml->ptr++ = 0; + xml->curr_node->ltag_size = + END(xml) - xml->curr_node->ltag; + ADD(xml, '\0'); xml->curr_node->status = ACL_XML2_S_ATTR; xml->curr_node->last_ch = ch; break; } else { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); xml->curr_node->last_ch = ch; } } @@ -709,7 +611,7 @@ static const char *xml_parse_attr(ACL_XML2 *xml, const char *data) int ch; ACL_XML2_ATTR *attr = xml->curr_node->curr_attr; - if (attr == NULL || attr->name == xml->addr) { + if (attr == NULL || attr->name == xml->dummy) { SKIP_SPACE(data); SKIP_WHILE(*data == '=', data); } @@ -728,11 +630,10 @@ static const char *xml_parse_attr(ACL_XML2 *xml, const char *data) xml->curr_node->status = ACL_XML2_S_LGT; xml->curr_node->curr_attr = NULL; - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - *xml->ptr++ = 0; + ADD(xml, '\0'); return data; } @@ -751,26 +652,24 @@ static const char *xml_parse_attr(ACL_XML2 *xml, const char *data) if (attr == NULL) { attr = acl_xml2_attr_alloc(xml->curr_node); xml->curr_node->curr_attr = attr; - attr->name = xml->ptr; + attr->name = END(xml); } while ((ch = *data) != 0) { xml->curr_node->last_ch = ch; if (ch == '=') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - attr->name_size = xml->ptr - attr->name; - *xml->ptr++ = 0; + attr->name_size = END(xml) - attr->name; + ADD(xml, '\0'); xml->curr_node->status = ACL_XML2_S_AVAL; break; } if (!IS_SPACE(ch)) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } data++; @@ -784,7 +683,7 @@ static const char *xml_parse_attr_val(ACL_XML2 *xml, const char *data) int ch; ACL_XML2_ATTR *attr = xml->curr_node->curr_attr; - if (attr->value == xml->addr && !attr->quote) { + if (attr->value == xml->dummy && !attr->quote) { SKIP_SPACE(data); if (IS_QUOTE(*data)) attr->quote = *data++; @@ -793,62 +692,57 @@ static const char *xml_parse_attr_val(ACL_XML2 *xml, const char *data) if (*data == 0) return data; - if (attr->value == xml->addr) - attr->value = xml->ptr; + if (attr->value == xml->dummy) + attr->value = END(xml); while ((ch = *data) != 0) { if (attr->quote) { if (ch == attr->quote) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - attr->value_size = xml->ptr - attr->value; - *xml->ptr++ = 0; + attr->value_size = END(xml) - attr->value; + ADD(xml, '\0'); xml->curr_node->status = ACL_XML2_S_ATTR; xml->curr_node->last_ch = ch; break; } - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); xml->curr_node->last_ch = ch; } else if (ch == '>') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - attr->value_size = xml->ptr - attr->value; - *xml->ptr++ = 0; + attr->value_size = END(xml) - attr->value; + ADD(xml, '\0'); xml_parse_check_self_closed(xml); if ((xml->curr_node->flag & ACL_XML2_F_SELF_CL) && xml->curr_node->last_ch == '/') { - if (attr->value_size >= 2) - attr->value[attr->value_size - 2] = 0; + if (--attr->value_size >= 0) + attr->value[attr->value_size] = 0; xml->curr_node->status = ACL_XML2_S_RGT; } else xml->curr_node->status = ACL_XML2_S_LGT; break; } else if (IS_SPACE(ch)) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - attr->value_size = xml->ptr - attr->value; - *xml->ptr++ = 0; + attr->value_size = END(xml) - attr->value; + ADD(xml, '\0'); xml->curr_node->status = ACL_XML2_S_ATTR; xml->curr_node->last_ch = ch; break; } else { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); xml->curr_node->last_ch = ch; } @@ -861,14 +755,13 @@ static const char *xml_parse_attr_val(ACL_XML2 *xml, const char *data) /* 当状态发生改变时,则说明属性值已经完毕 */ - if ((xml->flag & ACL_XML2_FLAG_XML_DECODE) && attr->value_size > 1 - && xml->len > 0) - { + if ((xml->flag & ACL_XML2_FLAG_XML_DECODE) && attr->value_size > 1) { const char *val = attr->value; - attr->value = xml->ptr; - (void) acl_xml_decode2(val, &xml->ptr, &xml->len); - attr->value_size = xml->ptr - attr->value - 1; + attr->value = END(xml); + (void) acl_xml_decode(val, xml->vbuf); + attr->value_size = END(xml) - attr->value; + ADD(xml, '\0'); /* skip one byte */ } /* 将该标签ID号映射至哈希表中,以便于快速查询 */ @@ -904,59 +797,53 @@ static const char *xml_parse_text(ACL_XML2 *xml, const char *data) { int ch; - if (xml->curr_node->text == xml->addr) + if (xml->curr_node->text == xml->dummy) SKIP_SPACE(data); if (*data == 0) return data; - if (xml->curr_node->text == xml->addr) - xml->curr_node->text = xml->ptr; + if (xml->curr_node->text == xml->dummy) + xml->curr_node->text = END(xml); while ((ch = *data) != 0) { if (ch == '<') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - xml->curr_node->text_size = xml->ptr - - xml->curr_node->text; - *xml->ptr++ = 0; + xml->curr_node->text_size = + END(xml) - xml->curr_node->text; + ADD(xml, '\0'); xml->curr_node->status = ACL_XML2_S_RLT; break; } - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } - if (xml->curr_node->status == ACL_XML2_S_RLT && (xml->flag & ACL_XML2_FLAG_XML_DECODE) && xml->curr_node->text_size > 1 - && xml->len > 0) + && !NO_SPACE(xml)) { char *txt = xml->curr_node->text; - xml->curr_node->text = xml->ptr; - (void) acl_xml_decode2(txt, &xml->ptr, &xml->len); - xml->curr_node->text_size = xml->ptr - - xml->curr_node->text - 1; - - /* xml->ptr pointer to the position after '\0', but we - * want to get the position before '\0', so subtract 2. - */ - txt = xml->ptr - 2; + xml->curr_node->text = END(xml); + (void) acl_xml_decode(txt, xml->vbuf); + xml->curr_node->text_size = END(xml) - xml->curr_node->text; + txt = END(xml) - 1; while (txt >= xml->curr_node->text && IS_SPACE(*txt)) { *txt-- = 0; xml->curr_node->text_size--; } + + ADD(xml, '\0'); } return data; @@ -977,12 +864,13 @@ static const char *xml_parse_right_lt(ACL_XML2 *xml, const char *data) return data; } else if ((xml->curr_node->flag & ACL_XML2_F_LEAF)) { /* XXX: some error ? */ - if (xml->len < MIN_LEN * 2) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = '<'; - xml->len--; - *xml->ptr++ = *data++; + ADD(xml, '<'); + if (NO_SPACE(xml)) + return data; + ADD(xml, *data); + data++; xml->curr_node->status = ACL_XML2_S_TXT; return data; @@ -1021,13 +909,6 @@ static void update_children_depth(ACL_XML2_NODE *parent) } } -static void string_copy(char *to, const char *from) -{ - while (*from) - *to++ = *from++; - *to = 0; -} - /* 查找与右标签相同的父节点 */ static int search_match_node(ACL_XML2 *xml) { @@ -1041,8 +922,8 @@ static int search_match_node(ACL_XML2 *xml) while (parent != xml->root) { if (acl_strcasecmp(xml->curr_node->rtag, parent->ltag) == 0) { - parent->rtag = xml->ptr; - string_copy(xml->ptr, xml->curr_node->rtag); + parent->rtag = END(xml); + APPEND(xml, xml->curr_node->rtag); parent->status = ACL_XML2_S_RGT; xml->curr_node = parent; break; @@ -1079,33 +960,32 @@ static const char *xml_parse_right_tag(ACL_XML2 *xml, const char *data) /* after: "rtag == xml->addr) + if (curr_node->rtag == xml->dummy) SKIP_SPACE(data); if (*data == 0) return data; - if (curr_node->rtag == xml->addr) - curr_node->rtag = xml->ptr; + if (curr_node->rtag == xml->dummy) + curr_node->rtag = END(xml); while ((ch = *data) != 0) { if (ch == '>') { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; data++; - xml->len--; - curr_node->rtag_size = xml->ptr - curr_node->rtag; - *xml->ptr++ = 0; + curr_node->rtag_size = END(xml) - curr_node->rtag; + ADD(xml, '\0'); curr_node->status = ACL_XML2_S_RGT; break; } if (!IS_SPACE(ch)) { - if (xml->len < MIN_LEN) + if (NO_SPACE(xml)) return data; - xml->len--; - *xml->ptr++ = ch; + ADD(xml, ch); } + data++; } @@ -1124,8 +1004,8 @@ static const char *xml_parse_right_tag(ACL_XML2 *xml, const char *data) /* 如果节点标签名与开始标签名不匹配, * 则需要继续寻找真正的结束标签 */ - curr_node->text = xml->ptr; - string_copy(xml->ptr, curr_node->rtag); + curr_node->text = END(xml); + APPEND(xml, curr_node->rtag); /* 重新设置当前节点状态,以便于其可以找到 "status = ACL_XML2_S_TXT; @@ -1203,7 +1083,7 @@ const char *acl_xml2_update(ACL_XML2 *xml, const char *data) data = status_tab[xml->curr_node->status].callback(xml, data); - if (xml->len < MIN_LEN && acl_xml2_mmap_extend(xml) == 0) { + if (NO_SPACE(xml)) { acl_msg_warn("%s(%d), %s: space not enougth!", __FILE__, __LINE__, myname); break; diff --git a/lib_acl/src/xml/acl_xml2_util.c b/lib_acl/src/xml/acl_xml2_util.c index 9b0273a1d..4eacc78c4 100644 --- a/lib_acl/src/xml/acl_xml2_util.c +++ b/lib_acl/src/xml/acl_xml2_util.c @@ -272,38 +272,23 @@ int acl_xml2_removeElementAttr(ACL_XML2_NODE *node, const char *name) /***************************************************************************/ -#define MIN 1 - -static const char *string_copy(const char *in, ACL_XML2 *xml) -{ - if (xml->len < MIN && acl_xml2_mmap_extend(xml) < MIN) - return in; - - while (*in != 0 && xml->len > MIN) { - *xml->ptr++ = *in++; - xml->len--; - if (xml->len < MIN && acl_xml2_mmap_extend(xml) < MIN) - return in; - } - - if (xml->len > MIN || acl_xml2_mmap_extend(xml) > MIN) { - *xml->ptr++ = 0; - xml->len--; - } - - return in; -} +#define STR acl_vstring_str +#define LEN ACL_VSTRING_LEN +#define END(x) acl_vstring_end((x)->vbuf) +#define ADD(x, ch) ACL_VSTRING_ADDCH((x)->vbuf, (ch)) +#define APPEND(x, y) acl_vstring_strcat((x)->vbuf, (y)) +#define TERM(x) ACL_VSTRING_TERMINATE((x)->vbuf) +#define NO_SPACE(x) acl_vbuf_eof(&((x)->vbuf->vbuf)) void acl_xml2_node_set_text(ACL_XML2_NODE *node, const char *text) { if (text == NULL || *text == 0) return; - node->text = node->xml->ptr; - string_copy(text, node->xml); - node->text_size = node->xml->ptr - node->text ; - if (node->text_size > 0) - node->text_size--; + node->text = END(node->xml); + APPEND(node->xml, text); + node->text_size = END(node->xml) - node->text; + ADD(node->xml, '\0'); } ACL_XML2_NODE *acl_xml2_create_node(ACL_XML2 *xml, const char* tag, @@ -313,18 +298,16 @@ ACL_XML2_NODE *acl_xml2_create_node(ACL_XML2 *xml, const char* tag, acl_assert(tag && *tag); - node->ltag = xml->ptr; - string_copy(tag, xml); - node->ltag_size = xml->ptr - node->ltag; - if (node->ltag_size > 0) - node->ltag_size--; + node->ltag = END(xml); + APPEND(xml, tag); + node->ltag_size = END(xml) - node->ltag; + ADD(xml, '\0'); if (text && *text) { - node->text = xml->ptr; - string_copy(text, xml); - node->text_size = xml->ptr - node->text; - if (node->text_size > 0) - node->text_size--; + node->text = END(xml); + APPEND(xml, text); + node->text_size = END(xml) - node->text; + ADD(xml, '\0'); } return node; @@ -336,18 +319,17 @@ ACL_XML2_ATTR *acl_xml2_node_add_attr(ACL_XML2_NODE *node, const char *name, ACL_XML2_ATTR *attr = acl_xml2_attr_alloc(node); acl_assert(name && *name); - attr->name = node->xml->ptr; - string_copy(name, node->xml); - attr->name_size = node->xml->ptr - attr->name; - if (attr->name_size > 0) - attr->name_size--; + + attr->name = END(node->xml); + APPEND(node->xml, name); + attr->name_size = END(node->xml) - attr->name; + ADD(node->xml, '\0'); if (value && *value) { - attr->value = node->xml->ptr; - string_copy(value, node->xml); - attr->value_size = node->xml->ptr - attr->value; - if (attr->value_size > 0) - attr->value_size--; + attr->value = END(node->xml); + APPEND(node->xml, value); + attr->value_size = END(node->xml) - attr->value; + ADD(node->xml, '\0'); } return attr; @@ -373,26 +355,23 @@ ACL_XML2_ATTR *acl_xml2_addElementAttr(ACL_XML2_NODE *node, ACL_XML2_ATTR *attr = acl_xml2_getElementAttr(node, name); if (attr) { - attr->value = node->xml->ptr; - string_copy(value, node->xml); - attr->value_size = node->xml->ptr - attr->value; - if (attr->value_size > 0) - attr->value_size--; + attr->value = END(node->xml); + APPEND(node->xml, value); + attr->value_size = END(node->xml) - attr->value; + ADD(node->xml, '\0'); return attr; } attr = acl_xml2_attr_alloc(node); - attr->name = node->xml->ptr; - string_copy(name, node->xml); - attr->name_size = node->xml->ptr - attr->name; - if (attr->name_size > 0) - attr->name_size--; + attr->name = END(node->xml); + APPEND(node->xml, name); + attr->name_size = END(node->xml) - attr->name; + ADD(node->xml, '\0'); - attr->value = node->xml->ptr; - string_copy(value, node->xml); - attr->value_size = node->xml->ptr - attr->value; - if (attr->value_size > 0) - attr->value_size--; + attr->value = END(node->xml); + APPEND(node->xml, value); + attr->value_size = END(node->xml) - attr->value; + ADD(node->xml, '\0'); acl_array_append(node->attr_list, attr); @@ -401,56 +380,18 @@ ACL_XML2_ATTR *acl_xml2_addElementAttr(ACL_XML2_NODE *node, /***************************************************************************/ -static const char *escape_append(ACL_XML2 *xml, const char *in, int quoted) +static void escape_append(ACL_XML2 *xml, const char *in, int quoted) { - const char *next = in, *last = in; - size_t len = strlen(in); + if (quoted) + ADD(xml, '"'); - if (xml->len < MIN && acl_xml2_mmap_extend(xml) < MIN) - return next; + if (in && *in) + (void) acl_xml_encode(in, xml->vbuf); - if (quoted) { - *xml->ptr++ = '"'; - xml->len--; - } + if (quoted) + ADD(xml, '"'); - while (len > 0) { - size_t n = acl_xml_encode2(&next, len, xml->ptr, xml->len); - if (n < MIN && acl_xml2_mmap_extend(xml) < MIN) - return next; - len -= next - last; - last = next; - xml->ptr += n; - xml->len -= n; - } - - if (xml->len < MIN && acl_xml2_mmap_extend(xml) < MIN) - return next; - - if (quoted) { - *xml->ptr++ = '"'; - xml->len--; - } - - if (xml->len >= MIN) - *xml->ptr = 0; - - return next; -} - -#define CHECK_SPACE(x) \ - if ((x)->len < MIN && acl_xml2_mmap_extend((x)) < MIN) \ - break; - -static const char *mem_copy(ACL_XML2 *xml, const char *in) -{ - while (*in != 0 && xml->len > 0) { - *xml->ptr++ = *in++; - xml->len--; - CHECK_SPACE(xml); - } - - return in; + TERM(xml); } const char *acl_xml2_build(ACL_XML2 *xml) @@ -458,154 +399,89 @@ const char *acl_xml2_build(ACL_XML2 *xml) ACL_XML2_ATTR *attr; ACL_XML2_NODE *node; ACL_ITER iter1, iter2; - char *res = xml->ptr; - - if (xml->len < MIN) - return xml->addr; - - /* reserve one space for the last '\0 */ - xml->len--; + char *res = END(xml); acl_foreach(iter1, xml) { - - CHECK_SPACE(xml); + if (NO_SPACE(xml)) + break; node = (ACL_XML2_NODE*) iter1.data; if (ACL_XML2_IS_CDATA(node)) { - mem_copy(xml, "text_size > 0) { - mem_copy(xml, node->text); - CHECK_SPACE(xml); - } + APPEND(xml, "text_size > 0) + APPEND(xml, node->text); } else if (ACL_XML2_IS_COMMENT(node)) { - mem_copy(xml, ""); - CHECK_SPACE(xml); + APPEND(xml, "-->"); } else if (node->flag & ACL_XML2_F_META_QM) { - mem_copy(xml, "?>"); - CHECK_SPACE(xml); + APPEND(xml, "?>"); } else if (node->flag & ACL_XML2_F_META_EM) { - *xml->ptr++ = '>'; - xml->len--; - CHECK_SPACE(xml); + ADD(xml, '>'); } else if (node->text_size == 0) { - mem_copy(xml, ">ltag, 0); - CHECK_SPACE(xml); - - *xml->ptr++ = '>'; - xml->len--; - CHECK_SPACE(xml); + ADD(xml, '>'); } else { - *xml->ptr++ = '>'; - xml->len--; - CHECK_SPACE(xml); - + ADD(xml, '>'); escape_append(xml, node->text, 0); - CHECK_SPACE(xml); - - mem_copy(xml, "ltag, 0); - CHECK_SPACE(xml); - - *xml->ptr++ = '>'; - xml->len--; - CHECK_SPACE(xml); + ADD(xml, '>'); } while (node->parent != node->xml->root && acl_xml2_node_next(node) == NULL) { - mem_copy(xml, "parent->ltag, 0); - CHECK_SPACE(xml); - - *xml->ptr++ = '>'; - xml->len--; - CHECK_SPACE(xml); - + ADD(xml, '>'); node = node->parent; } } - *xml->ptr = 0; + TERM(xml); return res; } diff --git a/lib_acl_cpp/changes.txt b/lib_acl_cpp/changes.txt index 2cc670a5e..ba43d0dcc 100644 --- a/lib_acl_cpp/changes.txt +++ b/lib_acl_cpp/changes.txt @@ -1,6 +1,23 @@ 修改历史列表: ----------------------------------------------------------------------- +403) 2016.1.31 +403.1) feature: string 类支持内存映射文件方式管理内存,从而可以支持更多的内存空间 +403.2) samples: string/string5, 用于测试内存映射文件 +403.3) feature: xml/xml1/xml2 支持使用 dbuf_guard 会话内存池来创建临时对象, +从而提升了内存使用效率 + +402) 2016.1.27 +402.1) bugfix: charset_conv 类中的方法 update,当 m_addInvalid 为 false,应该 +过滤掉无效的字符 +402.2) performance: mime_state_parse.cpp 中的 mime_bound_body 函数优化了处理 +大邮件的性能 + +401) 2016.1.22 +401.1) feature: HttpServlet 类增加了请求/响应成员函数(req_/res_),以便于将 +读取 HTTP 请求数据体分离 +401.2) bugfix: connect_manager 类少两个设置函数 set_check_inter/set_idle_ttl + 400) 2016.1.15 400.1) feature: redis 库增加了出错日志输出,便于运行时进行信息调试 diff --git a/lib_acl_cpp/include/acl_cpp/http/HttpCookie.hpp b/lib_acl_cpp/include/acl_cpp/http/HttpCookie.hpp index f88c4220a..f686321d4 100644 --- a/lib_acl_cpp/include/acl_cpp/http/HttpCookie.hpp +++ b/lib_acl_cpp/include/acl_cpp/http/HttpCookie.hpp @@ -1,16 +1,15 @@ #pragma once #include "acl_cpp/acl_cpp_define.hpp" #include +#include "acl_cpp/stdlib/dbuf_pool.hpp" #include "acl_cpp/http/http_type.hpp" namespace acl { -class dbuf_pool; - /** * http 协议头中 cookie 对象类 */ -class ACL_CPP_API HttpCookie +class ACL_CPP_API HttpCookie : public dbuf_obj { public: /** @@ -18,23 +17,23 @@ public: * @param name {const char*} cookie 名,为非空字符串且字符串长度 > 0 * @param value {const char*} cookie 值,指针非空,字符串长度可以为 0 * 注:如果输入的两个参数不符合条件,内部将会产生断言 - * @param dbuf {dbuf_pool*} 非空时将做为内存分配池 + * @param dbuf {dbuf_guard*} 非空时将做为内存分配池 */ - HttpCookie(const char* name, const char* value, dbuf_pool* dbuf = NULL); + HttpCookie(const char* name, const char* value, dbuf_guard* dbuf = NULL); /** * 当使用该构造函数时,可以使用 setCookie 来添加 cookie 项 - * @param dbuf {dbuf_pool*} 非空时将做为内存分配池 + * @param dbuf {dbuf_guard*} 非空时将做为内存分配池 */ - HttpCookie(dbuf_pool* dbuf = NULL); + HttpCookie(dbuf_guard* dbuf = NULL); /** * 拷贝构造函数 - * @param cookie {const HttpCookie*} 该参数必须非 NULL,内部将复制拷贝其 - * 成员变量 - * @param dbuf {dbuf_pool*} 非空时将做为内存分配池 + * @param cookie {const HttpCookie*} 非 NULL, 内部将复制拷贝其成员变量 + * @param dbuf {dbuf_guard*} 非空时将做为内存分配池 */ - HttpCookie(const HttpCookie* cookie, dbuf_pool* dbuf = NULL); + HttpCookie(const HttpCookie* cookie, dbuf_guard* dbuf = NULL); + /** * 析构函数 */ @@ -155,14 +154,18 @@ public: const std::list& getParams(void) const; private: - dbuf_pool* dbuf_internal_; - dbuf_pool* dbuf_; + dbuf_guard* dbuf_internal_; + dbuf_guard* dbuf_; char dummy_[1]; char* name_; char* value_; std::list params_; bool splitNameValue(char* data, HTTP_PARAM* param); + +protected: +// HttpCookie(HttpCookie&) {} +// HttpCookie(const HttpCookie&) {} }; } // namespace acl end diff --git a/lib_acl_cpp/include/acl_cpp/http/HttpServlet.hpp b/lib_acl_cpp/include/acl_cpp/http/HttpServlet.hpp index 21c4b21aa..d328c202f 100644 --- a/lib_acl_cpp/include/acl_cpp/http/HttpServlet.hpp +++ b/lib_acl_cpp/include/acl_cpp/http/HttpServlet.hpp @@ -5,9 +5,8 @@ namespace acl { -class dbuf_pool; -class socket_stream; class session; +class socket_stream; class HttpServletRequest; class HttpServletResponse; @@ -85,10 +84,21 @@ public: * @return {HttpServlet&} */ HttpServlet& setParseBodyLimit(int length); + + /** + * HttpServlet 对象开始运行,接收 HTTP 请求,并回调以下 doXXX 虚函数, + * @return {bool} 返回处理结果,返回 false 表示处理失败,则应关闭连接, + * 返回 true 表示处理成功,调用此函数后应该继续通过判断请求/响应对象中 + * 是否需要保持长连接来确实最终是否保持长连接 + */ + bool start(void); /** - * HttpServlet 对象开始运行,接收 HTTP 请求,并回调以下 doXXX 虚函数 - * @return {bool} 返回处理结果 + * HttpServlet 对象开始运行,接收 HTTP 请求,并回调以下 doXXX 虚函数, + * 该函数首先会调用 start 过程,然后根据 start 的返回结果及请求/响应 + * 对象是否要求保持长连接来决定是否需要与客户端保持长连接 + * @return {bool} 返回处理结果,返回 false 表示处理失败或处理成功且不保持 + * 长连接,应关闭连接 */ bool doRun(); @@ -224,11 +234,13 @@ public: return false; } +protected: + HttpServletRequest* req_; + HttpServletResponse* res_; + private: - dbuf_pool* dbuf_; session* session_; session* session_ptr_; - size_t reserve_size_; socket_stream* stream_; bool first_; char local_charset_[32]; @@ -237,7 +249,6 @@ private: int parse_body_limit_; void init(); - bool doRun(dbuf_pool* dbuf); }; } // namespace acl diff --git a/lib_acl_cpp/include/acl_cpp/http/HttpServletRequest.hpp b/lib_acl_cpp/include/acl_cpp/http/HttpServletRequest.hpp index 4d44c6a7a..0c7da6905 100644 --- a/lib_acl_cpp/include/acl_cpp/http/HttpServletRequest.hpp +++ b/lib_acl_cpp/include/acl_cpp/http/HttpServletRequest.hpp @@ -8,7 +8,7 @@ namespace acl { -class dbuf_pool; +class dbuf_guard; class istream; class ostream; class socket_stream; @@ -46,12 +46,10 @@ public: * @param body_limit {int} 针对 POST 方法,当数据体为文本参数 * 类型时,此参数限制数据体的长度;当数据体为数据流或 MIME * 格式或 on 为 false,此参数无效 - * @param dbuf {dbuf_pool*} 非空时将做为内存分配池 */ HttpServletRequest(HttpServletResponse& res, session& store, socket_stream& stream, const char* charset = NULL, - bool body_parse = true, int body_limit = 102400, - dbuf_pool* dbuf = NULL); + bool body_parse = true, int body_limit = 102400); ~HttpServletRequest(void); /** @@ -330,8 +328,8 @@ public: void sprint_header(string& out, const char* prompt); private: - dbuf_pool* dbuf_internal_; - dbuf_pool* dbuf_; + dbuf_guard* dbuf_internal_; + dbuf_guard* dbuf_; http_request_error_t req_error_; char cookie_name_[64]; HttpServletResponse& res_; diff --git a/lib_acl_cpp/include/acl_cpp/http/HttpServletResponse.hpp b/lib_acl_cpp/include/acl_cpp/http/HttpServletResponse.hpp index 7b74ba89a..939027a64 100644 --- a/lib_acl_cpp/include/acl_cpp/http/HttpServletResponse.hpp +++ b/lib_acl_cpp/include/acl_cpp/http/HttpServletResponse.hpp @@ -3,14 +3,13 @@ namespace acl { -class dbuf_pool; +class dbuf_guard; class string; class ostream; class socket_stream; class http_header; class http_client; class HttpCookie; -class HttpServlet; class HttpServletRequest; /** @@ -23,9 +22,8 @@ public: /** * 构造函数 * @param stream {socket_stream&} 数据流,内部不会自动关闭流 - * @param dbuf {dbuf_pool*} 非空时将做为内存分配池 */ - HttpServletResponse(socket_stream& stream, dbuf_pool* dbuf = NULL); + HttpServletResponse(socket_stream& stream); ~HttpServletResponse(void); /** @@ -245,8 +243,8 @@ public: } private: - dbuf_pool* dbuf_internal_; - dbuf_pool* dbuf_; + dbuf_guard* dbuf_internal_; + dbuf_guard* dbuf_; socket_stream& stream_; // 客户端连接流 HttpServletRequest* request_; // http 请求对象 http_client* client_; // http 响应流对象 diff --git a/lib_acl_cpp/include/acl_cpp/http/HttpSession.hpp b/lib_acl_cpp/include/acl_cpp/http/HttpSession.hpp index 827d1c1b7..b3fe06470 100644 --- a/lib_acl_cpp/include/acl_cpp/http/HttpSession.hpp +++ b/lib_acl_cpp/include/acl_cpp/http/HttpSession.hpp @@ -1,5 +1,6 @@ #pragma once #include "acl_cpp/acl_cpp_define.hpp" +#include "acl_cpp/stdlib//dbuf_pool.hpp" #include namespace acl { @@ -9,7 +10,7 @@ class session; /** * 服务端 HttpSession 类,目前该类的数据存储只能支持存在 memcached 上 */ -class ACL_CPP_API HttpSession +class ACL_CPP_API HttpSession : public dbuf_obj { public: /** diff --git a/lib_acl_cpp/include/acl_cpp/http/http_header.hpp b/lib_acl_cpp/include/acl_cpp/http/http_header.hpp index a64bb936b..fc913c020 100644 --- a/lib_acl_cpp/include/acl_cpp/http/http_header.hpp +++ b/lib_acl_cpp/include/acl_cpp/http/http_header.hpp @@ -1,6 +1,7 @@ #pragma once #include "acl_cpp/acl_cpp_define.hpp" #include +#include "acl_cpp/stdlib/dbuf_pool.hpp" #include "acl_cpp/http/http_type.hpp" struct HTTP_HDR_RES; @@ -8,21 +9,20 @@ struct HTTP_HDR_ENTRY; namespace acl { -class dbuf_pool; class string; class HttpCookie; /** * HTTP 头类,可以构建请求头或响应头 */ -class ACL_CPP_API http_header +class ACL_CPP_API http_header : public dbuf_obj { public: /** * 构造函数 - * @param dbuf {dbuf_pool*} 非空时将做为内存分配池 + * @param dbuf {dbuf_guard*} 非空时将做为内存分配池 */ - http_header(dbuf_pool* dbuf = NULL); + http_header(dbuf_guard* dbuf = NULL); /** * HTTP 请求头构造函数 @@ -37,16 +37,16 @@ public: * 调用该函数后用户仍可以调用 add_param 等函数添加其它参数; * 当参数字段只有参数名没有参数值时,该参数将会被忽略,所以如果想 * 单独添加参数名,应该调用 add_param 方法来添加 - * @param dbuf {dbuf_pool*} 非空时将做为内存分配池 + * @param dbuf {dbuf_guard*} 非空时将做为内存分配池 */ - http_header(const char* url, dbuf_pool* dbuf = NULL); + http_header(const char* url, dbuf_guard* dbuf = NULL); /** * HTTP 响应头构造函数 * @param status {int} 状态字如:1xx, 2xx, 3xx, 4xx, 5xx - * @param dbuf {dbuf_pool*} 非空时将做为内存分配池 + * @param dbuf {dbuf_guard*} 非空时将做为内存分配池 */ - http_header(int status, dbuf_pool* dbuf = NULL); + http_header(int status, dbuf_guard* dbuf = NULL); virtual ~http_header(void); @@ -386,8 +386,8 @@ public: } private: - dbuf_pool* dbuf_internal_; - dbuf_pool* dbuf_; + dbuf_guard* dbuf_internal_; + dbuf_guard* dbuf_; //char* domain_; // HTTP 服务器域名 //unsigned short port_; // HTTP 服务器端口 char* url_; // HTTP 请求的 URL diff --git a/lib_acl_cpp/include/acl_cpp/http/http_mime.hpp b/lib_acl_cpp/include/acl_cpp/http/http_mime.hpp index 737c28501..0effc0d7e 100644 --- a/lib_acl_cpp/include/acl_cpp/http/http_mime.hpp +++ b/lib_acl_cpp/include/acl_cpp/http/http_mime.hpp @@ -2,6 +2,7 @@ #include "acl_cpp/acl_cpp_define.hpp" #include #include +#include "acl_cpp/stdlib/dbuf_pool.hpp" #include "acl_cpp/stdlib/string.hpp" #include "acl_cpp/mime/mime_attach.hpp" #include "acl_cpp/http/http_type.hpp" @@ -50,7 +51,9 @@ public: * @return {const char*} 返回 NULL 表示参数不存在 */ const char* get_value(void) const; + protected: + private: http_mime_t mime_type_; char* param_value_; @@ -64,7 +67,7 @@ private: * http mime 解析器,该解析器为流式解析器,用户在使用时可以每次仅输入 * 部分数据给 update 函数,当该函数返回 true 时表示解析完成且解析正确 */ -class ACL_CPP_API http_mime +class ACL_CPP_API http_mime : public dbuf_obj { public: /** @@ -112,10 +115,10 @@ public: * 不存在 */ const http_mime_node* get_node(const char* name) const; -protected: + private: - char* boundary_; - char* save_path_; + string boundary_; + string save_path_; off_t off_; MIME_STATE* mime_state_; std::list mime_nodes_; diff --git a/lib_acl_cpp/include/acl_cpp/session/session.hpp b/lib_acl_cpp/include/acl_cpp/session/session.hpp index 7e1999282..6471757fc 100644 --- a/lib_acl_cpp/include/acl_cpp/session/session.hpp +++ b/lib_acl_cpp/include/acl_cpp/session/session.hpp @@ -1,6 +1,7 @@ #pragma once #include "acl_cpp/acl_cpp_define.hpp" #include +#include "acl_cpp/stdlib/dbuf_pool.hpp" #include "acl_cpp/stdlib/string.hpp" namespace acl { @@ -30,7 +31,7 @@ public: /** * session 类,该类使用 memcached 存储 session 数据 */ -class ACL_CPP_API session +class ACL_CPP_API session : public dbuf_obj { public: /** diff --git a/lib_acl_cpp/include/acl_cpp/stdlib/dbuf_pool.hpp b/lib_acl_cpp/include/acl_cpp/stdlib/dbuf_pool.hpp index bc52cc3e5..23fd41f24 100644 --- a/lib_acl_cpp/include/acl_cpp/stdlib/dbuf_pool.hpp +++ b/lib_acl_cpp/include/acl_cpp/stdlib/dbuf_pool.hpp @@ -1,5 +1,6 @@ #pragma once #include "acl_cpp/acl_cpp_define.hpp" +#include "acl_cpp/stdlib/noncopyable.hpp" #include struct ACL_DBUF_POOL; @@ -206,7 +207,7 @@ private: * 会话内存池管理器,由该类对象管理 dbuf_pool 对象及在其上分配的对象,当该类 * 对象销毁时,dbuf_pool 对象及在上面均被释放。 */ -class ACL_CPP_API dbuf_guard +class ACL_CPP_API dbuf_guard : public noncopyable { public: /** @@ -499,9 +500,6 @@ private: // 扩充 objs_ 数组对象的空间 void extend_objs(); - - // 禁止引用拷贝 - dbuf_guard(dbuf_guard&) {} }; /** diff --git a/lib_acl_cpp/include/acl_cpp/stdlib/json.hpp b/lib_acl_cpp/include/acl_cpp/stdlib/json.hpp index ff995c980..8c9813148 100644 --- a/lib_acl_cpp/include/acl_cpp/stdlib/json.hpp +++ b/lib_acl_cpp/include/acl_cpp/stdlib/json.hpp @@ -2,6 +2,7 @@ #include "acl_cpp/acl_cpp_define.hpp" #include #include +#include "acl_cpp/stdlib/dbuf_pool.hpp" #include "acl_cpp/stdlib/pipe_stream.hpp" struct ACL_JSON_NODE; @@ -23,7 +24,7 @@ class json; /** * json 节点,该类对象必须以 json.create_node() 方式创建 */ -class ACL_CPP_API json_node +class ACL_CPP_API json_node : public dbuf_obj { public: /** @@ -367,7 +368,7 @@ private: void prepare_iter(void); }; -class ACL_CPP_API json : public pipe_stream +class ACL_CPP_API json : public pipe_stream, public dbuf_obj { public: /** diff --git a/lib_acl_cpp/include/acl_cpp/stdlib/string.hpp b/lib_acl_cpp/include/acl_cpp/stdlib/string.hpp index 57adebca9..997ec5549 100644 --- a/lib_acl_cpp/include/acl_cpp/stdlib/string.hpp +++ b/lib_acl_cpp/include/acl_cpp/stdlib/string.hpp @@ -48,6 +48,17 @@ public: * @param n {size_t} s 缓冲区数据长度 */ string(const void* s, size_t n); + +#if !defined(_WIN32) && !defined(_WIN64) + /** + * 采用内存映射文件方式构造对象 + * @param fd {int} 文件句柄 + * @param max {size_t} 所映射的最大空间大小 + * @param n {size_t} 初始化大小 + */ + string(int fd, size_t max, size_t n); +#endif + virtual ~string(void); /** diff --git a/lib_acl_cpp/include/acl_cpp/stdlib/xml.hpp b/lib_acl_cpp/include/acl_cpp/stdlib/xml.hpp index f07b15e6b..46974a7ff 100644 --- a/lib_acl_cpp/include/acl_cpp/stdlib/xml.hpp +++ b/lib_acl_cpp/include/acl_cpp/stdlib/xml.hpp @@ -2,6 +2,7 @@ #include "acl_cpp/acl_cpp_define.hpp" #include #include +#include "acl_cpp/stdlib/dbuf_pool.hpp" #include "acl_cpp/stdlib/string.hpp" #include "acl_cpp/stdlib/pipe_stream.hpp" @@ -20,7 +21,7 @@ namespace acl { class xml; class xml_node; -class ACL_CPP_API xml_attr +class ACL_CPP_API xml_attr : public dbuf_obj { public: /** @@ -46,7 +47,7 @@ protected: xml_node* node_; }; -class ACL_CPP_API xml_node +class ACL_CPP_API xml_node : public dbuf_obj { public: /** @@ -269,6 +270,7 @@ public: protected: friend class xml; + friend class dbuf_guard; /** * xml 节点构造函数 @@ -289,7 +291,7 @@ protected: class string; -class ACL_CPP_API xml : public pipe_stream +class ACL_CPP_API xml : public pipe_stream, public dbuf_obj { public: xml(void); @@ -475,12 +477,13 @@ public: virtual void clear(void); protected: + dbuf_guard dbuf_; std::vector elements_; string* buf_; //bool dummyRootAdded_; ACL_TOKEN* m_pTokenTree; - std::list nodes_tmp_; + //std::list nodes_tmp_; }; } // namespace acl diff --git a/lib_acl_cpp/include/acl_cpp/stdlib/xml1.hpp b/lib_acl_cpp/include/acl_cpp/stdlib/xml1.hpp index 45862655c..69f13bbd8 100644 --- a/lib_acl_cpp/include/acl_cpp/stdlib/xml1.hpp +++ b/lib_acl_cpp/include/acl_cpp/stdlib/xml1.hpp @@ -175,6 +175,7 @@ public: protected: friend class xml1; + friend class dbuf_guard; /** * xml 节点构造函数 diff --git a/lib_acl_cpp/include/acl_cpp/stdlib/xml2.hpp b/lib_acl_cpp/include/acl_cpp/stdlib/xml2.hpp index d74f919a9..93fe012e4 100644 --- a/lib_acl_cpp/include/acl_cpp/stdlib/xml2.hpp +++ b/lib_acl_cpp/include/acl_cpp/stdlib/xml2.hpp @@ -131,6 +131,7 @@ public: protected: friend class xml2; + friend class dbuf_guard; xml2_node(xml* xml_ptr, ACL_XML2_NODE* node); ~xml2_node(void); @@ -149,56 +150,44 @@ class fstream; class ACL_CPP_API xml2 : public xml { public: - /** - * 构造函数,使 xml 对象树创建在指定的内存块上 - * @param addr {char*} 内存映射的地址或内存地址,解析过程中产生的数据 - * 将存储于该内存区域中 - * @param size {size_t} addr 内存空间大小,当解析产生的数据超过此值 - * 时则解析过程停止,所以必须保证该空间大小足够用 - * @param data {const char*} 非空时自动调用解析过程 - */ - xml2(char* addr, size_t size, const char* data = NULL); - /** * 构造函数,使 xml 对象树创建在指定内存映射文件上 * @param filepath {const char*} 内存映射文件名 - * @param size {size_t} 内存映射文件的最大大小,即内存映射文件在自动 + * @param max_len {size_t} 内存映射文件的最大大小,即内存映射文件在自动 * 增长时不应超过此大小 * @param data {const char*} 非空时自动调用解析过程 - * @param block {size_t} 内存映射文件创建时的初始大小 - * @param keep_open {bool} 打开的内存映射文件的句柄是否一直保持打开 - * 状态,这样可以提高文件增长时的效率 + * @param init_len {size_t} 内存映射文件创建时的初始大小 */ - xml2(const char* filepath, size_t size, const char* data = NULL, - size_t block = 8192, bool keep_open = true); + xml2(const char* filepath, size_t max_len, const char* data = NULL, + size_t init_len = 8192); /** * 构造函数,使 xml 对象树创建在指定内存映射文件上 * @param fp {fstream&} 内存映射文件句柄,该文件句柄应在本 xml 对象 * 释放前一直保持打开状态,即 fp 必须在 xml 对象释放后才可以关闭 - * @param size {size_t} 内存映射文件的最大大小,即内存映射文件在自动 + * @param max_len {size_t} 内存映射文件的最大大小,即内存映射文件在自动 * 增长时不应超过此大小 * @param data {const char*} 非空时自动调用解析过程 - * @param block {size_t} 内存映射文件创建时的初始大小 + * @param init_len {size_t} 内存映射文件创建时的初始大小 */ - xml2(fstream& fp, size_t size, const char* data = NULL, - size_t block = 8192); + xml2(fstream& fp, size_t max_len, const char* data = NULL, + size_t init_len = 8192); /** * 构造函数,使 xml 对象树创建在指定内存映射文件上 * @param fd {ACL_FILE_HANDLE} 内存映射文件句柄,该文件句柄应在本 xml * 对象释放前一直保持打开状态,即 fp 必须在 xml 对象释放后才可以关闭 - * @param size {size_t} 内存映射文件的最大大小,即内存映射文件在自动 + * @param max_len {size_t} 内存映射文件的最大大小,即内存映射文件在自动 * 增长时不应超过此大小 * @param data {const char*} 非空时自动调用解析过程 - * @param block {size_t} 内存映射文件创建时的初始大小 + * @param init_len {size_t} 内存映射文件创建时的初始大小 */ #if defined(_WIN32) || defined(_WIN64) - xml2(void* fd, size_t size, const char* data = NULL, - size_t block = 8192); + xml2(void* fd, size_t max_len, const char* data = NULL, + size_t init_len = 8192); #else - xml2(int fd, size_t size, const char* data = NULL, - size_t block = 8192); + xml2(int fd, size_t max_len, const char* data = NULL, + size_t init_len = 8192); #endif ~xml2(void); diff --git a/lib_acl_cpp/samples/mime/mime/mime.cpp b/lib_acl_cpp/samples/mime/mime/mime.cpp index 713fad834..e633a659b 100644 --- a/lib_acl_cpp/samples/mime/mime/mime.cpp +++ b/lib_acl_cpp/samples/mime/mime/mime.cpp @@ -250,7 +250,10 @@ static void mime_test1(acl::mime& mime, const char* path, bool htmlFirst) for (; cit != attaches.end(); cit++) { buf = "./var/"; - buf << (*cit)->get_filename(); + const char* filename = (*cit)->get_filename(); + if (filename == NULL) + continue; + buf << filename; acl::string attach_name; acl::rfc2047 rfc2047; @@ -448,6 +451,7 @@ int main(int argc, char* argv[]) bool htmlFirst = false; acl::string path("test.eml"); acl::string cmd("test1"); + acl::log::stdout_open(true); while ((ch = (char) getopt(argc, argv, "hst:f:")) > 0) { diff --git a/lib_acl_cpp/samples/mime/mime/test.sh b/lib_acl_cpp/samples/mime/mime/test.sh new file mode 100644 index 000000000..b486988da --- /dev/null +++ b/lib_acl_cpp/samples/mime/mime/test.sh @@ -0,0 +1,124 @@ +#!/bin/sh + +./mime -s -t test1 -f test1.eml +diff test1.eml var/test1.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test2.eml +diff test2.eml var/test2.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test3.eml +diff test3.eml var/test3.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test4.eml +diff test4.eml var/test4.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test5.eml +diff test5.eml var/test5.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test6.eml +diff test6.eml var/test6.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test7.eml +diff test7.eml var/test7.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test8.eml +diff test8.eml var/test8.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test9.eml +diff test8.eml var/test8.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test10.eml +diff test10.eml var/test10.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test11.eml +diff test11.eml var/test11.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test12.eml +diff test12.eml var/test12.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test13.eml +diff test13.eml var/test13.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test14.eml +diff test14.eml var/test14.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test15.eml +diff test15.eml var/test15.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test16.eml +diff test16.eml var/test16.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test17.eml +diff test17.eml var/test17.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test18.eml +diff test18.eml var/test18.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test19.eml +diff test19.eml var/test19.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test21.eml +diff test21.eml var/test21.eml + +echo "" +echo "Enter any key to continue ..." +read tmp +./mime -s -t test1 -f test22.eml +diff test22.eml var/test22.eml diff --git a/lib_acl_cpp/samples/rfc2047/main.cpp b/lib_acl_cpp/samples/rfc2047/main.cpp index 1dd5a604b..0c66a0b03 100644 --- a/lib_acl_cpp/samples/rfc2047/main.cpp +++ b/lib_acl_cpp/samples/rfc2047/main.cpp @@ -379,6 +379,9 @@ int main(int argc, char* argv[]) rfc2047_test(rfc2047, s10); ///////////////////////////////////////////////////////////////////// + + const char* s11 = "=?utf-8?B?57rnur/kuIrmg4XlhrXnu5/orqE=?="; + rfc2047_test(rfc2047, s11); getchar(); return (0); diff --git a/lib_acl_cpp/samples/string/Makefile b/lib_acl_cpp/samples/string/Makefile index ea7f3187e..54f637201 100644 --- a/lib_acl_cpp/samples/string/Makefile +++ b/lib_acl_cpp/samples/string/Makefile @@ -4,8 +4,12 @@ all: @(cd string1; make) @(cd string2; make) @(cd string3; make) + @(cd string4; make) + @(cd string5; make) clean: @(cd string1; make clean) @(cd string2; make clean) @(cd string3; make clean) + @(cd string4; make clean) + @(cd string5; make clean) diff --git a/lib_acl_cpp/samples/string/string5/Makefile b/lib_acl_cpp/samples/string/string5/Makefile new file mode 100644 index 000000000..80c81993a --- /dev/null +++ b/lib_acl_cpp/samples/string/string5/Makefile @@ -0,0 +1,3 @@ +base_path = ../../.. +PROG = string +include ../../Makefile.in diff --git a/lib_acl_cpp/samples/string/string5/main.cpp b/lib_acl_cpp/samples/string/string5/main.cpp new file mode 100644 index 000000000..d41091ab6 --- /dev/null +++ b/lib_acl_cpp/samples/string/string5/main.cpp @@ -0,0 +1,120 @@ +#include "lib_acl.h" +#include "acl_cpp/lib_acl.hpp" +#include +#include + +static void test(acl::string& buf) +{ + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; + buf += "hello world!"; +} + +static void test_mmap(int max) +{ + const char* filename = "local.map"; + acl::fstream fp; + if (fp.open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600) == false) + { + printf("open %s error %s\r\n", filename, acl::last_serror()); + return; + } + + size_t max_len = 1024 * 1024 * 500, init_len = 4096; + acl::string buf(fp.file_handle(), max_len, init_len); + + ACL_METER_TIME(">> begin acl::string"); + + for (int i = 0; i < max; i++) + { + test(buf); + } + + ACL_METER_TIME(">> end acl::string"); +} + +static void test_mem(int max) +{ + size_t max_len = 1024 * 1024 * 500, init_len = 4096; + acl::string buf(init_len); + buf.set_max(max_len); + + ACL_METER_TIME(">> begin acl::string"); + + for (int i = 0; i < max; i++) + { + test(buf); + } + + ACL_METER_TIME(">> end acl::string"); +} + +static void usage(const char* procname) +{ + printf("usage: %s -h [help] -m [use_mmap] -n max_count\r\n", procname); +} + +int main(int argc, char* argv[]) +{ + bool use_mmap = false; + int ch, max = 100000; + + while ((ch = getopt(argc, argv, "hmn:")) > 0) + { + switch (ch) + { + case 'h': + usage(argv[0]); + return 0; + case 'm': + use_mmap = true; + break; + case 'n': + max = atoi(optarg); + break; + default: + break; + } + } + + if (use_mmap) + test_mmap(max); + else + test_mem(max); + + return (0); +} diff --git a/lib_acl_cpp/samples/string/string5/valgrind.sh b/lib_acl_cpp/samples/string/string5/valgrind.sh new file mode 100644 index 000000000..e9857918e --- /dev/null +++ b/lib_acl_cpp/samples/string/string5/valgrind.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +valgrind --tool=memcheck --leak-check=yes --show-reachable=yes -v ./string -m diff --git a/lib_acl_cpp/src/connpool/connect_manager.cpp b/lib_acl_cpp/src/connpool/connect_manager.cpp index 2d847eeb5..a64abf19c 100644 --- a/lib_acl_cpp/src/connpool/connect_manager.cpp +++ b/lib_acl_cpp/src/connpool/connect_manager.cpp @@ -14,6 +14,8 @@ connect_manager::connect_manager() , service_idx_(0) , stat_inter_(1) , retry_inter_(1) +, idle_ttl_(-1) +, check_inter_(-1) , monitor_(NULL) { } @@ -79,6 +81,16 @@ void connect_manager::set_retry_inter(int n) lock_.unlock(); } +void connect_manager::set_check_inter(int n) +{ + check_inter_ = n; +} + +void connect_manager::set_idle_ttl(time_t ttl) +{ + idle_ttl_ = ttl; +} + void connect_manager::init(const char* default_addr, const char* addr_list, size_t count, int conn_timeout /* = 30 */, int rw_timeout /* = 30 */) { diff --git a/lib_acl_cpp/src/http/HttpCookie.cpp b/lib_acl_cpp/src/http/HttpCookie.cpp index 297c6e2fd..e53c9ae4f 100644 --- a/lib_acl_cpp/src/http/HttpCookie.cpp +++ b/lib_acl_cpp/src/http/HttpCookie.cpp @@ -8,7 +8,7 @@ namespace acl { HttpCookie::HttpCookie(const char* name, const char* value, - dbuf_pool* dbuf /* = NULL */) + dbuf_guard* dbuf /* = NULL */) { if (dbuf != NULL) { @@ -17,7 +17,7 @@ HttpCookie::HttpCookie(const char* name, const char* value, } else { - dbuf_internal_ = new dbuf_pool; + dbuf_internal_ = new dbuf_guard; dbuf_ = dbuf_internal_; } @@ -27,7 +27,7 @@ HttpCookie::HttpCookie(const char* name, const char* value, dummy_[0] = 0; } -HttpCookie::HttpCookie(dbuf_pool* dbuf /* = NULL */) +HttpCookie::HttpCookie(dbuf_guard* dbuf /* = NULL */) { if (dbuf != NULL) { @@ -36,7 +36,7 @@ HttpCookie::HttpCookie(dbuf_pool* dbuf /* = NULL */) } else { - dbuf_internal_ = new dbuf_pool; + dbuf_internal_ = new dbuf_guard; dbuf_ = dbuf_internal_; } @@ -45,7 +45,7 @@ HttpCookie::HttpCookie(dbuf_pool* dbuf /* = NULL */) dummy_[0] = 0; } -HttpCookie::HttpCookie(const HttpCookie* cookie, dbuf_pool* dbuf /* = NULL */) +HttpCookie::HttpCookie(const HttpCookie* cookie, dbuf_guard* dbuf /* = NULL */) { if (dbuf != NULL) { @@ -54,11 +54,14 @@ HttpCookie::HttpCookie(const HttpCookie* cookie, dbuf_pool* dbuf /* = NULL */) } else { - dbuf_internal_ = new dbuf_pool; + dbuf_internal_ = new dbuf_guard; dbuf_ = dbuf_internal_; } dummy_[0] = 0; + + acl_assert(cookie); + if (cookie->name_) name_ = dbuf_->dbuf_strdup(cookie->name_); else @@ -81,8 +84,7 @@ HttpCookie::HttpCookie(const HttpCookie* cookie, dbuf_pool* dbuf /* = NULL */) HttpCookie::~HttpCookie(void) { - if (dbuf_internal_) - dbuf_internal_->destroy(); + delete dbuf_internal_; } void HttpCookie::destroy(void) diff --git a/lib_acl_cpp/src/http/HttpServlet.cpp b/lib_acl_cpp/src/http/HttpServlet.cpp index f0922abb9..6bf61500d 100644 --- a/lib_acl_cpp/src/http/HttpServlet.cpp +++ b/lib_acl_cpp/src/http/HttpServlet.cpp @@ -1,7 +1,6 @@ #include "acl_stdafx.hpp" -#include "acl_cpp/stdlib/dbuf_pool.hpp" -#include "acl_cpp/stdlib/snprintf.hpp" #include "acl_cpp/stdlib/log.hpp" +#include "acl_cpp/stdlib/snprintf.hpp" #include "acl_cpp/stream/socket_stream.hpp" #include "acl_cpp/session/memcache_session.hpp" #include "acl_cpp/http/http_header.hpp" @@ -14,50 +13,45 @@ namespace acl { HttpServlet::HttpServlet(socket_stream* stream, session* session) -: stream_(stream) +: req_(NULL) +, res_(NULL) +, stream_(stream) { - dbuf_ = new dbuf_pool; init(); if (session == NULL) { - session_ = new (dbuf_->dbuf_alloc(sizeof(memcache_session))) - memcache_session("127.0.0.1"); + session_ = NEW memcache_session("127.0.0.1"); session_ptr_ = session_; - reserve_size_ = sizeof(memcache_session); } else { session_ = session; session_ptr_ = NULL; - reserve_size_ = 0; } } HttpServlet::HttpServlet(socket_stream* stream, const char* memcache_addr /* = "127.0.0.1:11211" */) -: stream_(stream) +: req_(NULL) +, res_(NULL) +, stream_(stream) { - dbuf_ = new dbuf_pool; - init(); - session_ = new (dbuf_->dbuf_alloc(sizeof(memcache_session))) - memcache_session(memcache_addr); + session_ = NEW memcache_session(memcache_addr); session_ptr_ = session_; - reserve_size_ = sizeof(memcache_session); } HttpServlet::HttpServlet() { - dbuf_ = new dbuf_pool; - init(); + req_ = NULL; + res_ = NULL; stream_ = NULL; session_ = NULL; session_ptr_ = NULL; - reserve_size_ = 0; } void HttpServlet::init() @@ -71,9 +65,8 @@ void HttpServlet::init() HttpServlet::~HttpServlet(void) { - if (session_ptr_) - session_ptr_->~session(); - dbuf_->destroy(); + delete req_; + delete res_; } #define COPY(x, y) ACL_SAFE_STRNCPY((x), (y), sizeof((x))) @@ -106,7 +99,7 @@ HttpServlet& HttpServlet::setParseBodyLimit(int length) return *this; } -bool HttpServlet::doRun(dbuf_pool* dbuf) +bool HttpServlet::start() { socket_stream* in; socket_stream* out; @@ -133,67 +126,69 @@ bool HttpServlet::doRun(dbuf_pool* dbuf) cgi_mode = false; } - // req/res 采用栈变量,减少内存分配次数 + // 在 HTTP 长连接重复请求情况下,以防万一,需要首先删除请求/响应对象 + delete req_; + delete res_; - HttpServletResponse res(*out, dbuf); - HttpServletRequest req(res, *session_, *in, local_charset_, - parse_body_enable_, parse_body_limit_, dbuf); + res_ = NEW HttpServletResponse(*out); + req_ = NEW HttpServletRequest(*res_, *session_, *in, local_charset_, + parse_body_enable_, parse_body_limit_); // 设置 HttpServletRequest 对象 - res.setHttpServletRequest(&req); + res_->setHttpServletRequest(req_); if (rw_timeout_ >= 0) - req.setRwTimeout(rw_timeout_); + req_->setRwTimeout(rw_timeout_); - res.setCgiMode(cgi_mode); + res_->setCgiMode(cgi_mode); string method_s(32); - http_method_t method = req.getMethod(&method_s); + http_method_t method = req_->getMethod(&method_s); // 根据请求的值自动设定是否需要保持长连接 if (!cgi_mode) - res.setKeepAlive(req.isKeepAlive()); + res_->setKeepAlive(req_->isKeepAlive()); bool ret; switch (method) { case HTTP_METHOD_GET: - ret = doGet(req, res); + ret = doGet(*req_, *res_); break; case HTTP_METHOD_POST: - ret = doPost(req, res); + ret = doPost(*req_, *res_); break; case HTTP_METHOD_PUT: - ret = doPut(req, res); + ret = doPut(*req_, *res_); break; case HTTP_METHOD_CONNECT: - ret = doConnect(req, res); + ret = doConnect(*req_, *res_); break; case HTTP_METHOD_PURGE: - ret = doPurge(req, res); + ret = doPurge(*req_, *res_); break; case HTTP_METHOD_DELETE: - ret = doDelete(req, res); + ret = doDelete(*req_, *res_); break; case HTTP_METHOD_HEAD: - ret = doHead(req, res); + ret = doHead(*req_, *res_); break; case HTTP_METHOD_OPTION: - ret = doOptions(req, res); + ret = doOptions(*req_, *res_); break; case HTTP_METHOD_PROPFIND: - ret = doPropfind(req, res); + ret = doPropfind(*req_, *res_); break; case HTTP_METHOD_OTHER: - ret = doOther(req, res, method_s.c_str()); + ret = doOther(*req_, *res_, method_s.c_str()); break; default: ret = false; // 有可能是IO失败或未知方法 - if (req.getLastError() == HTTP_REQ_ERR_METHOD) - doUnknown(req, res); + if (req_->getLastError() == HTTP_REQ_ERR_METHOD) + doUnknown(*req_, *res_); else if (first) - doError(req, res); + doError(*req_, *res_); break; } @@ -208,18 +203,18 @@ bool HttpServlet::doRun(dbuf_pool* dbuf) delete out; } - // 返回给上层调用者:true 表示继续保持长连接,否则表示需断开连接 - return ret && req.isKeepAlive() - && res.getHttpHeader().get_keep_alive(); + return ret; } bool HttpServlet::doRun() { - bool ret = doRun(dbuf_); + bool ret = start(); + if (req_ == NULL || res_ == NULL) + return ret; - // 重置内存池状态 - dbuf_->dbuf_reset(reserve_size_); - return ret; + // 返回给上层调用者:true 表示继续保持长连接,否则表示需断开连接 + return ret && req_->isKeepAlive() + && res_->getHttpHeader().get_keep_alive(); } bool HttpServlet::doRun(session& session, socket_stream* stream /* = NULL */) diff --git a/lib_acl_cpp/src/http/HttpServletRequest.cpp b/lib_acl_cpp/src/http/HttpServletRequest.cpp index 3a4047d51..c0e84e29c 100644 --- a/lib_acl_cpp/src/http/HttpServletRequest.cpp +++ b/lib_acl_cpp/src/http/HttpServletRequest.cpp @@ -1,5 +1,5 @@ #include "acl_stdafx.hpp" -#include "acl_cpp/stdlib//dbuf_pool.hpp" +#include "acl_cpp/stdlib/dbuf_pool.hpp" #include "acl_cpp/stdlib/snprintf.hpp" #include "acl_cpp/stdlib/log.hpp" #include "acl_cpp/stdlib/string.hpp" @@ -28,7 +28,7 @@ namespace acl HttpServletRequest::HttpServletRequest(HttpServletResponse& res, session& store, socket_stream& stream, const char* charset /* = NULL */, bool body_parse /* = true */, - int body_limit /* = 102400 */, dbuf_pool* dbuf /* = NULL */) + int body_limit /* = 102400 */) : req_error_(HTTP_REQ_OK) , res_(res) , store_(store) @@ -45,16 +45,8 @@ HttpServletRequest::HttpServletRequest(HttpServletResponse& res, , xml_(NULL) , readHeaderCalled_(false) { - if (dbuf != NULL) - { - dbuf_ = dbuf; - dbuf_internal_ = NULL; - } - else - { - dbuf_internal_ = new dbuf_pool; - dbuf_ = dbuf_internal_; - } + dbuf_internal_ = new dbuf_guard; + dbuf_ = dbuf_internal_; COPY(cookie_name_, "ACL_SESSION_ID"); ACL_VSTREAM* in = stream.get_vstream(); @@ -73,23 +65,9 @@ HttpServletRequest::HttpServletRequest(HttpServletResponse& res, HttpServletRequest::~HttpServletRequest(void) { - std::vector::iterator it = cookies_.begin(); - for (; it != cookies_.end(); ++it) - (*it)->~HttpCookie(); - - if (http_session_) - http_session_->~HttpSession(); if (client_) client_->~http_client(); - if (mime_) - mime_->~http_mime(); - if (json_) - json_->~json(); - if (xml_) - xml_->~xml(); - - if (dbuf_internal_) - dbuf_internal_->destroy(); + delete dbuf_internal_; } http_method_t HttpServletRequest::getMethod(string* method_s /* = NULL */) const @@ -121,17 +99,15 @@ void HttpServletRequest::add_cookie(char* data) char* end = ptr + strlen(ptr) - 1; while (end > ptr && (*end == ' ' || *end == '\t')) *end-- = 0; - HttpCookie* cookie = new (dbuf_->dbuf_alloc(sizeof(HttpCookie))) - HttpCookie(data, ptr, dbuf_); - cookies_.push_back(cookie); + setCookie(data, ptr); } void HttpServletRequest::setCookie(const char* name, const char* value) { if (name == NULL || *name == 0 || value == NULL) return; - HttpCookie* cookie = new (dbuf_->dbuf_alloc(sizeof(HttpCookie))) - HttpCookie(name, value, dbuf_); + HttpCookie* cookie = dbuf_->create (name, value, dbuf_); cookies_.push_back(cookie); } @@ -167,23 +143,21 @@ const std::vector& HttpServletRequest::getCookies(void) const if (req->cookies_table == NULL) return cookies_; - const char* name, *value; - HttpCookie* cookie; ACL_HTABLE_ITER iter; // 遍历 HTTP 请求头中的 cookie 项 acl_htable_foreach(iter, req->cookies_table) { - name = acl_htable_iter_key(iter); - value = (char*) acl_htable_iter_value(iter); + const char* name = acl_htable_iter_key(iter); + const char* value = (char*) acl_htable_iter_value(iter); if (name == NULL || *name == 0 || value == NULL || *value == 0) { continue; } // 创建 cookie 对象并将之加入数组中 - cookie = new (dbuf_->dbuf_alloc(sizeof(HttpCookie))) - HttpCookie(name, value, dbuf_); + HttpCookie* cookie = dbuf_->create(name, value, dbuf_); const_cast (this)->cookies_.push_back(cookie); } @@ -255,8 +229,7 @@ HttpSession& HttpServletRequest::getSession(bool create /* = true */, if (http_session_ != NULL) return *http_session_; - http_session_ = new (dbuf_->dbuf_alloc(sizeof(HttpSession))) - HttpSession(store_); + http_session_ = dbuf_->create(store_); const char* sid; if ((sid = getCookieValue(cookie_name_)) != NULL) @@ -266,8 +239,8 @@ HttpSession& HttpServletRequest::getSession(bool create /* = true */, // 获得唯一 ID 标识符 sid = store_.get_sid(); // 生成 cookie 对象,并分别向请求对象和响应对象添加 cookie - HttpCookie* cookie = new (dbuf_->dbuf_alloc(sizeof(HttpCookie))) - HttpCookie(cookie_name_, sid, dbuf_); + HttpCookie* cookie = dbuf_->create(cookie_name_, sid, dbuf_); res_.addCookie(cookie); setCookie(cookie_name_, sid); } @@ -275,8 +248,8 @@ HttpSession& HttpServletRequest::getSession(bool create /* = true */, { store_.set_sid(sid_in); // 生成 cookie 对象,并分别向请求对象和响应对象添加 cookie - HttpCookie* cookie = new (dbuf_->dbuf_alloc(sizeof(HttpCookie))) - HttpCookie(cookie_name_, sid_in, dbuf_); + HttpCookie* cookie = dbuf_->create(cookie_name_, sid_in, dbuf_); res_.addCookie(cookie); setCookie(cookie_name_, sid_in); } @@ -556,7 +529,6 @@ bool HttpServletRequest::readHeader(string* method_s) { client_ = new (dbuf_->dbuf_alloc(sizeof(http_client))) http_client(&stream_, rw_timeout_); - if (client_->read_head() == false) { req_error_ = HTTP_REQ_ERR_IO; @@ -638,8 +610,8 @@ bool HttpServletRequest::readHeader(string* method_s) else { request_type_ = HTTP_REQUEST_MULTIPART_FORM; - mime_ = new (dbuf_->dbuf_alloc(sizeof(http_mime))) - http_mime(bound, localCharset_); + mime_ = dbuf_->create(bound, localCharset_); } return true; @@ -677,12 +649,17 @@ bool HttpServletRequest::readHeader(string* method_s) return ret == -1 ? false : true; } + if (!EQ(ctype, "text")) + { + request_type_ = HTTP_REQUEST_OTHER; + return true; + } // 当数据类型为 text/json 格式时: - if (EQ(ctype, "text") && EQ(stype, "json")) + else if (EQ(stype, "json")) { request_type_ = HTTP_REQUEST_TEXT_JSON; - json_ = new (dbuf_->dbuf_alloc(sizeof(json))) json(); + json_ = dbuf_->create(); ssize_t dlen = (ssize_t) len, n; char buf[8192]; istream& in = getInputStream(); @@ -702,10 +679,10 @@ bool HttpServletRequest::readHeader(string* method_s) } // 当数据类型为 text/xml 格式时: - if (EQ(ctype, "text") && EQ(stype, "xml")) + else if (EQ(stype, "xml")) { request_type_ = HTTP_REQUEST_TEXT_XML; - xml_ = new (dbuf_->dbuf_alloc(sizeof(xml1))) xml1(); + xml_ = dbuf_->create(); ssize_t dlen = (ssize_t) len, n; char buf[8192]; istream& in = getInputStream(); @@ -723,9 +700,11 @@ bool HttpServletRequest::readHeader(string* method_s) } return true; } - - request_type_ = HTTP_REQUEST_OTHER; - return true; + else + { + request_type_ = HTTP_REQUEST_OTHER; + return true; + } } const char* HttpServletRequest::getRequestReferer(void) const diff --git a/lib_acl_cpp/src/http/HttpServletResponse.cpp b/lib_acl_cpp/src/http/HttpServletResponse.cpp index 59593834b..a820bbbf2 100644 --- a/lib_acl_cpp/src/http/HttpServletResponse.cpp +++ b/lib_acl_cpp/src/http/HttpServletResponse.cpp @@ -6,33 +6,22 @@ #include "acl_cpp/stream/socket_stream.hpp" #include "acl_cpp/http/http_header.hpp" #include "acl_cpp/http/http_client.hpp" -#include "acl_cpp/http/HttpServlet.hpp" #include "acl_cpp/http/HttpServletRequest.hpp" #include "acl_cpp/http/HttpServletResponse.hpp" namespace acl { -HttpServletResponse::HttpServletResponse(socket_stream& stream, - dbuf_pool* dbuf /* = NULL */) +HttpServletResponse::HttpServletResponse(socket_stream& stream) : stream_(stream) , request_(NULL) { - if (dbuf != NULL) - { - dbuf_ = dbuf; - dbuf_internal_ = NULL; - } - else - { - dbuf_internal_ = new dbuf_pool; - dbuf_ = dbuf_internal_; - } + dbuf_internal_ = new dbuf_guard; + dbuf_ = dbuf_internal_; client_ = new (dbuf_->dbuf_alloc(sizeof(http_client))) http_client(&stream_, stream_.get_rw_timeout()); - header_ = new (dbuf_->dbuf_alloc(sizeof(http_header))) - http_header(dbuf_); + header_ = dbuf_->create(dbuf_); header_->set_request_mode(false); charset_[0] = 0; @@ -43,10 +32,7 @@ HttpServletResponse::HttpServletResponse(socket_stream& stream, HttpServletResponse::~HttpServletResponse(void) { client_->~http_client(); - header_->~http_header(); - - if (dbuf_internal_) - dbuf_internal_->destroy(); + delete dbuf_internal_; } HttpServletResponse& HttpServletResponse::setRedirect( diff --git a/lib_acl_cpp/src/http/http_header.cpp b/lib_acl_cpp/src/http/http_header.cpp index 9c7f8ac5f..c09bcfc60 100644 --- a/lib_acl_cpp/src/http/http_header.cpp +++ b/lib_acl_cpp/src/http/http_header.cpp @@ -13,7 +13,7 @@ namespace acl #define CP(x, y) ACL_SAFE_STRNCPY(x, y, sizeof(x)) -http_header::http_header(dbuf_pool* dbuf /* = NULL */) +http_header::http_header(dbuf_guard* dbuf /* = NULL */) { if (dbuf != NULL) { @@ -22,13 +22,13 @@ http_header::http_header(dbuf_pool* dbuf /* = NULL */) } else { - dbuf_internal_ = new dbuf_pool; + dbuf_internal_ = new dbuf_guard; dbuf_ = dbuf_internal_; } init(); } -http_header::http_header(const char* url, dbuf_pool* dbuf /* = NULL */) +http_header::http_header(const char* url, dbuf_guard* dbuf /* = NULL */) { if (dbuf != NULL) { @@ -37,7 +37,7 @@ http_header::http_header(const char* url, dbuf_pool* dbuf /* = NULL */) } else { - dbuf_internal_ = new dbuf_pool; + dbuf_internal_ = new dbuf_guard; dbuf_ = dbuf_internal_; } init(); @@ -45,7 +45,7 @@ http_header::http_header(const char* url, dbuf_pool* dbuf /* = NULL */) set_url(url); } -http_header::http_header(int status, dbuf_pool* dbuf /* = NULL */) +http_header::http_header(int status, dbuf_guard* dbuf /* = NULL */) { if (dbuf != NULL) { @@ -54,7 +54,7 @@ http_header::http_header(int status, dbuf_pool* dbuf /* = NULL */) } else { - dbuf_internal_ = new dbuf_pool; + dbuf_internal_ = new dbuf_guard; dbuf_ = dbuf_internal_; } init(); @@ -64,8 +64,7 @@ http_header::http_header(int status, dbuf_pool* dbuf /* = NULL */) http_header::~http_header(void) { clear(); - if (dbuf_internal_) - dbuf_internal_->destroy(); + delete dbuf_internal_; } void http_header::init() @@ -90,9 +89,6 @@ void http_header::init() void http_header::clear() { - std::list::iterator it = cookies_.begin(); - for (; it != cookies_.end(); ++it) - (*it)->~HttpCookie(); cookies_.clear(); entries_.clear(); params_.clear(); @@ -170,8 +166,8 @@ http_header& http_header::add_cookie(const char* name, const char* value, if (name == NULL || *name == 0 || value == NULL) return *this; - HttpCookie* cookie = new (dbuf_->dbuf_alloc((sizeof(HttpCookie)))) - HttpCookie(name, value, dbuf_); + HttpCookie* cookie = dbuf_->create(name, value, dbuf_); if (domain && *domain) cookie->setDomain(domain); @@ -188,8 +184,8 @@ http_header& http_header::add_cookie(const HttpCookie* in) if (in == NULL) return *this; - HttpCookie* cookie = new (dbuf_->dbuf_alloc(sizeof(HttpCookie))) - HttpCookie(in); + HttpCookie* cookie = dbuf_->create (in, dbuf_); cookies_.push_back(cookie); return *this; } diff --git a/lib_acl_cpp/src/http/http_mime.cpp b/lib_acl_cpp/src/http/http_mime.cpp index 7f6b93f31..ba8749557 100644 --- a/lib_acl_cpp/src/http/http_mime.cpp +++ b/lib_acl_cpp/src/http/http_mime.cpp @@ -135,9 +135,7 @@ http_mime::http_mime(const char* boundary, if (boundary == NULL || strlen(boundary) < 2) { logger_error("boundary invalid"); - boundary = NULL; mime_state_ = NULL; - save_path_ = NULL; return; } // HTTP 的 MIME 格式与 邮件的 MIME 的分隔符有所不同, @@ -149,7 +147,7 @@ http_mime::http_mime(const char* boundary, boundary++; if (*boundary == '-') boundary++; - boundary_ = acl_mystrdup(boundary); + boundary_ = boundary; if (local_charset && *local_charset) safe_snprintf(local_charset_, sizeof(local_charset_), @@ -159,7 +157,7 @@ http_mime::http_mime(const char* boundary, decode_on_ = true; - save_path_ = NULL; + save_path_.clear(); mime_state_ = mime_state_alloc(); // 为了使用邮件的 mime 解析器,需要模拟出一个头部字段 @@ -177,10 +175,6 @@ http_mime::http_mime(const char* boundary, http_mime::~http_mime() { - if (boundary_) - acl_myfree(boundary_); - if (save_path_) - acl_myfree(save_path_); if (mime_state_) mime_state_free(mime_state_); std::list::iterator it = mime_nodes_.begin(); @@ -191,7 +185,7 @@ http_mime::~http_mime() void http_mime::set_saved_path(const char* path) { if (path && *path) - save_path_ = acl_mystrdup(path); + save_path_ = path; } bool http_mime::update(const char* data, size_t len) diff --git a/lib_acl_cpp/src/mime/internal/mime_state.cpp b/lib_acl_cpp/src/mime/internal/mime_state.cpp index 21f616fcc..d2475f228 100644 --- a/lib_acl_cpp/src/mime/internal/mime_state.cpp +++ b/lib_acl_cpp/src/mime/internal/mime_state.cpp @@ -159,8 +159,10 @@ static void mime_node_free(MIME_NODE *node) acl_vstring_free(node->buffer); if (node->boundary) acl_vstring_free(node->boundary); +#ifdef SAVE_BODY if (node->body) acl_vstring_free(node->body); +#endif acl_myfree(node); } @@ -498,3 +500,16 @@ const char *mime_stype_name(size_t stype) return (OTHER_NAME); return (mime_stype_map[stype - MIME_STYPE_MIN].name); } + +const char *mime_head_value(MIME_NODE* node, const char* name) +{ + ACL_ITER iter; + acl_foreach(iter, node->header_list) + { + HEADER_NV* hdr = (HEADER_NV*) iter.data; + if (strcasecmp(hdr->name, name) == 0 && *hdr->value) + return (hdr->value); + } + + return NULL; +} diff --git a/lib_acl_cpp/src/mime/internal/mime_state.hpp b/lib_acl_cpp/src/mime/internal/mime_state.hpp index 1420d1844..23714fef9 100644 --- a/lib_acl_cpp/src/mime/internal/mime_state.hpp +++ b/lib_acl_cpp/src/mime/internal/mime_state.hpp @@ -15,6 +15,8 @@ struct MAIL_ADDR char *comment; }; +//#define SAVE_BODY + struct MIME_NODE { ACL_RING children; /**< 子结点集合 */ @@ -59,7 +61,9 @@ struct MIME_NODE char bound_term[3]; ACL_VSTRING *buffer; /**< headers, quoted-printable body */ +#ifdef SAVE_BODY ACL_VSTRING *body; +#endif ACL_RING node; /**< 当前结点 */ off_t header_begin; /**< 结点头开始位置 */ @@ -131,5 +135,6 @@ int mime_node_delete(MIME_NODE *node); void mime_node_add_child(MIME_NODE *parent, MIME_NODE *child); const char *mime_ctype_name(size_t ctype); const char *mime_stype_name(size_t stype); +const char *mime_head_value(MIME_NODE *node, const char *name); #endif diff --git a/lib_acl_cpp/src/mime/internal/mime_state_parse.cpp b/lib_acl_cpp/src/mime/internal/mime_state_parse.cpp index b7ca0e34e..ea8f0391e 100644 --- a/lib_acl_cpp/src/mime/internal/mime_state_parse.cpp +++ b/lib_acl_cpp/src/mime/internal/mime_state_parse.cpp @@ -607,14 +607,113 @@ static int mime_state_head(MIME_STATE *state, const char *s, int n) return n; } +#if 1 + +// 分析 multipart 部分体, 当匹配到一个完整的分隔符后则表明该部分数据体分析完毕 +static int mime_bound_body(MIME_STATE *state, const char * const boundary, + MIME_NODE *node, const char *s, int n, int *finish) +{ + const unsigned char *cp = (const unsigned char*) s; + const unsigned char *end = (const unsigned char*) s + n; + size_t bound_len = strlen(boundary); + off_t curr_off = state->curr_off; + off_t last_cr_pos = node->last_cr_pos; + off_t last_lf_pos = node->last_lf_pos; + const char *bound_ptr = node->bound_ptr; + unsigned char ch; +#ifdef SAVE_BODY + const unsigned char *startn = NULL; +#endif + + for (; cp < end; cp++) { + ch = *cp; + + // 记录下 \r\n 的位置 + if (ch == '\r') + last_cr_pos = curr_off; + else if (ch == '\n') + last_lf_pos = curr_off; + + curr_off++; + + if (bound_ptr == NULL) { + if (ch != *boundary) { +#ifdef SAVE_BODY + ADDCH(node->body, ch); +#endif + continue; + } + +#ifdef SAVE_BODY + startn = cp; +#endif + bound_ptr = boundary; + } + + if (ch != *bound_ptr) { +#ifdef SAVE_BODY + // 说明之前的匹配失效,需要重新匹配, + // 但必须将之前匹配的字符拷贝 + if (bound_ptr > boundary) { + APPEND(node->body, boundary, + bound_ptr - boundary); + } +#endif + + bound_ptr = NULL; + } else if (*++bound_ptr == 0) { + /* 说明完全匹配 */ + *finish = 1; + + node->body_end = curr_off - bound_len; + node->body_data_end = node->body_end; + + // 因为 body_end 记录的是某个结点最后的位置, + // 其中会包含, 根据协议附加的 \r\n,所以真实 + // 数据的结束位置 body_data_end 是去掉这些数据 + // 后的位置 + if (last_lf_pos + (off_t) bound_len == curr_off - 1) + { + node->body_data_end--; + if (last_cr_pos + 1 == last_lf_pos) + node->body_data_end--; + } + +#ifdef SAVE_BODY + if (startn > (const unsigned char *) s) { + /* 将匹配之前的数据拷贝 */ + APPEND(node->body, (const char*) s, + (const char*) startn - s); + } +#endif + bound_ptr = NULL; + cp++; + break; + } + } + + node->bound_ptr = bound_ptr; + node->last_cr_pos = last_cr_pos; + node->last_lf_pos = last_lf_pos; + state->curr_off = curr_off; + + return (int) (n - ((const char*) cp - s)); +} + +#else + // 分析 multipart 部分体, 当匹配到一个完整的分隔符后则表明该部分数据体分析完毕 static int mime_bound_body(MIME_STATE *state, const char *boundary, MIME_NODE *node, const char *s, int n, int *finish) { const unsigned char *cp, *end = (const unsigned char*) s + n; +#ifdef SAVE_BODY const unsigned char *startn = NULL; +#endif size_t bound_len = strlen(boundary); +// printf(">>>size: %ld\r\n", (long) ACL_VSTRING_SIZE(node->body)); + for (cp = (const unsigned char *) s; cp < end; cp++) { // 记录下 \r\n 的位置 if (*cp == '\r') @@ -626,12 +725,14 @@ static int mime_bound_body(MIME_STATE *state, const char *boundary, if (node->bound_ptr != NULL) { if (*cp != *node->bound_ptr) { +#ifdef SAVE_BODY // 说明之前的匹配失效,需要重新匹配, // 但必须将之前匹配的字符拷贝 if (node->bound_ptr > boundary) { APPEND(node->body, boundary, node->bound_ptr - boundary); } +#endif node->bound_ptr = NULL; } else if (*++node->bound_ptr == 0) { @@ -654,11 +755,13 @@ static int mime_bound_body(MIME_STATE *state, const char *boundary, node->body_data_end--; } +#ifdef SAVE_BODY if (startn > (const unsigned char *) s) { /* 将匹配之前的数据拷贝 */ APPEND(node->body, (const char*) s, (const char*) startn - s); } +#endif node->bound_ptr = NULL; cp++; break; @@ -669,7 +772,9 @@ static int mime_bound_body(MIME_STATE *state, const char *boundary, // --> node->bound_ptr == NULL if (*cp != *boundary) { +#ifdef SAVE_BODY ADDCH(node->body, *cp); +#endif continue; } @@ -698,25 +803,33 @@ static int mime_bound_body(MIME_STATE *state, const char *boundary, break; } +#ifdef SAVE_BODY startn = cp; +#endif } return (int) (n - ((const char*) cp - s)); } +#endif + // 分析邮件体或 multipart 部分体 static int mime_state_body(MIME_STATE *state, const char *s, int n) { int finish = 0; +#ifdef SAVE_BODY if (state->curr_node->body == NULL) state->curr_node->body = acl_vstring_alloc(1024); +#endif if (state->curr_bound == NULL) { /* 如果没有分隔符,则说明是文本类型,即只有正文内容 */ +#ifdef SAVE_BODY APPEND(state->curr_node->body, s, n); +#endif state->curr_off += n; /* 因为 curr_off 指向下一个偏移位置,所以 diff --git a/lib_acl_cpp/src/mime/mime.cpp b/lib_acl_cpp/src/mime/mime.cpp index cd7da0f30..ceed89fbc 100644 --- a/lib_acl_cpp/src/mime/mime.cpp +++ b/lib_acl_cpp/src/mime/mime.cpp @@ -611,6 +611,11 @@ const std::list& mime::get_mime_nodes(bool enableDecode /* = true */ return (*m_pNodes); } +static bool has_content_id(MIME_NODE* node) +{ + return mime_head_value(node, "Content-ID") == NULL ? false : true; +} + const std::list& mime::get_attachments(bool enableDecode /* = true */, const char* toCharset /* = "gb2312" */, off_t off /* = 0 */) { @@ -628,11 +633,12 @@ const std::list& mime::get_attachments(bool enableDecode /* = true acl_foreach(iter, m_pMimeState) { node = (MIME_NODE*) iter.data; - if (node->header_filename == NULL) - continue; - attach = NEW mime_attach(m_pFilePath, node, - enableDecode, toCharset, off); - m_pAttaches->push_back(attach); + if (node->header_filename != NULL || has_content_id(node)) + { + attach = NEW mime_attach(m_pFilePath, node, + enableDecode, toCharset, off); + m_pAttaches->push_back(attach); + } } return (*m_pAttaches); } diff --git a/lib_acl_cpp/src/stdlib/charset_conv.cpp b/lib_acl_cpp/src/stdlib/charset_conv.cpp index 36267af9a..506be939e 100644 --- a/lib_acl_cpp/src/stdlib/charset_conv.cpp +++ b/lib_acl_cpp/src/stdlib/charset_conv.cpp @@ -356,7 +356,6 @@ bool charset_conv::update(const char* in, size_t len, acl::string* out) ret = __iconv(m_iconv, &pIn, &nIn, &pOut, &nOut); #endif - if (ret != (size_t) -1) { if ((ret = SIZE(m_pOutBuf) - nOut) > 0) @@ -411,8 +410,9 @@ bool charset_conv::update(const char* in, size_t len, acl::string* out) acl_assert(pIn >= STR(m_pInBuf)); - // 跳过无效字节 - (*out) += (char)(*pIn); // 直接拷贝无效字节 + // 是否跳过无效字节? + if (m_addInvalid) + (*out) += (char)(*pIn); // 直接拷贝无效字节 nIn--; pIn++; if (nIn > 0) diff --git a/lib_acl_cpp/src/stdlib/string.cpp b/lib_acl_cpp/src/stdlib/string.cpp index 4bdc56ead..d82f6aeb8 100644 --- a/lib_acl_cpp/src/stdlib/string.cpp +++ b/lib_acl_cpp/src/stdlib/string.cpp @@ -63,6 +63,24 @@ string::string(const void* s, size_t n) : use_bin_(false) TERM(vbf_); } +#if !defined(_WIN32) && !defined(_WIN64) +string::string(int fd, size_t max, size_t n) +{ + if (n < 1) + n = 1; + if (fd >= 0) + vbf_ = acl_vstring_mmap_alloc(fd, max, n); + else + vbf_ = ALLOC(n); + list_tmp_ = NULL; + vector_tmp_ = NULL; + pair_tmp_ = NULL; + scan_ptr_ = NULL; + line_state_ = NULL; + line_state_offset_ = 0; +} +#endif + string::~string() { FREE(vbf_); diff --git a/lib_acl_cpp/src/stdlib/xml.cpp b/lib_acl_cpp/src/stdlib/xml.cpp index 41eae9640..0864fc31b 100644 --- a/lib_acl_cpp/src/stdlib/xml.cpp +++ b/lib_acl_cpp/src/stdlib/xml.cpp @@ -124,15 +124,17 @@ void xml::clear(void) if (buf_) buf_->clear(); - std::vector::iterator it = elements_.begin(); - for (; it != elements_.end(); ++it) - delete (*it); + //std::vector::iterator it = elements_.begin(); + //for (; it != elements_.end(); ++it) + // delete (*it); elements_.clear(); - std::list::iterator it1 = nodes_tmp_.begin(); - for (; it1 != nodes_tmp_.end(); ++it1) - delete (*it1); - nodes_tmp_.clear(); + //std::list::iterator it1 = nodes_tmp_.begin(); + //for (; it1 != nodes_tmp_.end(); ++it1) + // delete (*it1); + //nodes_tmp_.clear(); + + dbuf_.dbuf_reset(); } const acl::string& xml::getText() diff --git a/lib_acl_cpp/src/stdlib/xml1.cpp b/lib_acl_cpp/src/stdlib/xml1.cpp index 5519caf45..fadc7ea3e 100644 --- a/lib_acl_cpp/src/stdlib/xml1.cpp +++ b/lib_acl_cpp/src/stdlib/xml1.cpp @@ -264,7 +264,10 @@ const std::vector& xml1::getElementsByTagName(const char* tag) const acl_foreach(iter, a) { ACL_XML_NODE *tmp = (ACL_XML_NODE*) iter.data; - xml1_node* node = NEW xml1_node(const_cast(this), tmp); +// xml1_node* node = NEW xml1_node(const_cast(this), tmp); + xml1_node* node = const_cast(dbuf_) + .create + (const_cast(this), tmp); const_cast(this)->elements_.push_back(node); } @@ -278,8 +281,11 @@ xml_node* xml1::getFirstElementByTag(const char* tag) const if (node == NULL) return NULL; - xml1_node* n = NEW xml1_node(const_cast(this), node); - const_cast(this)->nodes_tmp_.push_back(n); +// xml1_node* n = NEW xml1_node(const_cast(this), node); +// const_cast(this)->nodes_tmp_.push_back(n); + xml1_node* n = const_cast(dbuf_) + .create + (const_cast(this), node); return n; } @@ -295,7 +301,10 @@ const std::vector& xml1::getElementsByTags(const char* tags) const acl_foreach(iter, a) { ACL_XML_NODE *tmp = (ACL_XML_NODE*) iter.data; - xml1_node* node = NEW xml1_node(const_cast(this), tmp); +// xml1_node* node = NEW xml1_node(const_cast(this), tmp); + xml1_node* node = const_cast(dbuf_) + .create + (const_cast(this), tmp); const_cast(this)->elements_.push_back(node); } @@ -312,8 +321,11 @@ xml_node* xml1::getFirstElementByTags(const char* tags) const ACL_XML_NODE* node = (ACL_XML_NODE*) acl_array_index(a, 0); acl_assert(node); - xml1_node* n = NEW xml1_node(const_cast(this), node); - const_cast(this)->nodes_tmp_.push_back(n); +// xml1_node* n = NEW xml1_node(const_cast(this), node); +// const_cast(this)->nodes_tmp_.push_back(n); + xml1_node* n = const_cast(dbuf_) + .create + (const_cast(this), node); acl_xml_free_array(a); return n; @@ -330,7 +342,10 @@ const std::vector& xml1::getElementsByName(const char* value) const acl_foreach(iter, a) { ACL_XML_NODE *tmp = (ACL_XML_NODE*) iter.data; - xml1_node* node = NEW xml1_node(const_cast(this), tmp); +// xml1_node* node = NEW xml1_node(const_cast(this), tmp); + xml1_node* node = const_cast(dbuf_) + .create + (const_cast(this), tmp); const_cast(this)->elements_.push_back(node); } @@ -350,7 +365,10 @@ const std::vector& xml1::getElementsByAttr( acl_foreach(iter, a) { ACL_XML_NODE *tmp = (ACL_XML_NODE*) iter.data; - xml1_node* node = NEW xml1_node(const_cast(this), tmp); +// xml1_node* node = NEW xml1_node(const_cast(this), tmp); + xml1_node* node = const_cast(dbuf_) + .create + (const_cast(this), tmp); const_cast(this)->elements_.push_back(node); } @@ -364,8 +382,11 @@ xml_node* xml1::getElementById(const char* id) const if (node == NULL) return NULL; - xml1_node* n = NEW xml1_node(const_cast(this), node); - const_cast(this)->nodes_tmp_.push_back(n); +// xml1_node* n = NEW xml1_node(const_cast(this), node); +// const_cast(this)->nodes_tmp_.push_back(n); + xml1_node* n = const_cast(dbuf_) + .create + (const_cast(this), node); return n; } @@ -462,8 +483,10 @@ const acl::string& xml1::getText() xml_node& xml1::create_node(const char* tag, const char* text /* = NULL */) { ACL_XML_NODE* node = acl_xml_create_node(xml_, tag, text); - xml1_node* n = NEW xml1_node(this, node); - nodes_tmp_.push_back(n); +// xml1_node* n = NEW xml1_node(this, node); +// nodes_tmp_.push_back(n); + xml1_node* n = dbuf_.create + (this, node); return *n; } @@ -484,8 +507,10 @@ xml_node* xml1::first_node(void) if (node == NULL) return NULL; - xml1_node* n = NEW xml1_node(this, node); - nodes_tmp_.push_back(n); +// xml1_node* n = NEW xml1_node(this, node); +// nodes_tmp_.push_back(n); + xml1_node* n = dbuf_.create + (this, node); return n; } @@ -497,8 +522,10 @@ xml_node* xml1::next_node(void) if (node == NULL) return NULL; - xml1_node* n = NEW xml1_node(this, node); - nodes_tmp_.push_back(n); +// xml1_node* n = NEW xml1_node(this, node); +// nodes_tmp_.push_back(n); + xml1_node* n = dbuf_.create + (this, node); return n; } diff --git a/lib_acl_cpp/src/stdlib/xml2.cpp b/lib_acl_cpp/src/stdlib/xml2.cpp index fa7dc853c..996cdc00f 100644 --- a/lib_acl_cpp/src/stdlib/xml2.cpp +++ b/lib_acl_cpp/src/stdlib/xml2.cpp @@ -206,66 +206,52 @@ int xml2_node::children_count(void) const ////////////////////////////////////////////////////////////////////// -xml2::xml2(char* addr, size_t size, const char* data /* = NULL */) +xml2::xml2(const char* filepath, size_t max_len, const char* data /* = NULL */, + size_t init_len /* = 8192 */) { - acl_assert(addr && size > 0); + acl_assert(filepath && max_len > 0 && init_len > 0); + + if (max_len < init_len) + max_len = init_len; iter_ = NULL; root_ = NULL; - xml_ = acl_xml2_alloc(addr, size); - - if (data && *data) - update(data); -} - -xml2::xml2(const char* filepath, size_t size, const char* data /* = NULL */, - size_t block /* = 8192 */, bool keep_open /* = true */) -{ - acl_assert(filepath && size > 0 && block > 0); - - if (block > size) - block = size; - - iter_ = NULL; - root_ = NULL; - - xml_ = acl_xml2_mmap_file(filepath, size, block, - keep_open ? 1 : 0, NULL); + xml_ = acl_xml2_mmap_file(filepath, max_len, init_len, NULL); if (data && *data) update(data); } -xml2::xml2(fstream& fp, size_t size, const char* data /* = NULL */, - size_t block /* = 8192 */) +xml2::xml2(fstream& fp, size_t max_len, const char* data /* = NULL */, + size_t init_len /* = 8192 */) { - acl_assert(size > 0 && block > 0); + acl_assert(max_len > 0 && init_len > 0); - if (block > size) - block = size; + if (max_len < init_len) + max_len = init_len; iter_ = NULL; root_ = NULL; - xml_ = acl_xml2_mmap_fd((ACL_FILE_HANDLE) fp.file_handle(), - size, block, NULL); + xml_ = acl_xml2_mmap_fd(fp.file_handle(), + max_len, init_len, NULL); if (data && *data) update(data); } -xml2::xml2(ACL_FILE_HANDLE fd, size_t size, const char* data /* = NULL */, - size_t block /* = 8192 */) +xml2::xml2(ACL_FILE_HANDLE fd, size_t max_len, const char* data /* = NULL */, + size_t init_len /* = 8192 */) { acl_assert(fd != ACL_FILE_INVALID); - acl_assert(size > 0); + acl_assert(max_len > 0); - if (block > size) - block = size; + if (init_len > max_len) + max_len = init_len; - xml_ = acl_xml2_mmap_fd(fd, size, block, NULL); + xml_ = acl_xml2_mmap_fd(fd, max_len, init_len, NULL); if (data && *data) update(data); @@ -308,7 +294,10 @@ const std::vector& xml2::getElementsByTagName(const char* tag) const acl_foreach(iter, a) { ACL_XML2_NODE *tmp = (ACL_XML2_NODE*) iter.data; - xml2_node* node = NEW xml2_node(const_cast(this), tmp); +// xml2_node* node = NEW xml2_node(const_cast(this), tmp); + xml2_node* node = const_cast(dbuf_) + .create + (const_cast(this), tmp); const_cast(this)->elements_.push_back(node); } @@ -322,8 +311,11 @@ xml_node* xml2::getFirstElementByTag(const char* tag) const if (node == NULL) return NULL; - xml2_node* n = NEW xml2_node(const_cast(this), node); - const_cast(this)->nodes_tmp_.push_back(n); +// xml2_node* n = NEW xml2_node(const_cast(this), node); +// const_cast(this)->nodes_tmp_.push_back(n); + xml2_node* n = const_cast(dbuf_) + .create + (const_cast(this), node); return n; } @@ -339,7 +331,10 @@ const std::vector& xml2::getElementsByTags(const char* tags) const acl_foreach(iter, a) { ACL_XML2_NODE *tmp = (ACL_XML2_NODE*) iter.data; - xml2_node* node = NEW xml2_node(const_cast(this), tmp); +// xml2_node* node = NEW xml2_node(const_cast(this), tmp); + xml2_node* node = const_cast(dbuf_) + .create + (const_cast(this), tmp); const_cast(this)->elements_.push_back(node); } @@ -356,8 +351,11 @@ xml_node* xml2::getFirstElementByTags(const char* tags) const ACL_XML2_NODE* node = (ACL_XML2_NODE*) acl_array_index(a, 0); acl_assert(node); - xml2_node* n = NEW xml2_node(const_cast(this), node); - const_cast(this)->nodes_tmp_.push_back(n); +// xml2_node* n = NEW xml2_node(const_cast(this), node); +// const_cast(this)->nodes_tmp_.push_back(n); + xml2_node* n = const_cast(dbuf_) + .create + (const_cast(this), node); acl_xml_free_array(a); return n; @@ -374,7 +372,10 @@ const std::vector& xml2::getElementsByName(const char* value) const acl_foreach(iter, a) { ACL_XML2_NODE *tmp = (ACL_XML2_NODE*) iter.data; - xml2_node* node = NEW xml2_node(const_cast(this), tmp); +// xml2_node* node = NEW xml2_node(const_cast(this), tmp); + xml2_node* node = const_cast(dbuf_) + .create + (const_cast(this), tmp); const_cast(this)->elements_.push_back(node); } @@ -394,7 +395,10 @@ const std::vector& xml2::getElementsByAttr( acl_foreach(iter, a) { ACL_XML2_NODE *tmp = (ACL_XML2_NODE*) iter.data; - xml2_node* node = NEW xml2_node(const_cast(this), tmp); +// xml2_node* node = NEW xml2_node(const_cast(this), tmp); + xml2_node* node = const_cast(dbuf_) + .create + (const_cast(this), tmp); const_cast(this)->elements_.push_back(node); } @@ -408,8 +412,11 @@ xml_node* xml2::getElementById(const char* id) const if (node == NULL) return (NULL); - xml2_node* n = NEW xml2_node(const_cast(this), node); - const_cast(this)->nodes_tmp_.push_back(n); +// xml2_node* n = NEW xml2_node(const_cast(this), node); +// const_cast(this)->nodes_tmp_.push_back(n); + xml2_node* n = const_cast(dbuf_) + .create + (const_cast(this), node); return n; } @@ -427,8 +434,10 @@ const acl::string& xml2::getText() xml_node& xml2::create_node(const char* tag, const char* text /* = NULL */) { ACL_XML2_NODE* node = acl_xml2_create_node(xml_, tag, text); - xml2_node* n = NEW xml2_node(this, node); - nodes_tmp_.push_back(n); +// xml2_node* n = NEW xml2_node(this, node); +// nodes_tmp_.push_back(n); + xml2_node* n = dbuf_.create + (this, node); return *n; } @@ -449,8 +458,10 @@ xml_node* xml2::first_node(void) if (node == NULL) return NULL; - xml2_node* n = NEW xml2_node(this, node); - nodes_tmp_.push_back(n); +// xml2_node* n = NEW xml2_node(this, node); +// nodes_tmp_.push_back(n); + xml2_node* n = dbuf_.create + (this, node); return n; } @@ -462,8 +473,10 @@ xml_node* xml2::next_node(void) if (node == NULL) return NULL; - xml2_node* n = NEW xml2_node(this, node); - nodes_tmp_.push_back(n); +// xml2_node* n = NEW xml2_node(this, node); +// nodes_tmp_.push_back(n); + xml2_node* n = dbuf_.create + (this, node); return n; } @@ -478,7 +491,7 @@ void xml2::build_xml(string& out) const const char* xml2::to_string(size_t* len /* = NULL */) const { const char* dat = acl_xml2_build(xml_); - if (dat <= xml_->addr) + if (dat >= acl_vstring_end(xml_->vbuf)) { if (len) *len = 0; @@ -486,7 +499,7 @@ const char* xml2::to_string(size_t* len /* = NULL */) const } if (len) - *len = xml_->ptr - dat; + *len = acl_vstring_end(xml_->vbuf) - dat; return dat; } diff --git a/lib_acl_cpp/src/stream/istream.cpp b/lib_acl_cpp/src/stream/istream.cpp index a51f74388..751e47b8f 100644 --- a/lib_acl_cpp/src/stream/istream.cpp +++ b/lib_acl_cpp/src/stream/istream.cpp @@ -256,7 +256,8 @@ bool istream::read_peek(string& buf, bool clear /* = false */) if (clear) buf.clear(); - if (acl_vstream_read_peek(stream_, buf.vstring()) == ACL_VSTREAM_EOF) + int n = acl_vstream_read_peek(stream_, buf.vstring()); + if (n == ACL_VSTREAM_EOF) { #if ACL_EWOULDBLOCK == ACL_EAGAIN if (stream_->errnum != ACL_EWOULDBLOCK) @@ -269,6 +270,8 @@ bool istream::read_peek(string& buf, bool clear /* = false */) } return false; } + else if (n == 0) + return false; else return true; }