mirror of
https://github.com/netdata/netdata.git
synced 2025-04-14 09:38:34 +00:00
include Judy into our source tree (#13362)
This commit is contained in:
parent
146c66b349
commit
014c9f3259
54 changed files with 26707 additions and 238 deletions
.gitignore.travis.ymlCMakeLists.txtMakefile.amconfigure.ac
contrib/debian
libnetdata/libjudy/src
Judy.h
netdata-installer.shnetdata.spec.inJudyCommon
JudyHS
JudyL
JudyL.hJudyLByCount.cJudyLCascade.cJudyLCount.cJudyLCreateBranch.cJudyLDecascade.cJudyLDel.cJudyLFirst.cJudyLFreeArray.cJudyLGet.cJudyLIns.cJudyLInsArray.cJudyLInsertBranch.cJudyLMallocIF.cJudyLMemActive.cJudyLMemUsed.cJudyLNext.cJudyLNextEmpty.cJudyLPrev.cJudyLPrevEmpty.cJudyLTablesGen.cj__udyLGet.c
packaging
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -228,3 +228,7 @@ Session.*.vim
|
|||
|
||||
# Jupyter notebook checkpoints
|
||||
.ipynb_checkpoints
|
||||
|
||||
# Judy stuff
|
||||
JudyLTables.c
|
||||
judyltablesgen
|
||||
|
|
|
@ -17,7 +17,7 @@ before_install:
|
|||
# Install dependencies for all, once
|
||||
#
|
||||
install:
|
||||
- sudo apt-get install -y libuv1-dev liblz4-dev libjudy-dev libcap2-bin zlib1g-dev uuid-dev fakeroot libipmimonitoring-dev libmnl-dev libnetfilter-acct-dev gnupg python3-pip
|
||||
- sudo apt-get install -y libuv1-dev liblz4-dev libcap2-bin zlib1g-dev uuid-dev fakeroot libipmimonitoring-dev libmnl-dev libnetfilter-acct-dev gnupg python3-pip
|
||||
- sudo pip3 install git-semver==0.3.2 # 11/Sep/2019: git-semver tip was broken, so we had to force last good run of it
|
||||
- source tests/installer/slack.sh
|
||||
- export NOTIF_CHANNEL="automation-beta"
|
||||
|
|
|
@ -102,20 +102,7 @@ set(NETDATA_COMMON_INCLUDE_DIRS ${NETDATA_COMMON_INCLUDE_DIRS} ${LIBLZ4_INCLUDE_
|
|||
# -----------------------------------------------------------------------------
|
||||
# Judy General purpose dynamic array
|
||||
|
||||
# pkgconfig not working in Ubuntu, why? upstream package broken?
|
||||
#pkg_check_modules(JUDY REQUIRED Judy)
|
||||
#set(NETDATA_COMMON_CFLAGS ${NETDATA_COMMON_CFLAGS} ${JUDY_CFLAGS_OTHER})
|
||||
#set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} ${JUDY_LIBRARIES})
|
||||
#set(NETDATA_COMMON_INCLUDE_DIRS ${NETDATA_COMMON_INCLUDE_DIRS} ${JUDY_INCLUDE_DIRS})
|
||||
set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} "-lJudy")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "Judy")
|
||||
include(CheckSymbolExists)
|
||||
check_symbol_exists("JudyLLast" "Judy.h" HAVE_JUDY)
|
||||
IF(HAVE_JUDY)
|
||||
message(STATUS "Judy library found")
|
||||
ELSE()
|
||||
message( FATAL_ERROR "libJudy required but not found. Try installing 'libjudy-dev' or 'Judy-devel'." )
|
||||
ENDIF()
|
||||
set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} judy)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# OpenSSL Cryptography and SSL/TLS Toolkit
|
||||
|
@ -362,6 +349,88 @@ ELSE()
|
|||
set(ENABLE_ML False)
|
||||
ENDIF()
|
||||
|
||||
set(LIBJUDY_SOURCES
|
||||
libnetdata/libjudy/src/Judy.h
|
||||
libnetdata/libjudy/src/JudyCommon/JudyMalloc.c
|
||||
libnetdata/libjudy/src/JudyCommon/JudyPrivate.h
|
||||
libnetdata/libjudy/src/JudyCommon/JudyPrivate1L.h
|
||||
libnetdata/libjudy/src/JudyCommon/JudyPrivateBranch.h
|
||||
libnetdata/libjudy/src/JudyL/JudyL.h
|
||||
libnetdata/libjudy/src/JudyL/JudyLByCount.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLCascade.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLCount.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLCreateBranch.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLDecascade.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLDel.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLFirst.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLFreeArray.c
|
||||
libnetdata/libjudy/src/JudyL/j__udyLGet.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLGet.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLInsArray.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLIns.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLInsertBranch.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLMallocIF.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLMemActive.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLMemUsed.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLNext.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLPrev.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c
|
||||
JudyLTables.c
|
||||
libnetdata/libjudy/src/JudyHS/JudyHS.c)
|
||||
|
||||
ADD_LIBRARY(judy STATIC
|
||||
${LIBJUDY_SOURCES})
|
||||
|
||||
ADD_EXECUTABLE(judyltablesgen
|
||||
libnetdata/libjudy/src/JudyL/JudyLTablesGen.c)
|
||||
|
||||
target_include_directories(judyltablesgen PUBLIC
|
||||
libnetdata/libjudy/src
|
||||
libnetdata/libjudy/src/JudyCommon)
|
||||
|
||||
target_compile_options(judyltablesgen PUBLIC
|
||||
-Wno-format
|
||||
-Wno-format-security)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/libnetdata/libjudy/src)
|
||||
|
||||
target_compile_definitions(judyltablesgen PUBLIC
|
||||
JU_64BIT
|
||||
JUDYL)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/JudyLTables.c
|
||||
COMMAND judyltablesgen
|
||||
DEPENDS judyltablesgen
|
||||
)
|
||||
|
||||
target_include_directories(judy PUBLIC
|
||||
libnetdata/libjudy/src
|
||||
libnetdata/libjudy/src/JudyCommon)
|
||||
|
||||
target_compile_definitions(judy PUBLIC
|
||||
JU_64BIT
|
||||
JUDYL)
|
||||
|
||||
target_compile_options(judy PUBLIC
|
||||
-Wno-sign-compare
|
||||
-Wno-implicit-fallthrough)
|
||||
|
||||
set(LIBJUDY_PREV_FILES
|
||||
libnetdata/libjudy/src/JudyL/JudyLPrev.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c)
|
||||
|
||||
set(LIBJUDY_NEXT_FILES
|
||||
libnetdata/libjudy/src/JudyL/JudyLNext.c
|
||||
libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c)
|
||||
|
||||
set_source_files_properties(${LIBJUDY_PREV_FILES} PROPERTIES COMPILE_OPTIONS "-DJUDYPREV")
|
||||
set_source_files_properties(${LIBJUDY_NEXT_FILES} PROPERTIES COMPILE_OPTIONS "-DJUDYNEXT")
|
||||
set_source_files_properties(libnetdata/libjudy/src/JudyL/j__udyLGet.c PROPERTIES COMPILE_OPTIONS "-DJUDYGETINLINE")
|
||||
set_source_files_properties(libnetdata/libjudy/src/JudyL/JudyLByCount.c PROPERTIES COMPILE_OPTIONS "-DNOSMARTJBB -DNOSMARTJBU -DNOSMARTJLB")
|
||||
set_source_files_properties(JudyLTables.c PROPERTIES COMPILE_OPTIONS "-I${CMAKE_SOURCE_DIR}/libnetdata/libjudy/src/JudyL")
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# netdata files
|
||||
|
||||
|
|
66
Makefile.am
66
Makefile.am
|
@ -61,7 +61,6 @@ dist_noinst_DATA = \
|
|||
netdata.spec \
|
||||
packaging/bundle-ebpf.sh \
|
||||
packaging/bundle-ebpf-co-re.sh \
|
||||
packaging/bundle-judy.sh \
|
||||
packaging/bundle-libbpf.sh \
|
||||
packaging/check-kernel-config.sh \
|
||||
packaging/ebpf.checksums \
|
||||
|
@ -75,8 +74,6 @@ dist_noinst_DATA = \
|
|||
packaging/installer/UPDATE.md \
|
||||
packaging/jsonc.checksums \
|
||||
packaging/jsonc.version \
|
||||
packaging/judy.checksums \
|
||||
packaging/judy.version \
|
||||
packaging/libbpf.checksums \
|
||||
packaging/libbpf.version \
|
||||
packaging/protobuf.checksums \
|
||||
|
@ -480,6 +477,64 @@ database/sqlite/sqlite3.$(OBJEXT) : CFLAGS += -Wno-cast-function-type
|
|||
database/KolmogorovSmirnovDist.$(OBJEXT) : CFLAGS += -Wno-maybe-uninitialized
|
||||
|
||||
if ENABLE_DBENGINE
|
||||
noinst_LIBRARIES = libjudy.a
|
||||
|
||||
libjudy_a_SOURCES = libnetdata/libjudy/src/Judy.h \
|
||||
libnetdata/libjudy/src/JudyCommon/JudyMalloc.c \
|
||||
libnetdata/libjudy/src/JudyCommon/JudyPrivate.h \
|
||||
libnetdata/libjudy/src/JudyCommon/JudyPrivate1L.h \
|
||||
libnetdata/libjudy/src/JudyCommon/JudyPrivateBranch.h \
|
||||
libnetdata/libjudy/src/JudyL/JudyL.h \
|
||||
libnetdata/libjudy/src/JudyL/JudyLByCount.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLCascade.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLCount.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLCreateBranch.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLDecascade.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLDel.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLFirst.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLFreeArray.c \
|
||||
libnetdata/libjudy/src/JudyL/j__udyLGet.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLGet.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLInsArray.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLIns.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLInsertBranch.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLMallocIF.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLMemActive.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLMemUsed.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLNext.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLPrev.c \
|
||||
libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c \
|
||||
libnetdata/libjudy/src/JudyHS/JudyHS.c \
|
||||
$(NULL)
|
||||
|
||||
nodist_libjudy_a_SOURCES = JudyLTables.c
|
||||
|
||||
BUILT_SOURCES += JudyLTables.c
|
||||
|
||||
CLEANFILES += JudyLTables.c
|
||||
|
||||
libjudy_a_CFLAGS = $(LIBJUDY_CFLAGS) -DJUDYL -I$(abs_top_srcdir)/libnetdata/libjudy/src -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyCommon -Wno-sign-compare -Wno-implicit-fallthrough
|
||||
|
||||
libnetdata/libjudy/src/JudyL/libjudy_a-JudyLPrev.$(OBJEXT) : CFLAGS += -DJUDYPREV
|
||||
libnetdata/libjudy/src/JudyL/libjudy_a-JudyLPrevEmpty.$(OBJEXT) : CFLAGS += -DJUDYPREV
|
||||
libnetdata/libjudy/src/JudyL/libjudy_a-JudyLNext.$(OBJEXT) : CFLAGS += -DJUDYNEXT
|
||||
libnetdata/libjudy/src/JudyL/libjudy_a-JudyLNextEmpty.$(OBJEXT) : CFLAGS += -DJUDYNEXT
|
||||
libnetdata/libjudy/src/JudyL/libjudy_a-JudyLByCount.$(OBJEXT) : CFLAGS += -DNOSMARTJBB -DNOSMARTJBU -DNOSMARTJLB
|
||||
libnetdata/libjudy/src/JudyL/libjudy_a-j__udyLGet.$(OBJEXT) : CFLAGS += -DJUDYGETINLINE
|
||||
|
||||
noinst_PROGRAMS = judyltablesgen
|
||||
|
||||
judyltablesgen_SOURCES = libnetdata/libjudy/src/JudyL/JudyLTablesGen.c
|
||||
judyltablesgen_CFLAGS = $(LIBJUDY_CFLAGS) -DJUDYL -I$(abs_top_srcdir)/libnetdata/libjudy/src -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyCommon -Wno-sign-compare -Wno-implicit-fallthrough
|
||||
|
||||
judyltablesgen$(EXEEXT) : CFLAGS += -Wno-format -Wno-format-security
|
||||
|
||||
JudyLTables.c: $(abs_top_srcdir)/libnetdata/libjudy/src/JudyL/JudyLTablesGen.c $(builddir)/judyltablesgen$(EXEEXT)
|
||||
$(builddir)/judyltablesgen$(EXEEXT)
|
||||
|
||||
libjudy_a-JudyLTables.$(OBJEXT) : CFLAGS += -I$(abs_top_srcdir)/libnetdata/libjudy/src/JudyL
|
||||
|
||||
RRD_PLUGIN_FILES += \
|
||||
database/engine/rrdengine.c \
|
||||
database/engine/rrdengine.h \
|
||||
|
@ -925,6 +980,11 @@ NETDATA_COMMON_LIBS = \
|
|||
$(OPTIONAL_ATOMIC_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
if ENABLE_DBENGINE
|
||||
NETDATA_COMMON_LIBS += libjudy.a \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
if LINK_STATIC_JSONC
|
||||
NETDATA_COMMON_LIBS += $(abs_top_srcdir)/externaldeps/jsonc/libjson-c.a
|
||||
endif
|
||||
|
|
55
configure.ac
55
configure.ac
|
@ -42,6 +42,7 @@ AC_PROG_CXX
|
|||
AC_PROG_INSTALL
|
||||
PKG_PROG_PKG_CONFIG
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_RANLIB
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# configurable options
|
||||
|
@ -468,45 +469,22 @@ OPTIONAL_JSONC_LIBS="${JSONC_LIBS}"
|
|||
test "${enable_dbengine}" = "yes" -a -z "${LZ4_LIBS}" && \
|
||||
AC_MSG_ERROR([liblz4 required but not found. Try installing 'liblz4-dev' or 'lz4-devel'.])
|
||||
|
||||
AC_C_BIGENDIAN([],
|
||||
[LIBJUDY_CFLAGS="-DJU_LITTLE_ENDIAN"],
|
||||
[AC_MSG_ERROR([Could not find out system endiannnes])])
|
||||
|
||||
AC_ARG_WITH([bundled-libJudy],
|
||||
[AS_HELP_STRING([--with-bundled-libJudy],[Use the bundled version of Judy library (default is system-library)])],
|
||||
[
|
||||
AC_MSG_CHECKING(for libJudy in $withval)
|
||||
if test -f "externaldeps/libJudy/libJudy.a" -a -f "externaldeps/libJudy/Judy.h"; then
|
||||
LIBS_BACKUP="${LIBS}"
|
||||
LIBS="externaldeps/libJudy/libJudy.a"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[#include "externaldeps/libJudy/Judy.h"
|
||||
int main (int argc, char **argv) {
|
||||
Pvoid_t PJLArray = (Pvoid_t) NULL;
|
||||
Word_t * PValue;
|
||||
Word_t Index;
|
||||
JLI(PValue, PJLArray, Index);
|
||||
}]])],
|
||||
[HAVE_libJudy_a="yes"],
|
||||
[HAVE_libJudy_a="no"])
|
||||
LIBS="${LIBS_BACKUP}"
|
||||
JUDY_LIBS="\$(abs_top_srcdir)/externaldeps/libJudy/libJudy.a"
|
||||
JUDY_CFLAGS="-I \$(abs_top_srcdir)/externaldeps/libJudy"
|
||||
AC_MSG_RESULT([$HAVE_libJudy_a])
|
||||
else
|
||||
libjudy_dir=""
|
||||
HAVE_libJudy_a="no"
|
||||
AC_MSG_RESULT([$HAVE_libJudy_a])
|
||||
fi
|
||||
],
|
||||
[HAVE_libJudy_a="no"])
|
||||
|
||||
if test "${HAVE_libJudy_a}" = "no"; then
|
||||
AC_CHECK_LIB(
|
||||
[Judy],
|
||||
[JudyLIns],
|
||||
[JUDY_LIBS="-lJudy"]
|
||||
)
|
||||
AC_CHECK_SIZEOF(void *)
|
||||
if test "$ac_cv_sizeof_void_p" = 8; then
|
||||
AC_MSG_RESULT(Detected 64-bit Build Environment)
|
||||
LIBJUDY_CFLAGS="$LIBJUDY_CFLAGS -DJU_64BIT"
|
||||
else
|
||||
AC_MSG_RESULT(Detected 32-bit Build Environment)
|
||||
LIBJUDY_CFLAGS="$LIBJUDY_CFLAGS -UJU_64BIT"
|
||||
fi
|
||||
|
||||
test "${enable_dbengine}" = "yes" -a -z "${JUDY_LIBS}" && \
|
||||
AC_MSG_ERROR([libJudy required but not found. Try installing 'libjudy-dev' or 'Judy-devel'.])
|
||||
AC_SUBST([LIBJUDY_CFLAGS])
|
||||
|
||||
JUDY_CFLAGS="-I \$(abs_top_srcdir)/libnetdata/libjudy/src"
|
||||
|
||||
test "${enable_https}" = "yes" -a -z "${SSL_LIBS}" && \
|
||||
AC_MSG_ERROR([OpenSSL required for HTTPS but not found. Try installing 'libssl-dev' or 'openssl-devel'.])
|
||||
|
@ -515,13 +493,12 @@ test "${enable_dbengine}" = "yes" -a -z "${SSL_LIBS}" && \
|
|||
AC_MSG_ERROR([OpenSSL required for DBENGINE but not found. Try installing 'libssl-dev' or 'openssl-devel'.])
|
||||
|
||||
AC_MSG_CHECKING([if netdata dbengine should be used])
|
||||
if test "${enable_dbengine}" != "no" -a "${UV_LIBS}" -a "${LZ4_LIBS}" -a "${JUDY_LIBS}" -a "${SSL_LIBS}"; then
|
||||
if test "${enable_dbengine}" != "no" -a "${UV_LIBS}" -a "${LZ4_LIBS}" -a "${SSL_LIBS}"; then
|
||||
enable_dbengine="yes"
|
||||
AC_DEFINE([ENABLE_DBENGINE], [1], [netdata dbengine usability])
|
||||
OPTIONAL_LZ4_CFLAGS="${LZ4_CFLAGS}"
|
||||
OPTIONAL_LZ4_LIBS="${LZ4_LIBS}"
|
||||
OPTIONAL_JUDY_CFLAGS="${JUDY_CFLAGS}"
|
||||
OPTIONAL_JUDY_LIBS="${JUDY_LIBS}"
|
||||
OPTIONAL_SSL_CFLAGS="${SSL_CFLAGS}"
|
||||
OPTIONAL_SSL_LIBS="${SSL_LIBS}"
|
||||
else
|
||||
|
@ -1600,8 +1577,6 @@ AC_SUBST([OPTIONAL_MATH_CFLAGS])
|
|||
AC_SUBST([OPTIONAL_MATH_LIBS])
|
||||
AC_SUBST([OPTIONAL_UV_LIBS])
|
||||
AC_SUBST([OPTIONAL_LZ4_LIBS])
|
||||
AC_SUBST([OPTIONAL_JUDY_CFLAGS])
|
||||
AC_SUBST([OPTIONAL_JUDY_LIBS])
|
||||
AC_SUBST([OPTIONAL_SSL_LIBS])
|
||||
AC_SUBST([OPTIONAL_JSONC_LIBS])
|
||||
AC_SUBST([OPTIONAL_NFACCT_CFLAGS])
|
||||
|
|
|
@ -7,7 +7,6 @@ Build-Depends: debhelper (>= 9.20160709),
|
|||
libelf-dev,
|
||||
libuv1-dev,
|
||||
liblz4-dev,
|
||||
libjudy-dev,
|
||||
libssl-dev,
|
||||
libmnl-dev,
|
||||
libjson-c-dev,
|
||||
|
|
|
@ -8,7 +8,6 @@ Build-Depends: debhelper (>= 9),
|
|||
libelf-dev,
|
||||
libuv1-dev,
|
||||
liblz4-dev,
|
||||
libjudy-dev,
|
||||
libssl-dev,
|
||||
libmnl-dev,
|
||||
libjson-c-dev,
|
||||
|
|
622
libnetdata/libjudy/src/Judy.h
Normal file
622
libnetdata/libjudy/src/Judy.h
Normal file
|
@ -0,0 +1,622 @@
|
|||
#ifndef _JUDY_INCLUDED
|
||||
#define _JUDY_INCLUDED
|
||||
// _________________
|
||||
//
|
||||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.52 $ $Source: /judy/src/Judy.h $
|
||||
//
|
||||
// HEADER FILE FOR EXPORTED FEATURES IN JUDY LIBRARY, libJudy.*
|
||||
//
|
||||
// See the manual entries for details.
|
||||
//
|
||||
// Note: This header file uses old-style comments on #-directive lines and
|
||||
// avoids "()" on macro names in comments for compatibility with older cc -Aa
|
||||
// and some tools on some platforms.
|
||||
|
||||
|
||||
// PLATFORM-SPECIFIC
|
||||
|
||||
#ifdef JU_WIN /* =============================================== */
|
||||
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#else /* ================ ! JU_WIN ============================= */
|
||||
|
||||
// ISO C99: 7.8 Format conversion of integer types <inttypes.h>
|
||||
#include <inttypes.h> /* if this FAILS, try #include <stdint.h> */
|
||||
|
||||
// ISO C99: 7.18 Integer types uint*_t
|
||||
//#include <stdint.h>
|
||||
|
||||
#endif /* ================ ! JU_WIN ============================= */
|
||||
|
||||
// ISO C99 Standard: 7.20 General utilities
|
||||
#include <stdlib.h>
|
||||
|
||||
// ISO C99 Standard: 7.10/5.2.4.2.1 Sizes of integer types
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef __cplusplus /* support use by C++ code */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// DECLARE SOME BASE TYPES IN CASE THEY ARE MISSING:
|
||||
//
|
||||
// These base types include "const" where appropriate, but only where of
|
||||
// interest to the caller. For example, a caller cares that a variable passed
|
||||
// by reference will not be modified, such as, "const void * Pindex", but not
|
||||
// that the called function internally does not modify the pointer itself, such
|
||||
// as, "void * const Pindex".
|
||||
//
|
||||
// Note that its OK to pass a Pvoid_t to a Pcvoid_t; the latter is the same,
|
||||
// only constant. Callers need to do this so they can also pass & Pvoid_t to
|
||||
// PPvoid_t (non-constant).
|
||||
|
||||
#ifndef _PCVOID_T
|
||||
#define _PCVOID_T
|
||||
typedef const void * Pcvoid_t;
|
||||
#endif
|
||||
|
||||
#ifndef _PVOID_T
|
||||
#define _PVOID_T
|
||||
typedef void * Pvoid_t;
|
||||
typedef void ** PPvoid_t;
|
||||
#endif
|
||||
|
||||
#ifndef _WORD_T
|
||||
#define _WORD_T
|
||||
typedef unsigned long Word_t, * PWord_t; // expect 32-bit or 64-bit words.
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// SUPPORT FOR ERROR HANDLING:
|
||||
//
|
||||
// Judy error numbers:
|
||||
//
|
||||
// Note: These are an enum so theres a related typedef, but the numbers are
|
||||
// spelled out so you can map a number back to its name.
|
||||
|
||||
typedef enum // uint8_t -- but C does not support this type of enum.
|
||||
{
|
||||
|
||||
// Note: JU_ERRNO_NONE and JU_ERRNO_FULL are not real errors. They specify
|
||||
// conditions which are otherwise impossible return values from 32-bit
|
||||
// Judy1Count, which has 2^32 + 1 valid returns (0..2^32) plus one error
|
||||
// return. These pseudo-errors support the return values that cannot otherwise
|
||||
// be unambiguously represented in a 32-bit word, and will never occur on a
|
||||
// 64-bit system.
|
||||
|
||||
JU_ERRNO_NONE = 0,
|
||||
JU_ERRNO_FULL = 1,
|
||||
JU_ERRNO_NFMAX = JU_ERRNO_FULL,
|
||||
|
||||
// JU_ERRNO_NOMEM comes from malloc(3C) when Judy cannot obtain needed memory.
|
||||
// The system errno value is also set to ENOMEM. This error can be recoverable
|
||||
// if the calling application frees other memory.
|
||||
//
|
||||
// TBD: Currently there is no guarantee the Judy array has no memory leaks
|
||||
// upon JU_ERRNO_NOMEM.
|
||||
|
||||
JU_ERRNO_NOMEM = 2,
|
||||
|
||||
// Problems with parameters from the calling program:
|
||||
//
|
||||
// JU_ERRNO_NULLPPARRAY means PPArray was null; perhaps PArray was passed where
|
||||
// &PArray was intended. Similarly, JU_ERRNO_NULLPINDEX means PIndex was null;
|
||||
// perhaps &Index was intended. Also, JU_ERRNO_NONNULLPARRAY,
|
||||
// JU_ERRNO_NULLPVALUE, and JU_ERRNO_UNSORTED, all added later (hence with
|
||||
// higher numbers), mean: A non-null array was passed in where a null pointer
|
||||
// was required; PValue was null; and unsorted indexes were detected.
|
||||
|
||||
JU_ERRNO_NULLPPARRAY = 3, // see above.
|
||||
JU_ERRNO_NONNULLPARRAY = 10, // see above.
|
||||
JU_ERRNO_NULLPINDEX = 4, // see above.
|
||||
JU_ERRNO_NULLPVALUE = 11, // see above.
|
||||
JU_ERRNO_NOTJUDY1 = 5, // PArray is not to a Judy1 array.
|
||||
JU_ERRNO_NOTJUDYL = 6, // PArray is not to a JudyL array.
|
||||
JU_ERRNO_NOTJUDYSL = 7, // PArray is not to a JudySL array.
|
||||
JU_ERRNO_UNSORTED = 12, // see above.
|
||||
|
||||
// Errors below this point are not recoverable; further tries to access the
|
||||
// Judy array might result in EFAULT and a core dump:
|
||||
//
|
||||
// JU_ERRNO_OVERRUN occurs when Judy detects, upon reallocation, that a block
|
||||
// of memory in its own freelist was modified since being freed.
|
||||
|
||||
JU_ERRNO_OVERRUN = 8,
|
||||
|
||||
// JU_ERRNO_CORRUPT occurs when Judy detects an impossible value in a Judy data
|
||||
// structure:
|
||||
//
|
||||
// Note: The Judy data structure contains some redundant elements that support
|
||||
// this type of checking.
|
||||
|
||||
JU_ERRNO_CORRUPT = 9
|
||||
|
||||
// Warning: At least some C or C++ compilers do not tolerate a trailing comma
|
||||
// above here. At least we know of one case, in aCC; see JAGad58928.
|
||||
|
||||
} JU_Errno_t;
|
||||
|
||||
|
||||
// Judy errno structure:
|
||||
//
|
||||
// WARNING: For compatibility with possible future changes, the fields of this
|
||||
// struct should not be referenced directly. Instead use the macros supplied
|
||||
// below.
|
||||
|
||||
// This structure should be declared on the stack in a threaded process.
|
||||
|
||||
typedef struct J_UDY_ERROR_STRUCT
|
||||
{
|
||||
JU_Errno_t je_Errno; // one of the enums above.
|
||||
int je_ErrID; // often an internal source line number.
|
||||
Word_t je_reserved[4]; // for future backward compatibility.
|
||||
|
||||
} JError_t, * PJError_t;
|
||||
|
||||
|
||||
// Related macros:
|
||||
//
|
||||
// Fields from error struct:
|
||||
|
||||
#define JU_ERRNO(PJError) ((PJError)->je_Errno)
|
||||
#define JU_ERRID(PJError) ((PJError)->je_ErrID)
|
||||
|
||||
// For checking return values from various Judy functions:
|
||||
//
|
||||
// Note: Define JERR as -1, not as the seemingly more portable (Word_t)
|
||||
// (~0UL), to avoid a compiler "overflow in implicit constant conversion"
|
||||
// warning.
|
||||
|
||||
#define JERR (-1) /* functions returning int or Word_t */
|
||||
#define PJERR ((Pvoid_t) (~0UL)) /* mainly for use here, see below */
|
||||
#define PPJERR ((PPvoid_t) (~0UL)) /* functions that return PPvoid_t */
|
||||
|
||||
// Convenience macro for when detailed error information (PJError_t) is not
|
||||
// desired by the caller; a purposely short name:
|
||||
|
||||
#define PJE0 ((PJError_t) NULL)
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDY FUNCTIONS:
|
||||
//
|
||||
// P_JE is a shorthand for use below:
|
||||
|
||||
#define P_JE PJError_t PJError
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDY1 FUNCTIONS:
|
||||
|
||||
extern int Judy1Test( Pcvoid_t PArray, Word_t Index, P_JE);
|
||||
extern int Judy1Set( PPvoid_t PPArray, Word_t Index, P_JE);
|
||||
extern int Judy1SetArray( PPvoid_t PPArray, Word_t Count,
|
||||
const Word_t * const PIndex,
|
||||
P_JE);
|
||||
extern int Judy1Unset( PPvoid_t PPArray, Word_t Index, P_JE);
|
||||
extern Word_t Judy1Count( Pcvoid_t PArray, Word_t Index1,
|
||||
Word_t Index2, P_JE);
|
||||
extern int Judy1ByCount( Pcvoid_t PArray, Word_t Count,
|
||||
Word_t * PIndex, P_JE);
|
||||
extern Word_t Judy1FreeArray( PPvoid_t PPArray, P_JE);
|
||||
extern Word_t Judy1MemUsed( Pcvoid_t PArray);
|
||||
extern Word_t Judy1MemActive( Pcvoid_t PArray);
|
||||
extern int Judy1First( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int Judy1Next( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int Judy1Last( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int Judy1Prev( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int Judy1FirstEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int Judy1NextEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int Judy1LastEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int Judy1PrevEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
|
||||
extern PPvoid_t JudyLGet( Pcvoid_t PArray, Word_t Index, P_JE);
|
||||
extern PPvoid_t JudyLIns( PPvoid_t PPArray, Word_t Index, P_JE);
|
||||
extern int JudyLInsArray( PPvoid_t PPArray, Word_t Count,
|
||||
const Word_t * const PIndex,
|
||||
const Word_t * const PValue,
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDYL FUNCTIONS:
|
||||
P_JE);
|
||||
extern int JudyLDel( PPvoid_t PPArray, Word_t Index, P_JE);
|
||||
extern Word_t JudyLCount( Pcvoid_t PArray, Word_t Index1,
|
||||
Word_t Index2, P_JE);
|
||||
extern PPvoid_t JudyLByCount( Pcvoid_t PArray, Word_t Count,
|
||||
Word_t * PIndex, P_JE);
|
||||
extern Word_t JudyLFreeArray( PPvoid_t PPArray, P_JE);
|
||||
extern Word_t JudyLMemUsed( Pcvoid_t PArray);
|
||||
extern Word_t JudyLMemActive( Pcvoid_t PArray);
|
||||
extern PPvoid_t JudyLFirst( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern PPvoid_t JudyLNext( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern PPvoid_t JudyLLast( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern PPvoid_t JudyLPrev( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int JudyLFirstEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int JudyLNextEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int JudyLLastEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
extern int JudyLPrevEmpty( Pcvoid_t PArray, Word_t * PIndex, P_JE);
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDYSL FUNCTIONS:
|
||||
|
||||
extern PPvoid_t JudySLGet( Pcvoid_t, const uint8_t * Index, P_JE);
|
||||
extern PPvoid_t JudySLIns( PPvoid_t, const uint8_t * Index, P_JE);
|
||||
extern int JudySLDel( PPvoid_t, const uint8_t * Index, P_JE);
|
||||
extern Word_t JudySLFreeArray( PPvoid_t, P_JE);
|
||||
extern PPvoid_t JudySLFirst( Pcvoid_t, uint8_t * Index, P_JE);
|
||||
extern PPvoid_t JudySLNext( Pcvoid_t, uint8_t * Index, P_JE);
|
||||
extern PPvoid_t JudySLLast( Pcvoid_t, uint8_t * Index, P_JE);
|
||||
extern PPvoid_t JudySLPrev( Pcvoid_t, uint8_t * Index, P_JE);
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDYHSL FUNCTIONS:
|
||||
|
||||
extern PPvoid_t JudyHSGet( Pcvoid_t, void *, Word_t);
|
||||
extern PPvoid_t JudyHSIns( PPvoid_t, void *, Word_t, P_JE);
|
||||
extern int JudyHSDel( PPvoid_t, void *, Word_t, P_JE);
|
||||
extern Word_t JudyHSFreeArray( PPvoid_t, P_JE);
|
||||
|
||||
extern const char *Judy1MallocSizes;
|
||||
extern const char *JudyLMallocSizes;
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDY memory interface to malloc() FUNCTIONS:
|
||||
|
||||
extern Word_t JudyMalloc(Word_t); // words reqd => words allocd.
|
||||
extern Word_t JudyMallocVirtual(Word_t); // words reqd => words allocd.
|
||||
extern void JudyFree(Pvoid_t, Word_t); // free, size in words.
|
||||
extern void JudyFreeVirtual(Pvoid_t, Word_t); // free, size in words.
|
||||
|
||||
#define JLAP_INVALID 0x1 /* flag to mark pointer "not a Judy array" */
|
||||
|
||||
// ****************************************************************************
|
||||
// MACRO EQUIVALENTS FOR JUDY FUNCTIONS:
|
||||
//
|
||||
// The following macros, such as J1T, are shorthands for calling Judy functions
|
||||
// with parameter address-of and detailed error checking included. Since they
|
||||
// are macros, the error checking code is replicated each time the macro is
|
||||
// used, but it runs fast in the normal case of no error.
|
||||
//
|
||||
// If the caller does not like the way the default JUDYERROR macro handles
|
||||
// errors (such as an exit(1) call when out of memory), they may define their
|
||||
// own before the "#include <Judy.h>". A routine such as HandleJudyError
|
||||
// could do checking on specific error numbers and print a different message
|
||||
// dependent on the error. The following is one example:
|
||||
//
|
||||
// Note: the back-slashes are removed because some compilers will not accept
|
||||
// them in comments.
|
||||
//
|
||||
// void HandleJudyError(uint8_t *, int, uint8_t *, int, int);
|
||||
// #define JUDYERROR(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID)
|
||||
// {
|
||||
// HandleJudyError(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID);
|
||||
// }
|
||||
//
|
||||
// The routine HandleJudyError could do checking on specific error numbers and
|
||||
// print a different message dependent on the error.
|
||||
//
|
||||
// The macro receives five parameters that are:
|
||||
//
|
||||
// 1. CallerFile: Source filename where a Judy call returned a serious error.
|
||||
// 2. CallerLine: Line number in that source file.
|
||||
// 3. JudyFunc: Name of Judy function reporting the error.
|
||||
// 4. JudyErrno: One of the JU_ERRNO* values enumerated above.
|
||||
// 5. JudyErrID: The je_ErrID field described above.
|
||||
|
||||
#ifndef JUDYERROR_NOTEST
|
||||
#ifndef JUDYERROR /* supply a default error macro */
|
||||
#include <stdio.h>
|
||||
|
||||
#define JUDYERROR(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID) \
|
||||
{ \
|
||||
(void) fprintf(stderr, "File '%s', line %d: %s(), " \
|
||||
"JU_ERRNO_* == %d, ID == %d\n", \
|
||||
CallerFile, CallerLine, \
|
||||
JudyFunc, JudyErrno, JudyErrID); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#endif /* JUDYERROR */
|
||||
#endif /* JUDYERROR_NOTEST */
|
||||
|
||||
// If the JUDYERROR macro is not desired at all, then the following eliminates
|
||||
// it. However, the return code from each Judy function (that is, the first
|
||||
// parameter of each macro) must be checked by the caller to assure that an
|
||||
// error did not occur.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// #define JUDYERROR_NOTEST 1
|
||||
// #include <Judy.h>
|
||||
//
|
||||
// or use this cc option at compile time:
|
||||
//
|
||||
// cc -DJUDYERROR_NOTEST ...
|
||||
//
|
||||
// Example code:
|
||||
//
|
||||
// J1S(Rc, PArray, Index);
|
||||
// if (Rc == JERR) goto ...error
|
||||
//
|
||||
// or:
|
||||
//
|
||||
// JLI(PValue, PArray, Index);
|
||||
// if (PValue == PJERR) goto ...error
|
||||
|
||||
|
||||
// Internal shorthand macros for writing the J1S, etc. macros:
|
||||
|
||||
#ifdef JUDYERROR_NOTEST /* ============================================ */
|
||||
|
||||
// "Judy Set Error":
|
||||
|
||||
#define J_SE(FuncName,Errno) ((void) 0)
|
||||
|
||||
// Note: In each J_*() case below, the digit is the number of key parameters
|
||||
// to the Judy*() call. Just assign the Func result to the callers Rc value
|
||||
// without a cast because none is required, and this keeps the API simpler.
|
||||
// However, a family of different J_*() macros is needed to support the
|
||||
// different numbers of key parameters (0,1,2) and the Func return type.
|
||||
//
|
||||
// In the names below, "I" = integer result; "P" = pointer result. Note, the
|
||||
// Funcs for J_*P() return PPvoid_t, but cast this to a Pvoid_t for flexible,
|
||||
// error-free assignment, and then compare to PJERR.
|
||||
|
||||
#define J_0I(Rc,PArray,Func,FuncName) \
|
||||
{ (Rc) = Func(PArray, PJE0); }
|
||||
|
||||
#define J_1I(Rc,PArray,Index,Func,FuncName) \
|
||||
{ (Rc) = Func(PArray, Index, PJE0); }
|
||||
|
||||
#define J_1P(PV,PArray,Index,Func,FuncName) \
|
||||
{ (PV) = (Pvoid_t) Func(PArray, Index, PJE0); }
|
||||
|
||||
#define J_2I(Rc,PArray,Index,Arg2,Func,FuncName) \
|
||||
{ (Rc) = Func(PArray, Index, Arg2, PJE0); }
|
||||
|
||||
#define J_2C(Rc,PArray,Index1,Index2,Func,FuncName) \
|
||||
{ (Rc) = Func(PArray, Index1, Index2, PJE0); }
|
||||
|
||||
#define J_2P(PV,PArray,Index,Arg2,Func,FuncName) \
|
||||
{ (PV) = (Pvoid_t) Func(PArray, Index, Arg2, PJE0); }
|
||||
|
||||
// Variations for Judy*Set/InsArray functions:
|
||||
|
||||
#define J_2AI(Rc,PArray,Count,PIndex,Func,FuncName) \
|
||||
{ (Rc) = Func(PArray, Count, PIndex, PJE0); }
|
||||
#define J_3AI(Rc,PArray,Count,PIndex,PValue,Func,FuncName) \
|
||||
{ (Rc) = Func(PArray, Count, PIndex, PValue, PJE0); }
|
||||
|
||||
#else /* ================ ! JUDYERROR_NOTEST ============================= */
|
||||
|
||||
#define J_E(FuncName,PJE) \
|
||||
JUDYERROR(__FILE__, __LINE__, FuncName, JU_ERRNO(PJE), JU_ERRID(PJE))
|
||||
|
||||
#define J_SE(FuncName,Errno) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
JU_ERRNO(&J_Error) = (Errno); \
|
||||
JU_ERRID(&J_Error) = __LINE__; \
|
||||
J_E(FuncName, &J_Error); \
|
||||
}
|
||||
|
||||
// Note: In each J_*() case below, the digit is the number of key parameters
|
||||
// to the Judy*() call. Just assign the Func result to the callers Rc value
|
||||
// without a cast because none is required, and this keeps the API simpler.
|
||||
// However, a family of different J_*() macros is needed to support the
|
||||
// different numbers of key parameters (0,1,2) and the Func return type.
|
||||
//
|
||||
// In the names below, "I" = integer result; "P" = pointer result. Note, the
|
||||
// Funcs for J_*P() return PPvoid_t, but cast this to a Pvoid_t for flexible,
|
||||
// error-free assignment, and then compare to PJERR.
|
||||
|
||||
#define J_0I(Rc,PArray,Func,FuncName) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
if (((Rc) = Func(PArray, &J_Error)) == JERR) \
|
||||
J_E(FuncName, &J_Error); \
|
||||
}
|
||||
|
||||
#define J_1I(Rc,PArray,Index,Func,FuncName) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
if (((Rc) = Func(PArray, Index, &J_Error)) == JERR) \
|
||||
J_E(FuncName, &J_Error); \
|
||||
}
|
||||
|
||||
#define J_1P(Rc,PArray,Index,Func,FuncName) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
if (((Rc) = (Pvoid_t) Func(PArray, Index, &J_Error)) == PJERR) \
|
||||
J_E(FuncName, &J_Error); \
|
||||
}
|
||||
|
||||
#define J_2I(Rc,PArray,Index,Arg2,Func,FuncName) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
if (((Rc) = Func(PArray, Index, Arg2, &J_Error)) == JERR) \
|
||||
J_E(FuncName, &J_Error); \
|
||||
}
|
||||
|
||||
// Variation for Judy*Count functions, which return 0, not JERR, for error (and
|
||||
// also for other non-error cases):
|
||||
//
|
||||
// Note: JU_ERRNO_NFMAX should only apply to 32-bit Judy1, but this header
|
||||
// file lacks the necessary ifdefs to make it go away otherwise, so always
|
||||
// check against it.
|
||||
|
||||
#define J_2C(Rc,PArray,Index1,Index2,Func,FuncName) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
if ((((Rc) = Func(PArray, Index1, Index2, &J_Error)) == 0) \
|
||||
&& (JU_ERRNO(&J_Error) > JU_ERRNO_NFMAX)) \
|
||||
{ \
|
||||
J_E(FuncName, &J_Error); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define J_2P(PV,PArray,Index,Arg2,Func,FuncName) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
if (((PV) = (Pvoid_t) Func(PArray, Index, Arg2, &J_Error)) \
|
||||
== PJERR) J_E(FuncName, &J_Error); \
|
||||
}
|
||||
|
||||
// Variations for Judy*Set/InsArray functions:
|
||||
|
||||
#define J_2AI(Rc,PArray,Count,PIndex,Func,FuncName) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
if (((Rc) = Func(PArray, Count, PIndex, &J_Error)) == JERR) \
|
||||
J_E(FuncName, &J_Error); \
|
||||
}
|
||||
|
||||
#define J_3AI(Rc,PArray,Count,PIndex,PValue,Func,FuncName) \
|
||||
{ \
|
||||
JError_t J_Error; \
|
||||
if (((Rc) = Func(PArray, Count, PIndex, PValue, &J_Error)) \
|
||||
== JERR) J_E(FuncName, &J_Error); \
|
||||
}
|
||||
|
||||
#endif /* ================ ! JUDYERROR_NOTEST ============================= */
|
||||
|
||||
// Some of the macros are special cases that use inlined shortcuts for speed
|
||||
// with root-level leaves:
|
||||
|
||||
// This is a slower version with current processors, but in the future...
|
||||
|
||||
#define J1T(Rc,PArray,Index) \
|
||||
(Rc) = Judy1Test((Pvoid_t)(PArray), Index, PJE0)
|
||||
|
||||
#define J1S( Rc, PArray, Index) \
|
||||
J_1I(Rc, (&(PArray)), Index, Judy1Set, "Judy1Set")
|
||||
#define J1SA(Rc, PArray, Count, PIndex) \
|
||||
J_2AI(Rc,(&(PArray)), Count, PIndex, Judy1SetArray, "Judy1SetArray")
|
||||
#define J1U( Rc, PArray, Index) \
|
||||
J_1I(Rc, (&(PArray)), Index, Judy1Unset, "Judy1Unset")
|
||||
#define J1F( Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), Judy1First, "Judy1First")
|
||||
#define J1N( Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), Judy1Next, "Judy1Next")
|
||||
#define J1L( Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), Judy1Last, "Judy1Last")
|
||||
#define J1P( Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), Judy1Prev, "Judy1Prev")
|
||||
#define J1FE(Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), Judy1FirstEmpty, "Judy1FirstEmpty")
|
||||
#define J1NE(Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), Judy1NextEmpty, "Judy1NextEmpty")
|
||||
#define J1LE(Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), Judy1LastEmpty, "Judy1LastEmpty")
|
||||
#define J1PE(Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), Judy1PrevEmpty, "Judy1PrevEmpty")
|
||||
#define J1C( Rc, PArray, Index1, Index2) \
|
||||
J_2C(Rc, PArray, Index1, Index2, Judy1Count, "Judy1Count")
|
||||
#define J1BC(Rc, PArray, Count, Index) \
|
||||
J_2I(Rc, PArray, Count, &(Index), Judy1ByCount, "Judy1ByCount")
|
||||
#define J1FA(Rc, PArray) \
|
||||
J_0I(Rc, (&(PArray)), Judy1FreeArray, "Judy1FreeArray")
|
||||
#define J1MU(Rc, PArray) \
|
||||
(Rc) = Judy1MemUsed(PArray)
|
||||
|
||||
#define JLG(PV,PArray,Index) \
|
||||
(PV) = (Pvoid_t)JudyLGet((Pvoid_t)PArray, Index, PJE0)
|
||||
|
||||
#define JLI( PV, PArray, Index) \
|
||||
J_1P(PV, (&(PArray)), Index, JudyLIns, "JudyLIns")
|
||||
|
||||
#define JLIA(Rc, PArray, Count, PIndex, PValue) \
|
||||
J_3AI(Rc,(&(PArray)), Count, PIndex, PValue, JudyLInsArray, \
|
||||
"JudyLInsArray")
|
||||
#define JLD( Rc, PArray, Index) \
|
||||
J_1I(Rc, (&(PArray)), Index, JudyLDel, "JudyLDel")
|
||||
|
||||
#define JLF( PV, PArray, Index) \
|
||||
J_1P(PV, PArray, &(Index), JudyLFirst, "JudyLFirst")
|
||||
|
||||
#define JLN( PV, PArray, Index) \
|
||||
J_1P(PV, PArray, &(Index), JudyLNext, "JudyLNext")
|
||||
|
||||
#define JLL( PV, PArray, Index) \
|
||||
J_1P(PV, PArray, &(Index), JudyLLast, "JudyLLast")
|
||||
#define JLP( PV, PArray, Index) \
|
||||
J_1P(PV, PArray, &(Index), JudyLPrev, "JudyLPrev")
|
||||
#define JLFE(Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), JudyLFirstEmpty, "JudyLFirstEmpty")
|
||||
#define JLNE(Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), JudyLNextEmpty, "JudyLNextEmpty")
|
||||
#define JLLE(Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), JudyLLastEmpty, "JudyLLastEmpty")
|
||||
#define JLPE(Rc, PArray, Index) \
|
||||
J_1I(Rc, PArray, &(Index), JudyLPrevEmpty, "JudyLPrevEmpty")
|
||||
#define JLC( Rc, PArray, Index1, Index2) \
|
||||
J_2C(Rc, PArray, Index1, Index2, JudyLCount, "JudyLCount")
|
||||
#define JLBC(PV, PArray, Count, Index) \
|
||||
J_2P(PV, PArray, Count, &(Index), JudyLByCount, "JudyLByCount")
|
||||
#define JLFA(Rc, PArray) \
|
||||
J_0I(Rc, (&(PArray)), JudyLFreeArray, "JudyLFreeArray")
|
||||
#define JLMU(Rc, PArray) \
|
||||
(Rc) = JudyLMemUsed(PArray)
|
||||
|
||||
#define JHSI(PV, PArray, PIndex, Count) \
|
||||
J_2P(PV, (&(PArray)), PIndex, Count, JudyHSIns, "JudyHSIns")
|
||||
#define JHSG(PV, PArray, PIndex, Count) \
|
||||
(PV) = (Pvoid_t) JudyHSGet(PArray, PIndex, Count)
|
||||
#define JHSD(Rc, PArray, PIndex, Count) \
|
||||
J_2I(Rc, (&(PArray)), PIndex, Count, JudyHSDel, "JudyHSDel")
|
||||
#define JHSFA(Rc, PArray) \
|
||||
J_0I(Rc, (&(PArray)), JudyHSFreeArray, "JudyHSFreeArray")
|
||||
|
||||
#define JSLG( PV, PArray, Index) \
|
||||
J_1P( PV, PArray, Index, JudySLGet, "JudySLGet")
|
||||
#define JSLI( PV, PArray, Index) \
|
||||
J_1P( PV, (&(PArray)), Index, JudySLIns, "JudySLIns")
|
||||
#define JSLD( Rc, PArray, Index) \
|
||||
J_1I( Rc, (&(PArray)), Index, JudySLDel, "JudySLDel")
|
||||
#define JSLF( PV, PArray, Index) \
|
||||
J_1P( PV, PArray, Index, JudySLFirst, "JudySLFirst")
|
||||
#define JSLN( PV, PArray, Index) \
|
||||
J_1P( PV, PArray, Index, JudySLNext, "JudySLNext")
|
||||
#define JSLL( PV, PArray, Index) \
|
||||
J_1P( PV, PArray, Index, JudySLLast, "JudySLLast")
|
||||
#define JSLP( PV, PArray, Index) \
|
||||
J_1P( PV, PArray, Index, JudySLPrev, "JudySLPrev")
|
||||
#define JSLFA(Rc, PArray) \
|
||||
J_0I( Rc, (&(PArray)), JudySLFreeArray, "JudySLFreeArray")
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* ! _JUDY_INCLUDED */
|
87
libnetdata/libjudy/src/JudyCommon/JudyMalloc.c
Normal file
87
libnetdata/libjudy/src/JudyCommon/JudyMalloc.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.33 $ $Source: /judy/src/JudyCommon/JudyMalloc.c $
|
||||
// ************************************************************************ //
|
||||
// JUDY - Memory Allocater //
|
||||
// -by- //
|
||||
// Douglas L. Baskins //
|
||||
// Hewlett Packard //
|
||||
// Fort Collins, Co //
|
||||
// (970) 229-2027 //
|
||||
// //
|
||||
// ************************************************************************ //
|
||||
|
||||
// JUDY INCLUDE FILES
|
||||
#include "Judy.h"
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y M A L L O C
|
||||
//
|
||||
// Allocate RAM. This is the single location in Judy code that calls
|
||||
// malloc(3C). Note: JPM accounting occurs at a higher level.
|
||||
|
||||
Word_t JudyMalloc(
|
||||
Word_t Words)
|
||||
{
|
||||
Word_t Addr;
|
||||
|
||||
Addr = (Word_t) malloc(Words * sizeof(Word_t));
|
||||
return(Addr);
|
||||
|
||||
} // JudyMalloc()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y F R E E
|
||||
|
||||
void JudyFree(
|
||||
void * PWord,
|
||||
Word_t Words)
|
||||
{
|
||||
(void) Words;
|
||||
free(PWord);
|
||||
|
||||
} // JudyFree()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y M A L L O C
|
||||
//
|
||||
// Higher-level "wrapper" for allocating objects that need not be in RAM,
|
||||
// although at this time they are in fact only in RAM. Later we hope that some
|
||||
// entire subtrees (at a JPM or branch) can be "virtual", so their allocations
|
||||
// and frees should go through this level.
|
||||
|
||||
Word_t JudyMallocVirtual(
|
||||
Word_t Words)
|
||||
{
|
||||
return(JudyMalloc(Words));
|
||||
|
||||
} // JudyMallocVirtual()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y F R E E
|
||||
|
||||
void JudyFreeVirtual(
|
||||
void * PWord,
|
||||
Word_t Words)
|
||||
{
|
||||
JudyFree(PWord, Words);
|
||||
|
||||
} // JudyFreeVirtual()
|
1613
libnetdata/libjudy/src/JudyCommon/JudyPrivate.h
Normal file
1613
libnetdata/libjudy/src/JudyCommon/JudyPrivate.h
Normal file
File diff suppressed because it is too large
Load diff
485
libnetdata/libjudy/src/JudyCommon/JudyPrivate1L.h
Normal file
485
libnetdata/libjudy/src/JudyCommon/JudyPrivate1L.h
Normal file
|
@ -0,0 +1,485 @@
|
|||
#ifndef _JUDYPRIVATE1L_INCLUDED
|
||||
#define _JUDYPRIVATE1L_INCLUDED
|
||||
// _________________
|
||||
//
|
||||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.31 $ $Source: /judy/src/JudyCommon/JudyPrivate1L.h $
|
||||
|
||||
// ****************************************************************************
|
||||
// Declare common cJU_* names for JP Types that occur in both Judy1 and JudyL,
|
||||
// for use by code that ifdefs JUDY1 and JUDYL. Only JP Types common to both
|
||||
// Judy1 and JudyL are #defined here with equivalent cJU_* names. JP Types
|
||||
// unique to only Judy1 or JudyL are listed in comments, so the type lists
|
||||
// match the Judy1.h and JudyL.h files.
|
||||
//
|
||||
// This file also defines cJU_* for other JP-related constants and functions
|
||||
// that some shared JUDY1/JUDYL code finds handy.
|
||||
//
|
||||
// At least in principle this file should be included AFTER Judy1.h or JudyL.h.
|
||||
//
|
||||
// WARNING: This file must be kept consistent with the enums in Judy1.h and
|
||||
// JudyL.h.
|
||||
//
|
||||
// TBD: You might think, why not define common cJU_* enums in, say,
|
||||
// JudyPrivate.h, and then inherit them into superset enums in Judy1.h and
|
||||
// JudyL.h? The problem is that the enum lists for each class (cJ1_* and
|
||||
// cJL_*) must be numerically "packed" into the correct order, for two reasons:
|
||||
// (1) allow the compiler to generate "tight" switch statements with no wasted
|
||||
// slots (although this is not very big), and (2) allow calculations using the
|
||||
// enum values, although this is also not an issue if the calculations are only
|
||||
// within each cJ*_JPIMMED_*_* class and the members are packed within the
|
||||
// class.
|
||||
|
||||
#ifdef JUDY1
|
||||
|
||||
#define cJU_JRPNULL cJ1_JRPNULL
|
||||
#define cJU_JPNULL1 cJ1_JPNULL1
|
||||
#define cJU_JPNULL2 cJ1_JPNULL2
|
||||
#define cJU_JPNULL3 cJ1_JPNULL3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPNULL4 cJ1_JPNULL4
|
||||
#define cJU_JPNULL5 cJ1_JPNULL5
|
||||
#define cJU_JPNULL6 cJ1_JPNULL6
|
||||
#define cJU_JPNULL7 cJ1_JPNULL7
|
||||
#endif
|
||||
#define cJU_JPNULLMAX cJ1_JPNULLMAX
|
||||
#define cJU_JPBRANCH_L2 cJ1_JPBRANCH_L2
|
||||
#define cJU_JPBRANCH_L3 cJ1_JPBRANCH_L3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPBRANCH_L4 cJ1_JPBRANCH_L4
|
||||
#define cJU_JPBRANCH_L5 cJ1_JPBRANCH_L5
|
||||
#define cJU_JPBRANCH_L6 cJ1_JPBRANCH_L6
|
||||
#define cJU_JPBRANCH_L7 cJ1_JPBRANCH_L7
|
||||
#endif
|
||||
#define cJU_JPBRANCH_L cJ1_JPBRANCH_L
|
||||
#define j__U_BranchBJPPopToWords j__1_BranchBJPPopToWords
|
||||
#define cJU_JPBRANCH_B2 cJ1_JPBRANCH_B2
|
||||
#define cJU_JPBRANCH_B3 cJ1_JPBRANCH_B3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPBRANCH_B4 cJ1_JPBRANCH_B4
|
||||
#define cJU_JPBRANCH_B5 cJ1_JPBRANCH_B5
|
||||
#define cJU_JPBRANCH_B6 cJ1_JPBRANCH_B6
|
||||
#define cJU_JPBRANCH_B7 cJ1_JPBRANCH_B7
|
||||
#endif
|
||||
#define cJU_JPBRANCH_B cJ1_JPBRANCH_B
|
||||
#define cJU_JPBRANCH_U2 cJ1_JPBRANCH_U2
|
||||
#define cJU_JPBRANCH_U3 cJ1_JPBRANCH_U3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPBRANCH_U4 cJ1_JPBRANCH_U4
|
||||
#define cJU_JPBRANCH_U5 cJ1_JPBRANCH_U5
|
||||
#define cJU_JPBRANCH_U6 cJ1_JPBRANCH_U6
|
||||
#define cJU_JPBRANCH_U7 cJ1_JPBRANCH_U7
|
||||
#endif
|
||||
#define cJU_JPBRANCH_U cJ1_JPBRANCH_U
|
||||
#ifndef JU_64BIT
|
||||
#define cJU_JPLEAF1 cJ1_JPLEAF1
|
||||
#endif
|
||||
#define cJU_JPLEAF2 cJ1_JPLEAF2
|
||||
#define cJU_JPLEAF3 cJ1_JPLEAF3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPLEAF4 cJ1_JPLEAF4
|
||||
#define cJU_JPLEAF5 cJ1_JPLEAF5
|
||||
#define cJU_JPLEAF6 cJ1_JPLEAF6
|
||||
#define cJU_JPLEAF7 cJ1_JPLEAF7
|
||||
#endif
|
||||
#define cJU_JPLEAF_B1 cJ1_JPLEAF_B1
|
||||
// cJ1_JPFULLPOPU1
|
||||
#define cJU_JPIMMED_1_01 cJ1_JPIMMED_1_01
|
||||
#define cJU_JPIMMED_2_01 cJ1_JPIMMED_2_01
|
||||
#define cJU_JPIMMED_3_01 cJ1_JPIMMED_3_01
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPIMMED_4_01 cJ1_JPIMMED_4_01
|
||||
#define cJU_JPIMMED_5_01 cJ1_JPIMMED_5_01
|
||||
#define cJU_JPIMMED_6_01 cJ1_JPIMMED_6_01
|
||||
#define cJU_JPIMMED_7_01 cJ1_JPIMMED_7_01
|
||||
#endif
|
||||
#define cJU_JPIMMED_1_02 cJ1_JPIMMED_1_02
|
||||
#define cJU_JPIMMED_1_03 cJ1_JPIMMED_1_03
|
||||
#define cJU_JPIMMED_1_04 cJ1_JPIMMED_1_04
|
||||
#define cJU_JPIMMED_1_05 cJ1_JPIMMED_1_05
|
||||
#define cJU_JPIMMED_1_06 cJ1_JPIMMED_1_06
|
||||
#define cJU_JPIMMED_1_07 cJ1_JPIMMED_1_07
|
||||
#ifdef JU_64BIT
|
||||
// cJ1_JPIMMED_1_08
|
||||
// cJ1_JPIMMED_1_09
|
||||
// cJ1_JPIMMED_1_10
|
||||
// cJ1_JPIMMED_1_11
|
||||
// cJ1_JPIMMED_1_12
|
||||
// cJ1_JPIMMED_1_13
|
||||
// cJ1_JPIMMED_1_14
|
||||
// cJ1_JPIMMED_1_15
|
||||
#endif
|
||||
#define cJU_JPIMMED_2_02 cJ1_JPIMMED_2_02
|
||||
#define cJU_JPIMMED_2_03 cJ1_JPIMMED_2_03
|
||||
#ifdef JU_64BIT
|
||||
// cJ1_JPIMMED_2_04
|
||||
// cJ1_JPIMMED_2_05
|
||||
// cJ1_JPIMMED_2_06
|
||||
// cJ1_JPIMMED_2_07
|
||||
#endif
|
||||
#define cJU_JPIMMED_3_02 cJ1_JPIMMED_3_02
|
||||
#ifdef JU_64BIT
|
||||
// cJ1_JPIMMED_3_03
|
||||
// cJ1_JPIMMED_3_04
|
||||
// cJ1_JPIMMED_3_05
|
||||
// cJ1_JPIMMED_4_02
|
||||
// cJ1_JPIMMED_4_03
|
||||
// cJ1_JPIMMED_5_02
|
||||
// cJ1_JPIMMED_5_03
|
||||
// cJ1_JPIMMED_6_02
|
||||
// cJ1_JPIMMED_7_02
|
||||
#endif
|
||||
#define cJU_JPIMMED_CAP cJ1_JPIMMED_CAP
|
||||
|
||||
#else // JUDYL ****************************************************************
|
||||
|
||||
#define cJU_JRPNULL cJL_JRPNULL
|
||||
#define cJU_JPNULL1 cJL_JPNULL1
|
||||
#define cJU_JPNULL2 cJL_JPNULL2
|
||||
#define cJU_JPNULL3 cJL_JPNULL3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPNULL4 cJL_JPNULL4
|
||||
#define cJU_JPNULL5 cJL_JPNULL5
|
||||
#define cJU_JPNULL6 cJL_JPNULL6
|
||||
#define cJU_JPNULL7 cJL_JPNULL7
|
||||
#endif
|
||||
#define cJU_JPNULLMAX cJL_JPNULLMAX
|
||||
#define cJU_JPBRANCH_L2 cJL_JPBRANCH_L2
|
||||
#define cJU_JPBRANCH_L3 cJL_JPBRANCH_L3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPBRANCH_L4 cJL_JPBRANCH_L4
|
||||
#define cJU_JPBRANCH_L5 cJL_JPBRANCH_L5
|
||||
#define cJU_JPBRANCH_L6 cJL_JPBRANCH_L6
|
||||
#define cJU_JPBRANCH_L7 cJL_JPBRANCH_L7
|
||||
#endif
|
||||
#define cJU_JPBRANCH_L cJL_JPBRANCH_L
|
||||
#define j__U_BranchBJPPopToWords j__L_BranchBJPPopToWords
|
||||
#define cJU_JPBRANCH_B2 cJL_JPBRANCH_B2
|
||||
#define cJU_JPBRANCH_B3 cJL_JPBRANCH_B3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPBRANCH_B4 cJL_JPBRANCH_B4
|
||||
#define cJU_JPBRANCH_B5 cJL_JPBRANCH_B5
|
||||
#define cJU_JPBRANCH_B6 cJL_JPBRANCH_B6
|
||||
#define cJU_JPBRANCH_B7 cJL_JPBRANCH_B7
|
||||
#endif
|
||||
#define cJU_JPBRANCH_B cJL_JPBRANCH_B
|
||||
#define cJU_JPBRANCH_U2 cJL_JPBRANCH_U2
|
||||
#define cJU_JPBRANCH_U3 cJL_JPBRANCH_U3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPBRANCH_U4 cJL_JPBRANCH_U4
|
||||
#define cJU_JPBRANCH_U5 cJL_JPBRANCH_U5
|
||||
#define cJU_JPBRANCH_U6 cJL_JPBRANCH_U6
|
||||
#define cJU_JPBRANCH_U7 cJL_JPBRANCH_U7
|
||||
#endif
|
||||
#define cJU_JPBRANCH_U cJL_JPBRANCH_U
|
||||
#define cJU_JPLEAF1 cJL_JPLEAF1
|
||||
#define cJU_JPLEAF2 cJL_JPLEAF2
|
||||
#define cJU_JPLEAF3 cJL_JPLEAF3
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPLEAF4 cJL_JPLEAF4
|
||||
#define cJU_JPLEAF5 cJL_JPLEAF5
|
||||
#define cJU_JPLEAF6 cJL_JPLEAF6
|
||||
#define cJU_JPLEAF7 cJL_JPLEAF7
|
||||
#endif
|
||||
#define cJU_JPLEAF_B1 cJL_JPLEAF_B1
|
||||
#define cJU_JPIMMED_1_01 cJL_JPIMMED_1_01
|
||||
#define cJU_JPIMMED_2_01 cJL_JPIMMED_2_01
|
||||
#define cJU_JPIMMED_3_01 cJL_JPIMMED_3_01
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPIMMED_4_01 cJL_JPIMMED_4_01
|
||||
#define cJU_JPIMMED_5_01 cJL_JPIMMED_5_01
|
||||
#define cJU_JPIMMED_6_01 cJL_JPIMMED_6_01
|
||||
#define cJU_JPIMMED_7_01 cJL_JPIMMED_7_01
|
||||
#endif
|
||||
#define cJU_JPIMMED_1_02 cJL_JPIMMED_1_02
|
||||
#define cJU_JPIMMED_1_03 cJL_JPIMMED_1_03
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_JPIMMED_1_04 cJL_JPIMMED_1_04
|
||||
#define cJU_JPIMMED_1_05 cJL_JPIMMED_1_05
|
||||
#define cJU_JPIMMED_1_06 cJL_JPIMMED_1_06
|
||||
#define cJU_JPIMMED_1_07 cJL_JPIMMED_1_07
|
||||
#define cJU_JPIMMED_2_02 cJL_JPIMMED_2_02
|
||||
#define cJU_JPIMMED_2_03 cJL_JPIMMED_2_03
|
||||
#define cJU_JPIMMED_3_02 cJL_JPIMMED_3_02
|
||||
#endif
|
||||
#define cJU_JPIMMED_CAP cJL_JPIMMED_CAP
|
||||
|
||||
#endif // JUDYL
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// cJU*_ other than JP types:
|
||||
|
||||
#ifdef JUDY1
|
||||
|
||||
#define cJU_LEAFW_MAXPOP1 cJ1_LEAFW_MAXPOP1
|
||||
#ifndef JU_64BIT
|
||||
#define cJU_LEAF1_MAXPOP1 cJ1_LEAF1_MAXPOP1
|
||||
#endif
|
||||
#define cJU_LEAF2_MAXPOP1 cJ1_LEAF2_MAXPOP1
|
||||
#define cJU_LEAF3_MAXPOP1 cJ1_LEAF3_MAXPOP1
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_LEAF4_MAXPOP1 cJ1_LEAF4_MAXPOP1
|
||||
#define cJU_LEAF5_MAXPOP1 cJ1_LEAF5_MAXPOP1
|
||||
#define cJU_LEAF6_MAXPOP1 cJ1_LEAF6_MAXPOP1
|
||||
#define cJU_LEAF7_MAXPOP1 cJ1_LEAF7_MAXPOP1
|
||||
#endif
|
||||
#define cJU_IMMED1_MAXPOP1 cJ1_IMMED1_MAXPOP1
|
||||
#define cJU_IMMED2_MAXPOP1 cJ1_IMMED2_MAXPOP1
|
||||
#define cJU_IMMED3_MAXPOP1 cJ1_IMMED3_MAXPOP1
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_IMMED4_MAXPOP1 cJ1_IMMED4_MAXPOP1
|
||||
#define cJU_IMMED5_MAXPOP1 cJ1_IMMED5_MAXPOP1
|
||||
#define cJU_IMMED6_MAXPOP1 cJ1_IMMED6_MAXPOP1
|
||||
#define cJU_IMMED7_MAXPOP1 cJ1_IMMED7_MAXPOP1
|
||||
#endif
|
||||
|
||||
#define JU_LEAF1POPTOWORDS(Pop1) J1_LEAF1POPTOWORDS(Pop1)
|
||||
#define JU_LEAF2POPTOWORDS(Pop1) J1_LEAF2POPTOWORDS(Pop1)
|
||||
#define JU_LEAF3POPTOWORDS(Pop1) J1_LEAF3POPTOWORDS(Pop1)
|
||||
#ifdef JU_64BIT
|
||||
#define JU_LEAF4POPTOWORDS(Pop1) J1_LEAF4POPTOWORDS(Pop1)
|
||||
#define JU_LEAF5POPTOWORDS(Pop1) J1_LEAF5POPTOWORDS(Pop1)
|
||||
#define JU_LEAF6POPTOWORDS(Pop1) J1_LEAF6POPTOWORDS(Pop1)
|
||||
#define JU_LEAF7POPTOWORDS(Pop1) J1_LEAF7POPTOWORDS(Pop1)
|
||||
#endif
|
||||
#define JU_LEAFWPOPTOWORDS(Pop1) J1_LEAFWPOPTOWORDS(Pop1)
|
||||
|
||||
#ifndef JU_64BIT
|
||||
#define JU_LEAF1GROWINPLACE(Pop1) J1_LEAF1GROWINPLACE(Pop1)
|
||||
#endif
|
||||
#define JU_LEAF2GROWINPLACE(Pop1) J1_LEAF2GROWINPLACE(Pop1)
|
||||
#define JU_LEAF3GROWINPLACE(Pop1) J1_LEAF3GROWINPLACE(Pop1)
|
||||
#ifdef JU_64BIT
|
||||
#define JU_LEAF4GROWINPLACE(Pop1) J1_LEAF4GROWINPLACE(Pop1)
|
||||
#define JU_LEAF5GROWINPLACE(Pop1) J1_LEAF5GROWINPLACE(Pop1)
|
||||
#define JU_LEAF6GROWINPLACE(Pop1) J1_LEAF6GROWINPLACE(Pop1)
|
||||
#define JU_LEAF7GROWINPLACE(Pop1) J1_LEAF7GROWINPLACE(Pop1)
|
||||
#endif
|
||||
#define JU_LEAFWGROWINPLACE(Pop1) J1_LEAFWGROWINPLACE(Pop1)
|
||||
|
||||
#define j__udyCreateBranchL j__udy1CreateBranchL
|
||||
#define j__udyCreateBranchB j__udy1CreateBranchB
|
||||
#define j__udyCreateBranchU j__udy1CreateBranchU
|
||||
#define j__udyCascade1 j__udy1Cascade1
|
||||
#define j__udyCascade2 j__udy1Cascade2
|
||||
#define j__udyCascade3 j__udy1Cascade3
|
||||
#ifdef JU_64BIT
|
||||
#define j__udyCascade4 j__udy1Cascade4
|
||||
#define j__udyCascade5 j__udy1Cascade5
|
||||
#define j__udyCascade6 j__udy1Cascade6
|
||||
#define j__udyCascade7 j__udy1Cascade7
|
||||
#endif
|
||||
#define j__udyCascadeL j__udy1CascadeL
|
||||
#define j__udyInsertBranch j__udy1InsertBranch
|
||||
|
||||
#define j__udyBranchBToBranchL j__udy1BranchBToBranchL
|
||||
#ifndef JU_64BIT
|
||||
#define j__udyLeafB1ToLeaf1 j__udy1LeafB1ToLeaf1
|
||||
#endif
|
||||
#define j__udyLeaf1ToLeaf2 j__udy1Leaf1ToLeaf2
|
||||
#define j__udyLeaf2ToLeaf3 j__udy1Leaf2ToLeaf3
|
||||
#ifndef JU_64BIT
|
||||
#define j__udyLeaf3ToLeafW j__udy1Leaf3ToLeafW
|
||||
#else
|
||||
#define j__udyLeaf3ToLeaf4 j__udy1Leaf3ToLeaf4
|
||||
#define j__udyLeaf4ToLeaf5 j__udy1Leaf4ToLeaf5
|
||||
#define j__udyLeaf5ToLeaf6 j__udy1Leaf5ToLeaf6
|
||||
#define j__udyLeaf6ToLeaf7 j__udy1Leaf6ToLeaf7
|
||||
#define j__udyLeaf7ToLeafW j__udy1Leaf7ToLeafW
|
||||
#endif
|
||||
|
||||
#define jpm_t j1pm_t
|
||||
#define Pjpm_t Pj1pm_t
|
||||
|
||||
#define jlb_t j1lb_t
|
||||
#define Pjlb_t Pj1lb_t
|
||||
|
||||
#define JU_JLB_BITMAP J1_JLB_BITMAP
|
||||
|
||||
#define j__udyAllocJPM j__udy1AllocJ1PM
|
||||
#define j__udyAllocJBL j__udy1AllocJBL
|
||||
#define j__udyAllocJBB j__udy1AllocJBB
|
||||
#define j__udyAllocJBBJP j__udy1AllocJBBJP
|
||||
#define j__udyAllocJBU j__udy1AllocJBU
|
||||
#ifndef JU_64BIT
|
||||
#define j__udyAllocJLL1 j__udy1AllocJLL1
|
||||
#endif
|
||||
#define j__udyAllocJLL2 j__udy1AllocJLL2
|
||||
#define j__udyAllocJLL3 j__udy1AllocJLL3
|
||||
#ifdef JU_64BIT
|
||||
#define j__udyAllocJLL4 j__udy1AllocJLL4
|
||||
#define j__udyAllocJLL5 j__udy1AllocJLL5
|
||||
#define j__udyAllocJLL6 j__udy1AllocJLL6
|
||||
#define j__udyAllocJLL7 j__udy1AllocJLL7
|
||||
#endif
|
||||
#define j__udyAllocJLW j__udy1AllocJLW
|
||||
#define j__udyAllocJLB1 j__udy1AllocJLB1
|
||||
#define j__udyFreeJPM j__udy1FreeJ1PM
|
||||
#define j__udyFreeJBL j__udy1FreeJBL
|
||||
#define j__udyFreeJBB j__udy1FreeJBB
|
||||
#define j__udyFreeJBBJP j__udy1FreeJBBJP
|
||||
#define j__udyFreeJBU j__udy1FreeJBU
|
||||
#ifndef JU_64BIT
|
||||
#define j__udyFreeJLL1 j__udy1FreeJLL1
|
||||
#endif
|
||||
#define j__udyFreeJLL2 j__udy1FreeJLL2
|
||||
#define j__udyFreeJLL3 j__udy1FreeJLL3
|
||||
#ifdef JU_64BIT
|
||||
#define j__udyFreeJLL4 j__udy1FreeJLL4
|
||||
#define j__udyFreeJLL5 j__udy1FreeJLL5
|
||||
#define j__udyFreeJLL6 j__udy1FreeJLL6
|
||||
#define j__udyFreeJLL7 j__udy1FreeJLL7
|
||||
#endif
|
||||
#define j__udyFreeJLW j__udy1FreeJLW
|
||||
#define j__udyFreeJLB1 j__udy1FreeJLB1
|
||||
#define j__udyFreeSM j__udy1FreeSM
|
||||
|
||||
#define j__uMaxWords j__u1MaxWords
|
||||
|
||||
#ifdef DEBUG
|
||||
#define JudyCheckPop Judy1CheckPop
|
||||
#endif
|
||||
|
||||
#else // JUDYL ****************************************************************
|
||||
|
||||
#define cJU_LEAFW_MAXPOP1 cJL_LEAFW_MAXPOP1
|
||||
#define cJU_LEAF1_MAXPOP1 cJL_LEAF1_MAXPOP1
|
||||
#define cJU_LEAF2_MAXPOP1 cJL_LEAF2_MAXPOP1
|
||||
#define cJU_LEAF3_MAXPOP1 cJL_LEAF3_MAXPOP1
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_LEAF4_MAXPOP1 cJL_LEAF4_MAXPOP1
|
||||
#define cJU_LEAF5_MAXPOP1 cJL_LEAF5_MAXPOP1
|
||||
#define cJU_LEAF6_MAXPOP1 cJL_LEAF6_MAXPOP1
|
||||
#define cJU_LEAF7_MAXPOP1 cJL_LEAF7_MAXPOP1
|
||||
#endif
|
||||
#define cJU_IMMED1_MAXPOP1 cJL_IMMED1_MAXPOP1
|
||||
#define cJU_IMMED2_MAXPOP1 cJL_IMMED2_MAXPOP1
|
||||
#define cJU_IMMED3_MAXPOP1 cJL_IMMED3_MAXPOP1
|
||||
#ifdef JU_64BIT
|
||||
#define cJU_IMMED4_MAXPOP1 cJL_IMMED4_MAXPOP1
|
||||
#define cJU_IMMED5_MAXPOP1 cJL_IMMED5_MAXPOP1
|
||||
#define cJU_IMMED6_MAXPOP1 cJL_IMMED6_MAXPOP1
|
||||
#define cJU_IMMED7_MAXPOP1 cJL_IMMED7_MAXPOP1
|
||||
#endif
|
||||
|
||||
#define JU_LEAF1POPTOWORDS(Pop1) JL_LEAF1POPTOWORDS(Pop1)
|
||||
#define JU_LEAF2POPTOWORDS(Pop1) JL_LEAF2POPTOWORDS(Pop1)
|
||||
#define JU_LEAF3POPTOWORDS(Pop1) JL_LEAF3POPTOWORDS(Pop1)
|
||||
#ifdef JU_64BIT
|
||||
#define JU_LEAF4POPTOWORDS(Pop1) JL_LEAF4POPTOWORDS(Pop1)
|
||||
#define JU_LEAF5POPTOWORDS(Pop1) JL_LEAF5POPTOWORDS(Pop1)
|
||||
#define JU_LEAF6POPTOWORDS(Pop1) JL_LEAF6POPTOWORDS(Pop1)
|
||||
#define JU_LEAF7POPTOWORDS(Pop1) JL_LEAF7POPTOWORDS(Pop1)
|
||||
#endif
|
||||
#define JU_LEAFWPOPTOWORDS(Pop1) JL_LEAFWPOPTOWORDS(Pop1)
|
||||
|
||||
#define JU_LEAF1GROWINPLACE(Pop1) JL_LEAF1GROWINPLACE(Pop1)
|
||||
#define JU_LEAF2GROWINPLACE(Pop1) JL_LEAF2GROWINPLACE(Pop1)
|
||||
#define JU_LEAF3GROWINPLACE(Pop1) JL_LEAF3GROWINPLACE(Pop1)
|
||||
#ifdef JU_64BIT
|
||||
#define JU_LEAF4GROWINPLACE(Pop1) JL_LEAF4GROWINPLACE(Pop1)
|
||||
#define JU_LEAF5GROWINPLACE(Pop1) JL_LEAF5GROWINPLACE(Pop1)
|
||||
#define JU_LEAF6GROWINPLACE(Pop1) JL_LEAF6GROWINPLACE(Pop1)
|
||||
#define JU_LEAF7GROWINPLACE(Pop1) JL_LEAF7GROWINPLACE(Pop1)
|
||||
#endif
|
||||
#define JU_LEAFWGROWINPLACE(Pop1) JL_LEAFWGROWINPLACE(Pop1)
|
||||
|
||||
#define j__udyCreateBranchL j__udyLCreateBranchL
|
||||
#define j__udyCreateBranchB j__udyLCreateBranchB
|
||||
#define j__udyCreateBranchU j__udyLCreateBranchU
|
||||
#define j__udyCascade1 j__udyLCascade1
|
||||
#define j__udyCascade2 j__udyLCascade2
|
||||
#define j__udyCascade3 j__udyLCascade3
|
||||
#ifdef JU_64BIT
|
||||
#define j__udyCascade4 j__udyLCascade4
|
||||
#define j__udyCascade5 j__udyLCascade5
|
||||
#define j__udyCascade6 j__udyLCascade6
|
||||
#define j__udyCascade7 j__udyLCascade7
|
||||
#endif
|
||||
#define j__udyCascadeL j__udyLCascadeL
|
||||
#define j__udyInsertBranch j__udyLInsertBranch
|
||||
|
||||
#define j__udyBranchBToBranchL j__udyLBranchBToBranchL
|
||||
#define j__udyLeafB1ToLeaf1 j__udyLLeafB1ToLeaf1
|
||||
#define j__udyLeaf1ToLeaf2 j__udyLLeaf1ToLeaf2
|
||||
#define j__udyLeaf2ToLeaf3 j__udyLLeaf2ToLeaf3
|
||||
#ifndef JU_64BIT
|
||||
#define j__udyLeaf3ToLeafW j__udyLLeaf3ToLeafW
|
||||
#else
|
||||
#define j__udyLeaf3ToLeaf4 j__udyLLeaf3ToLeaf4
|
||||
#define j__udyLeaf4ToLeaf5 j__udyLLeaf4ToLeaf5
|
||||
#define j__udyLeaf5ToLeaf6 j__udyLLeaf5ToLeaf6
|
||||
#define j__udyLeaf6ToLeaf7 j__udyLLeaf6ToLeaf7
|
||||
#define j__udyLeaf7ToLeafW j__udyLLeaf7ToLeafW
|
||||
#endif
|
||||
|
||||
#define jpm_t jLpm_t
|
||||
#define Pjpm_t PjLpm_t
|
||||
|
||||
#define jlb_t jLlb_t
|
||||
#define Pjlb_t PjLlb_t
|
||||
|
||||
#define JU_JLB_BITMAP JL_JLB_BITMAP
|
||||
|
||||
#define j__udyAllocJPM j__udyLAllocJLPM
|
||||
#define j__udyAllocJBL j__udyLAllocJBL
|
||||
#define j__udyAllocJBB j__udyLAllocJBB
|
||||
#define j__udyAllocJBBJP j__udyLAllocJBBJP
|
||||
#define j__udyAllocJBU j__udyLAllocJBU
|
||||
#define j__udyAllocJLL1 j__udyLAllocJLL1
|
||||
#define j__udyAllocJLL2 j__udyLAllocJLL2
|
||||
#define j__udyAllocJLL3 j__udyLAllocJLL3
|
||||
#ifdef JU_64BIT
|
||||
#define j__udyAllocJLL4 j__udyLAllocJLL4
|
||||
#define j__udyAllocJLL5 j__udyLAllocJLL5
|
||||
#define j__udyAllocJLL6 j__udyLAllocJLL6
|
||||
#define j__udyAllocJLL7 j__udyLAllocJLL7
|
||||
#endif
|
||||
#define j__udyAllocJLW j__udyLAllocJLW
|
||||
#define j__udyAllocJLB1 j__udyLAllocJLB1
|
||||
// j__udyLAllocJV
|
||||
#define j__udyFreeJPM j__udyLFreeJLPM
|
||||
#define j__udyFreeJBL j__udyLFreeJBL
|
||||
#define j__udyFreeJBB j__udyLFreeJBB
|
||||
#define j__udyFreeJBBJP j__udyLFreeJBBJP
|
||||
#define j__udyFreeJBU j__udyLFreeJBU
|
||||
#define j__udyFreeJLL1 j__udyLFreeJLL1
|
||||
#define j__udyFreeJLL2 j__udyLFreeJLL2
|
||||
#define j__udyFreeJLL3 j__udyLFreeJLL3
|
||||
#ifdef JU_64BIT
|
||||
#define j__udyFreeJLL4 j__udyLFreeJLL4
|
||||
#define j__udyFreeJLL5 j__udyLFreeJLL5
|
||||
#define j__udyFreeJLL6 j__udyLFreeJLL6
|
||||
#define j__udyFreeJLL7 j__udyLFreeJLL7
|
||||
#endif
|
||||
#define j__udyFreeJLW j__udyLFreeJLW
|
||||
#define j__udyFreeJLB1 j__udyLFreeJLB1
|
||||
#define j__udyFreeSM j__udyLFreeSM
|
||||
// j__udyLFreeJV
|
||||
|
||||
#define j__uMaxWords j__uLMaxWords
|
||||
|
||||
#ifdef DEBUG
|
||||
#define JudyCheckPop JudyLCheckPop
|
||||
#endif
|
||||
|
||||
#endif // JUDYL
|
||||
|
||||
#endif // _JUDYPRIVATE1L_INCLUDED
|
788
libnetdata/libjudy/src/JudyCommon/JudyPrivateBranch.h
Normal file
788
libnetdata/libjudy/src/JudyCommon/JudyPrivateBranch.h
Normal file
|
@ -0,0 +1,788 @@
|
|||
#ifndef _JUDY_PRIVATE_BRANCH_INCLUDED
|
||||
#define _JUDY_PRIVATE_BRANCH_INCLUDED
|
||||
// _________________
|
||||
//
|
||||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 1.2 $ $Source: /home/doug/judy-1.0.5_min/test/../src/JudyCommon/RCS/JudyPrivateBranch.h,v $
|
||||
//
|
||||
// Header file for all Judy sources, for global but private (non-exported)
|
||||
// declarations specific to branch support.
|
||||
//
|
||||
// See also the "Judy Shop Manual" (try judy/doc/int/JudyShopManual.*).
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDY POINTER (JP) SUPPORT
|
||||
// ****************************************************************************
|
||||
//
|
||||
// This "rich pointer" object is pivotal to Judy execution.
|
||||
//
|
||||
// JP CONTAINING OTHER THAN IMMEDIATE INDEXES:
|
||||
//
|
||||
// If the JP points to a linear or bitmap leaf, jp_DcdPopO contains the
|
||||
// Population-1 in LSbs and Decode (Dcd) bytes in the MSBs. (In practice the
|
||||
// Decode bits are masked off while accessing the Pop0 bits.)
|
||||
//
|
||||
// The Decode Size, the number of Dcd bytes available, is encoded in jpo_Type.
|
||||
// It can also be thought of as the number of states "skipped" in the SM, where
|
||||
// each state decodes 8 bits = 1 byte.
|
||||
//
|
||||
// TBD: Dont need two structures, except possibly to force jp_Type to highest
|
||||
// address!
|
||||
//
|
||||
// Note: The jpo_u union is not required by HP-UX or Linux but Win32 because
|
||||
// the cl.exe compiler otherwise refuses to pack a bitfield (DcdPopO) with
|
||||
// anything else, even with the -Zp option. This is pretty ugly, but
|
||||
// fortunately portable, and its all hide-able by macros (see below).
|
||||
|
||||
typedef struct J_UDY_POINTER_OTHERS // JPO.
|
||||
{
|
||||
Word_t j_po_Addr; // first word: Pjp_t, Word_t, etc.
|
||||
union {
|
||||
Word_t j_po_Addr1;
|
||||
uint8_t j_po_DcdP0[sizeof(Word_t) - 1];
|
||||
uint8_t j_po_Bytes[sizeof(Word_t)]; // last byte = jp_Type.
|
||||
} jpo_u;
|
||||
} jpo_t;
|
||||
|
||||
|
||||
// JP CONTAINING IMMEDIATE INDEXES:
|
||||
//
|
||||
// j_pi_1Index[] plus j_pi_LIndex[] together hold as many N-byte (1..3-byte
|
||||
// [1..7-byte]) Indexes as will fit in sizeof(jpi_t) less 1 byte for j_pi_Type
|
||||
// (that is, 7..1 [15..1] Indexes).
|
||||
//
|
||||
// For Judy1, j_pi_1Index[] is used and j_pi_LIndex[] is not used.
|
||||
// For JudyL, j_pi_LIndex[] is used and j_pi_1Index[] is not used.
|
||||
//
|
||||
// Note: Actually when Pop1 = 1, jpi_t is not used, and the least bytes of the
|
||||
// single Index are stored in j_po_DcdPopO, for both Judy1 and JudyL, so for
|
||||
// JudyL the j_po_Addr field can hold the target value.
|
||||
//
|
||||
// TBD: Revise this structure to not overload j_po_DcdPopO this way? The
|
||||
// current arrangement works, its just confusing.
|
||||
|
||||
typedef struct _JUDY_POINTER_IMMEDL
|
||||
{
|
||||
Word_t j_pL_Addr;
|
||||
uint8_t j_pL_LIndex[sizeof(Word_t) - 1]; // see above.
|
||||
uint8_t j_pL_Type;
|
||||
} jpL_t;
|
||||
|
||||
typedef struct _JUDY_POINTER_IMMED1
|
||||
{
|
||||
uint8_t j_p1_1Index[(2 * sizeof(Word_t)) - 1];
|
||||
uint8_t j_p1_Type;
|
||||
} jp1_t;
|
||||
|
||||
// UNION OF JP TYPES:
|
||||
//
|
||||
// A branch is an array of cJU_BRANCHUNUMJPS (256) of this object, or an
|
||||
// alternate data type such as: A linear branch which is a list of 2..7 JPs,
|
||||
// or a bitmap branch which contains 8 lists of 0..32 JPs. JPs reside only in
|
||||
// branches of a Judy SM.
|
||||
|
||||
typedef union J_UDY_POINTER // JP.
|
||||
{
|
||||
jpo_t j_po; // other than immediate indexes.
|
||||
jpL_t j_pL; // immediate indexes.
|
||||
jp1_t j_p1; // immediate indexes.
|
||||
} jp_t, *Pjp_t;
|
||||
|
||||
// For coding convenience:
|
||||
//
|
||||
// Note, jp_Type has the same bits in jpo_t jpL_t and jp1_t.
|
||||
|
||||
#define jp_1Index j_p1.j_p1_1Index // for storing Indexes in first word.
|
||||
#define jp_LIndex j_pL.j_pL_LIndex // for storing Indexes in second word.
|
||||
#define jp_Addr j_po.j_po_Addr
|
||||
#define jp_Addr1 j_po.jpo_u.j_po_Addr1
|
||||
//#define jp_DcdPop0 j_po.jpo_u.j_po_DcdPop0
|
||||
#define jp_Addr1 j_po.jpo_u.j_po_Addr1
|
||||
//#define jp_Type j_po.jpo_u.j_po_Bytes[sizeof(Word_t) - 1]
|
||||
#define jp_Type j_p1.j_p1_Type
|
||||
#define jp_DcdP0 j_po.jpo_u.j_po_DcdP0
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDY POINTER (JP) -- RELATED MACROS AND CONSTANTS
|
||||
// ****************************************************************************
|
||||
|
||||
// EXTRACT VALUES FROM JP:
|
||||
//
|
||||
// Masks for the bytes in the Dcd and Pop0 parts of jp_DcdPopO:
|
||||
//
|
||||
// cJU_DCDMASK() consists of a mask that excludes the (LSb) Pop0 bytes and
|
||||
// also, just to be safe, the top byte of the word, since jp_DcdPopO is 1 byte
|
||||
// less than a full word.
|
||||
//
|
||||
// Note: These are constant macros (cJU) because cPopBytes should be a
|
||||
// constant. Also note cPopBytes == state in the SM.
|
||||
|
||||
#define cJU_POP0MASK(cPopBytes) JU_LEASTBYTESMASK(cPopBytes)
|
||||
|
||||
#define cJU_DCDMASK(cPopBytes) \
|
||||
((cJU_ALLONES >> cJU_BITSPERBYTE) & (~cJU_POP0MASK(cPopBytes)))
|
||||
|
||||
// Mask off the high byte from INDEX to it can be compared to DcdPopO:
|
||||
|
||||
#define JU_TRIMTODCDSIZE(INDEX) ((cJU_ALLONES >> cJU_BITSPERBYTE) & (INDEX))
|
||||
|
||||
// Get from jp_DcdPopO the Pop0 for various branch JP Types:
|
||||
//
|
||||
// Note: There are no simple macros for cJU_BRANCH* Types because their
|
||||
// populations must be added up and dont reside in an already-calculated
|
||||
// place.
|
||||
|
||||
#define JU_JPBRANCH_POP0(PJP,cPopBytes) \
|
||||
(JU_JPDCDPOP0(PJP) & cJU_POP0MASK(cPopBytes))
|
||||
|
||||
// METHOD FOR DETERMINING IF OBJECTS HAVE ROOM TO GROW:
|
||||
//
|
||||
// J__U_GROWCK() is a generic method to determine if an object can grow in
|
||||
// place, based on whether the next population size (one more) would use the
|
||||
// same space.
|
||||
|
||||
#define J__U_GROWCK(POP1,MAXPOP1,POPTOWORDS) \
|
||||
(((POP1) != (MAXPOP1)) && (POPTOWORDS[POP1] == POPTOWORDS[(POP1) + 1]))
|
||||
|
||||
#define JU_BRANCHBJPGROWINPLACE(NumJPs) \
|
||||
J__U_GROWCK(NumJPs, cJU_BITSPERSUBEXPB, j__U_BranchBJPPopToWords)
|
||||
|
||||
|
||||
// DETERMINE IF AN INDEX IS (NOT) IN A JPS EXPANSE:
|
||||
|
||||
#define JU_DCDNOTMATCHINDEX(INDEX,PJP,POP0BYTES) \
|
||||
(((INDEX) ^ JU_JPDCDPOP0(PJP)) & cJU_DCDMASK(POP0BYTES))
|
||||
|
||||
|
||||
// NUMBER OF JPs IN AN UNCOMPRESSED BRANCH:
|
||||
//
|
||||
// An uncompressed branch is simply an array of 256 Judy Pointers (JPs). It is
|
||||
// a minimum cacheline fill object. Define it here before its first needed.
|
||||
|
||||
#define cJU_BRANCHUNUMJPS cJU_SUBEXPPERSTATE
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDY BRANCH LINEAR (JBL) SUPPORT
|
||||
// ****************************************************************************
|
||||
//
|
||||
// A linear branch is a way of compressing empty expanses (null JPs) out of an
|
||||
// uncompressed 256-way branch, when the number of populated expanses is so
|
||||
// small that even a bitmap branch is excessive.
|
||||
//
|
||||
// The maximum number of JPs in a Judy linear branch:
|
||||
//
|
||||
// Note: This number results in a 1-cacheline sized structure. Previous
|
||||
// versions had a larger struct so a linear branch didnt become a bitmap
|
||||
// branch until the memory consumed was even, but for speed, its better to
|
||||
// switch "sooner" and keep a linear branch fast.
|
||||
|
||||
#define cJU_BRANCHLMAXJPS 7
|
||||
|
||||
|
||||
// LINEAR BRANCH STRUCT:
|
||||
//
|
||||
// 1-byte count, followed by array of byte-sized expanses, followed by JPs.
|
||||
|
||||
typedef struct J__UDY_BRANCH_LINEAR
|
||||
{
|
||||
uint8_t jbl_NumJPs; // num of JPs (Pjp_t), 1..N.
|
||||
uint8_t jbl_Expanse[cJU_BRANCHLMAXJPS]; // 1..7 MSbs of pop exps.
|
||||
jp_t jbl_jp [cJU_BRANCHLMAXJPS]; // JPs for populated exps.
|
||||
} jbl_t, * Pjbl_t;
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDY BRANCH BITMAP (JBB) SUPPORT
|
||||
// ****************************************************************************
|
||||
//
|
||||
// A bitmap branch is a way of compressing empty expanses (null JPs) out of
|
||||
// uncompressed 256-way branch. This costs 1 additional cache line fill, but
|
||||
// can save a lot of memory when it matters most, near the leaves, and
|
||||
// typically there will be only one at most in the path to any Index (leaf).
|
||||
//
|
||||
// The bitmap indicates which of the cJU_BRANCHUNUMJPS (256) JPs in the branch
|
||||
// are NOT null, that is, their expanses are populated. The jbb_t also
|
||||
// contains N pointers to "mini" Judy branches ("subexpanses") of up to M JPs
|
||||
// each (see BITMAP_BRANCHMxN, for example, BITMAP_BRANCH32x8), where M x N =
|
||||
// cJU_BRANCHUNUMJPS. These are dynamically allocated and never contain
|
||||
// cJ*_JPNULL* jp_Types. An empty subexpanse is represented by no bit sets in
|
||||
// the corresponding subexpanse bitmap, in which case the corresponding
|
||||
// jbbs_Pjp pointers value is unused.
|
||||
//
|
||||
// Note that the number of valid JPs in each 1-of-N subexpanses is determined
|
||||
// by POPULATION rather than by EXPANSE -- the desired outcome to save memory
|
||||
// when near the leaves. Note that the memory required for 185 JPs is about as
|
||||
// much as an uncompressed 256-way branch, therefore 184 is set as the maximum.
|
||||
// However, it is expected that a conversion to an uncompressed 256-way branch
|
||||
// will normally take place before this limit is reached for other reasons,
|
||||
// such as improving performance when the "wasted" memory is well amortized by
|
||||
// the population under the branch, preserving an acceptable overall
|
||||
// bytes/Index in the Judy array.
|
||||
//
|
||||
// The number of pointers to arrays of JPs in the Judy bitmap branch:
|
||||
//
|
||||
// Note: The numbers below are the same in both 32 and 64 bit systems.
|
||||
|
||||
#define cJU_BRANCHBMAXJPS 184 // maximum JPs for bitmap branches.
|
||||
|
||||
// Convenience wrappers for referencing BranchB bitmaps or JP subarray
|
||||
// pointers:
|
||||
//
|
||||
// Note: JU_JBB_PJP produces a "raw" memory address that must pass through
|
||||
// P_JP before use, except when freeing memory:
|
||||
|
||||
#define JU_JBB_BITMAP(Pjbb, SubExp) ((Pjbb)->jbb_jbbs[SubExp].jbbs_Bitmap)
|
||||
#define JU_JBB_PJP( Pjbb, SubExp) ((Pjbb)->jbb_jbbs[SubExp].jbbs_Pjp)
|
||||
|
||||
#define JU_SUBEXPB(Digit) (((Digit) / cJU_BITSPERSUBEXPB) & (cJU_NUMSUBEXPB-1))
|
||||
|
||||
#define JU_BITMAPTESTB(Pjbb, Index) \
|
||||
(JU_JBB_BITMAP(Pjbb, JU_SUBEXPB(Index)) & JU_BITPOSMASKB(Index))
|
||||
|
||||
#define JU_BITMAPSETB(Pjbb, Index) \
|
||||
(JU_JBB_BITMAP(Pjbb, JU_SUBEXPB(Index)) |= JU_BITPOSMASKB(Index))
|
||||
|
||||
// Note: JU_BITMAPCLEARB is not defined because the code does it a faster way.
|
||||
|
||||
typedef struct J__UDY_BRANCH_BITMAP_SUBEXPANSE
|
||||
{
|
||||
BITMAPB_t jbbs_Bitmap;
|
||||
Pjp_t jbbs_Pjp;
|
||||
|
||||
} jbbs_t;
|
||||
|
||||
typedef struct J__UDY_BRANCH_BITMAP
|
||||
{
|
||||
jbbs_t jbb_jbbs [cJU_NUMSUBEXPB];
|
||||
#ifdef SUBEXPCOUNTS
|
||||
Word_t jbb_subPop1[cJU_NUMSUBEXPB];
|
||||
#endif
|
||||
} jbb_t, * Pjbb_t;
|
||||
|
||||
#define JU_BRANCHJP_NUMJPSTOWORDS(NumJPs) (j__U_BranchBJPPopToWords[NumJPs])
|
||||
|
||||
#ifdef SUBEXPCOUNTS
|
||||
#define cJU_NUMSUBEXPU 16 // number of subexpanse counts.
|
||||
#endif
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDY BRANCH UNCOMPRESSED (JBU) SUPPORT
|
||||
// ****************************************************************************
|
||||
|
||||
// Convenience wrapper for referencing BranchU JPs:
|
||||
//
|
||||
// Note: This produces a non-"raw" address already passed through P_JBU().
|
||||
|
||||
#define JU_JBU_PJP(Pjp,Index,Level) \
|
||||
(&((P_JBU((Pjp)->jp_Addr))->jbu_jp[JU_DIGITATSTATE(Index, Level)]))
|
||||
#define JU_JBU_PJP0(Pjp) \
|
||||
(&((P_JBU((Pjp)->jp_Addr))->jbu_jp[0]))
|
||||
|
||||
typedef struct J__UDY_BRANCH_UNCOMPRESSED
|
||||
{
|
||||
jp_t jbu_jp [cJU_BRANCHUNUMJPS]; // JPs for populated exp.
|
||||
#ifdef SUBEXPCOUNTS
|
||||
Word_t jbu_subPop1[cJU_NUMSUBEXPU];
|
||||
#endif
|
||||
} jbu_t, * Pjbu_t;
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// OTHER SUPPORT FOR JUDY STATE MACHINES (SMs)
|
||||
// ****************************************************************************
|
||||
|
||||
// OBJECT SIZES IN WORDS:
|
||||
//
|
||||
// Word_ts per various JudyL structures that have constant sizes.
|
||||
// cJU_WORDSPERJP should always be 2; this is fundamental to the Judy
|
||||
// structures.
|
||||
|
||||
#define cJU_WORDSPERJP (sizeof(jp_t) / cJU_BYTESPERWORD)
|
||||
#define cJU_WORDSPERCL (cJU_BYTESPERCL / cJU_BYTESPERWORD)
|
||||
|
||||
|
||||
// OPPORTUNISTIC UNCOMPRESSION:
|
||||
//
|
||||
// Define populations at which a BranchL or BranchB must convert to BranchU.
|
||||
// Earlier conversion is possible with good memory efficiency -- see below.
|
||||
|
||||
#ifndef NO_BRANCHU
|
||||
|
||||
// Max population below BranchL, then convert to BranchU:
|
||||
|
||||
#define JU_BRANCHL_MAX_POP 1000
|
||||
|
||||
// Minimum global population increment before next conversion of a BranchB to a
|
||||
// BranchU:
|
||||
//
|
||||
// This is was done to allow malloc() to coalesce memory before the next big
|
||||
// (~512 words) allocation.
|
||||
|
||||
#define JU_BTOU_POP_INCREMENT 300
|
||||
|
||||
// Min/max population below BranchB, then convert to BranchU:
|
||||
|
||||
#define JU_BRANCHB_MIN_POP 135
|
||||
#define JU_BRANCHB_MAX_POP 750
|
||||
|
||||
#else // NO_BRANCHU
|
||||
|
||||
// These are set up to have conservative conversion schedules to BranchU:
|
||||
|
||||
#define JU_BRANCHL_MAX_POP (-1UL)
|
||||
#define JU_BTOU_POP_INCREMENT 300
|
||||
#define JU_BRANCHB_MIN_POP 1000
|
||||
#define JU_BRANCHB_MAX_POP (-1UL)
|
||||
|
||||
#endif // NO_BRANCHU
|
||||
|
||||
|
||||
// MISCELLANEOUS MACROS:
|
||||
|
||||
// Get N most significant bits from the shifted Index word:
|
||||
//
|
||||
// As Index words are decoded, they are shifted left so only relevant,
|
||||
// undecoded Index bits remain.
|
||||
|
||||
#define JU_BITSFROMSFTIDX(SFTIDX, N) ((SFTIDX) >> (cJU_BITSPERWORD - (N)))
|
||||
|
||||
// TBD: I have my doubts about the necessity of these macros (dlb):
|
||||
|
||||
// Produce 1-digit mask at specified state:
|
||||
|
||||
#define cJU_MASKATSTATE(State) (0xffL << (((State) - 1) * cJU_BITSPERBYTE))
|
||||
|
||||
// Get byte (digit) from Index at the specified state, right justified:
|
||||
//
|
||||
// Note: State must be 1..cJU_ROOTSTATE, and Digits must be 1..(cJU_ROOTSTATE
|
||||
// - 1), but theres no way to assert these within an expression.
|
||||
|
||||
#define JU_DIGITATSTATE(Index,cState) \
|
||||
((uint8_t)((Index) >> (((cState) - 1) * cJU_BITSPERBYTE)))
|
||||
|
||||
// Similarly, place byte (digit) at correct position for the specified state:
|
||||
//
|
||||
// Note: Cast digit to a Word_t first so there are no complaints or problems
|
||||
// about shifting it more than 32 bits on a 64-bit system, say, when it is a
|
||||
// uint8_t from jbl_Expanse[]. (Believe it or not, the C standard says to
|
||||
// promote an unsigned char to a signed int; -Ac does not do this, but -Ae
|
||||
// does.)
|
||||
//
|
||||
// Also, to make lint happy, cast the whole result again because apparently
|
||||
// shifting a Word_t does not result in a Word_t!
|
||||
|
||||
#define JU_DIGITTOSTATE(Digit,cState) \
|
||||
((Word_t) (((Word_t) (Digit)) << (((cState) - 1) * cJU_BITSPERBYTE)))
|
||||
|
||||
#endif // ! _JUDY_PRIVATE_BRANCH_INCLUDED
|
||||
|
||||
|
||||
#ifdef TEST_INSDEL
|
||||
|
||||
// ****************************************************************************
|
||||
// TEST CODE FOR INSERT/DELETE MACROS
|
||||
// ****************************************************************************
|
||||
//
|
||||
// To use this, compile a temporary *.c file containing:
|
||||
//
|
||||
// #define DEBUG
|
||||
// #define JUDY_ASSERT
|
||||
// #define TEST_INSDEL
|
||||
// #include "JudyPrivate.h"
|
||||
// #include "JudyPrivateBranch.h"
|
||||
//
|
||||
// Use a command like this: cc -Ae +DD64 -I. -I JudyCommon -o t t.c
|
||||
// For best results, include +DD64 on a 64-bit system.
|
||||
//
|
||||
// This test code exercises some tricky macros, but the output must be studied
|
||||
// manually to verify it. Assume that for even-index testing, whole words
|
||||
// (Word_t) suffices.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define INDEXES 3 // in each array.
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// I N I T
|
||||
//
|
||||
// Set up variables for next test. See usage.
|
||||
|
||||
FUNCTION void Init (
|
||||
int base,
|
||||
PWord_t PeIndex,
|
||||
PWord_t PoIndex,
|
||||
PWord_t Peleaf, // always whole words.
|
||||
#ifndef JU_64BIT
|
||||
uint8_t * Poleaf3)
|
||||
#else
|
||||
uint8_t * Poleaf3,
|
||||
uint8_t * Poleaf5,
|
||||
uint8_t * Poleaf6,
|
||||
uint8_t * Poleaf7)
|
||||
#endif
|
||||
{
|
||||
int offset;
|
||||
|
||||
*PeIndex = 99;
|
||||
|
||||
for (offset = 0; offset <= INDEXES; ++offset)
|
||||
Peleaf[offset] = base + offset;
|
||||
|
||||
for (offset = 0; offset < (INDEXES + 1) * 3; ++offset)
|
||||
Poleaf3[offset] = base + offset;
|
||||
|
||||
#ifndef JU_64BIT
|
||||
*PoIndex = (91 << 24) | (92 << 16) | (93 << 8) | 94;
|
||||
#else
|
||||
|
||||
*PoIndex = (91L << 56) | (92L << 48) | (93L << 40) | (94L << 32)
|
||||
| (95L << 24) | (96L << 16) | (97L << 8) | 98L;
|
||||
|
||||
for (offset = 0; offset < (INDEXES + 1) * 5; ++offset)
|
||||
Poleaf5[offset] = base + offset;
|
||||
|
||||
for (offset = 0; offset < (INDEXES + 1) * 6; ++offset)
|
||||
Poleaf6[offset] = base + offset;
|
||||
|
||||
for (offset = 0; offset < (INDEXES + 1) * 7; ++offset)
|
||||
Poleaf7[offset] = base + offset;
|
||||
#endif
|
||||
|
||||
} // Init()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// P R I N T L E A F
|
||||
//
|
||||
// Print the byte values in a leaf.
|
||||
|
||||
FUNCTION void PrintLeaf (
|
||||
char * Label, // for output.
|
||||
int IOffset, // insertion offset in array.
|
||||
int Indsize, // index size in bytes.
|
||||
uint8_t * PLeaf) // array of Index bytes.
|
||||
{
|
||||
int offset; // in PLeaf.
|
||||
int byte; // in one word.
|
||||
|
||||
(void) printf("%s %u: ", Label, IOffset);
|
||||
|
||||
for (offset = 0; offset <= INDEXES; ++offset)
|
||||
{
|
||||
for (byte = 0; byte < Indsize; ++byte)
|
||||
(void) printf("%2d", PLeaf[(offset * Indsize) + byte]);
|
||||
|
||||
(void) printf(" ");
|
||||
}
|
||||
|
||||
(void) printf("\n");
|
||||
|
||||
} // PrintLeaf()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// M A I N
|
||||
//
|
||||
// Test program.
|
||||
|
||||
FUNCTION main()
|
||||
{
|
||||
Word_t eIndex; // even, to insert.
|
||||
Word_t oIndex; // odd, to insert.
|
||||
Word_t eleaf [ INDEXES + 1]; // even leaf, index size 4.
|
||||
uint8_t oleaf3[(INDEXES + 1) * 3]; // odd leaf, index size 3.
|
||||
#ifdef JU_64BIT
|
||||
uint8_t oleaf5[(INDEXES + 1) * 5]; // odd leaf, index size 5.
|
||||
uint8_t oleaf6[(INDEXES + 1) * 6]; // odd leaf, index size 6.
|
||||
uint8_t oleaf7[(INDEXES + 1) * 7]; // odd leaf, index size 7.
|
||||
#endif
|
||||
Word_t eleaf_2 [ INDEXES + 1]; // same, but second arrays:
|
||||
uint8_t oleaf3_2[(INDEXES + 1) * 3];
|
||||
#ifdef JU_64BIT
|
||||
uint8_t oleaf5_2[(INDEXES + 1) * 5];
|
||||
uint8_t oleaf6_2[(INDEXES + 1) * 6];
|
||||
uint8_t oleaf7_2[(INDEXES + 1) * 7];
|
||||
#endif
|
||||
int ioffset; // index insertion offset.
|
||||
|
||||
#ifndef JU_64BIT
|
||||
#define INIT Init( 0, & eIndex, & oIndex, eleaf, oleaf3)
|
||||
#define INIT2 INIT; Init(50, & eIndex, & oIndex, eleaf_2, oleaf3_2)
|
||||
#else
|
||||
#define INIT Init( 0, & eIndex, & oIndex, eleaf, oleaf3, \
|
||||
oleaf5, oleaf6, oleaf7)
|
||||
#define INIT2 INIT; Init(50, & eIndex, & oIndex, eleaf_2, oleaf3_2, \
|
||||
oleaf5_2, oleaf6_2, oleaf7_2)
|
||||
#endif
|
||||
|
||||
#define WSIZE sizeof (Word_t) // shorthand.
|
||||
|
||||
#ifdef PRINTALL // to turn on "noisy" printouts.
|
||||
#define PRINTLEAF(Label,IOffset,Indsize,PLeaf) \
|
||||
PrintLeaf(Label,IOffset,Indsize,PLeaf)
|
||||
#else
|
||||
#define PRINTLEAF(Label,IOffset,Indsize,PLeaf) \
|
||||
if (ioffset == 0) \
|
||||
PrintLeaf(Label,IOffset,Indsize,PLeaf)
|
||||
#endif
|
||||
|
||||
(void) printf(
|
||||
"In each case, tests operate on an initial array of %d indexes. Even-index\n"
|
||||
"tests set index values to 0,1,2...; odd-index tests set byte values to\n"
|
||||
"0,1,2... Inserted indexes have a value of 99 or else byte values 91,92,...\n",
|
||||
INDEXES);
|
||||
|
||||
(void) puts("\nJU_INSERTINPLACE():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, WSIZE, (uint8_t *) eleaf);
|
||||
JU_INSERTINPLACE(eleaf, INDEXES, ioffset, eIndex);
|
||||
PrintLeaf("After ", ioffset, WSIZE, (uint8_t *) eleaf);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_INSERTINPLACE3():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, 3, oleaf3);
|
||||
JU_INSERTINPLACE3(oleaf3, INDEXES, ioffset, oIndex);
|
||||
PrintLeaf("After ", ioffset, 3, oleaf3);
|
||||
}
|
||||
|
||||
#ifdef JU_64BIT
|
||||
(void) puts("\nJU_INSERTINPLACE5():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, 5, oleaf5);
|
||||
JU_INSERTINPLACE5(oleaf5, INDEXES, ioffset, oIndex);
|
||||
PrintLeaf("After ", ioffset, 5, oleaf5);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_INSERTINPLACE6():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, 6, oleaf6);
|
||||
JU_INSERTINPLACE6(oleaf6, INDEXES, ioffset, oIndex);
|
||||
PrintLeaf("After ", ioffset, 6, oleaf6);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_INSERTINPLACE7():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, 7, oleaf7);
|
||||
JU_INSERTINPLACE7(oleaf7, INDEXES, ioffset, oIndex);
|
||||
PrintLeaf("After ", ioffset, 7, oleaf7);
|
||||
}
|
||||
#endif // JU_64BIT
|
||||
|
||||
(void) puts("\nJU_DELETEINPLACE():");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, WSIZE, (uint8_t *) eleaf);
|
||||
JU_DELETEINPLACE(eleaf, INDEXES, ioffset);
|
||||
PrintLeaf("After ", ioffset, WSIZE, (uint8_t *) eleaf);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_DELETEINPLACE_ODD(3):");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, 3, oleaf3);
|
||||
JU_DELETEINPLACE_ODD(oleaf3, INDEXES, ioffset, 3);
|
||||
PrintLeaf("After ", ioffset, 3, oleaf3);
|
||||
}
|
||||
|
||||
#ifdef JU_64BIT
|
||||
(void) puts("\nJU_DELETEINPLACE_ODD(5):");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, 5, oleaf5);
|
||||
JU_DELETEINPLACE_ODD(oleaf5, INDEXES, ioffset, 5);
|
||||
PrintLeaf("After ", ioffset, 5, oleaf5);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_DELETEINPLACE_ODD(6):");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, 6, oleaf6);
|
||||
JU_DELETEINPLACE_ODD(oleaf6, INDEXES, ioffset, 6);
|
||||
PrintLeaf("After ", ioffset, 6, oleaf6);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_DELETEINPLACE_ODD(7):");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT;
|
||||
PRINTLEAF("Before", ioffset, 7, oleaf7);
|
||||
JU_DELETEINPLACE_ODD(oleaf7, INDEXES, ioffset, 7);
|
||||
PrintLeaf("After ", ioffset, 7, oleaf7);
|
||||
}
|
||||
#endif // JU_64BIT
|
||||
|
||||
(void) puts("\nJU_INSERTCOPY():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, WSIZE, (uint8_t *) eleaf);
|
||||
PRINTLEAF("Before, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
|
||||
JU_INSERTCOPY(eleaf_2, eleaf, INDEXES, ioffset, eIndex);
|
||||
PRINTLEAF("After, src ", ioffset, WSIZE, (uint8_t *) eleaf);
|
||||
PrintLeaf("After, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_INSERTCOPY3():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, 3, oleaf3);
|
||||
PRINTLEAF("Before, dest", ioffset, 3, oleaf3_2);
|
||||
JU_INSERTCOPY3(oleaf3_2, oleaf3, INDEXES, ioffset, oIndex);
|
||||
PRINTLEAF("After, src ", ioffset, 3, oleaf3);
|
||||
PrintLeaf("After, dest", ioffset, 3, oleaf3_2);
|
||||
}
|
||||
|
||||
#ifdef JU_64BIT
|
||||
(void) puts("\nJU_INSERTCOPY5():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, 5, oleaf5);
|
||||
PRINTLEAF("Before, dest", ioffset, 5, oleaf5_2);
|
||||
JU_INSERTCOPY5(oleaf5_2, oleaf5, INDEXES, ioffset, oIndex);
|
||||
PRINTLEAF("After, src ", ioffset, 5, oleaf5);
|
||||
PrintLeaf("After, dest", ioffset, 5, oleaf5_2);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_INSERTCOPY6():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, 6, oleaf6);
|
||||
PRINTLEAF("Before, dest", ioffset, 6, oleaf6_2);
|
||||
JU_INSERTCOPY6(oleaf6_2, oleaf6, INDEXES, ioffset, oIndex);
|
||||
PRINTLEAF("After, src ", ioffset, 6, oleaf6);
|
||||
PrintLeaf("After, dest", ioffset, 6, oleaf6_2);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_INSERTCOPY7():");
|
||||
|
||||
for (ioffset = 0; ioffset <= INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, 7, oleaf7);
|
||||
PRINTLEAF("Before, dest", ioffset, 7, oleaf7_2);
|
||||
JU_INSERTCOPY7(oleaf7_2, oleaf7, INDEXES, ioffset, oIndex);
|
||||
PRINTLEAF("After, src ", ioffset, 7, oleaf7);
|
||||
PrintLeaf("After, dest", ioffset, 7, oleaf7_2);
|
||||
}
|
||||
#endif // JU_64BIT
|
||||
|
||||
(void) puts("\nJU_DELETECOPY():");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, WSIZE, (uint8_t *) eleaf);
|
||||
PRINTLEAF("Before, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
|
||||
JU_DELETECOPY(eleaf_2, eleaf, INDEXES, ioffset, ignore);
|
||||
PRINTLEAF("After, src ", ioffset, WSIZE, (uint8_t *) eleaf);
|
||||
PrintLeaf("After, dest", ioffset, WSIZE, (uint8_t *) eleaf_2);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_DELETECOPY_ODD(3):");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, 3, oleaf3);
|
||||
PRINTLEAF("Before, dest", ioffset, 3, oleaf3_2);
|
||||
JU_DELETECOPY_ODD(oleaf3_2, oleaf3, INDEXES, ioffset, 3);
|
||||
PRINTLEAF("After, src ", ioffset, 3, oleaf3);
|
||||
PrintLeaf("After, dest", ioffset, 3, oleaf3_2);
|
||||
}
|
||||
|
||||
#ifdef JU_64BIT
|
||||
(void) puts("\nJU_DELETECOPY_ODD(5):");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, 5, oleaf5);
|
||||
PRINTLEAF("Before, dest", ioffset, 5, oleaf5_2);
|
||||
JU_DELETECOPY_ODD(oleaf5_2, oleaf5, INDEXES, ioffset, 5);
|
||||
PRINTLEAF("After, src ", ioffset, 5, oleaf5);
|
||||
PrintLeaf("After, dest", ioffset, 5, oleaf5_2);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_DELETECOPY_ODD(6):");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, 6, oleaf6);
|
||||
PRINTLEAF("Before, dest", ioffset, 6, oleaf6_2);
|
||||
JU_DELETECOPY_ODD(oleaf6_2, oleaf6, INDEXES, ioffset, 6);
|
||||
PRINTLEAF("After, src ", ioffset, 6, oleaf6);
|
||||
PrintLeaf("After, dest", ioffset, 6, oleaf6_2);
|
||||
}
|
||||
|
||||
(void) puts("\nJU_DELETECOPY_ODD(7):");
|
||||
|
||||
for (ioffset = 0; ioffset < INDEXES; ++ioffset)
|
||||
{
|
||||
INIT2;
|
||||
PRINTLEAF("Before, src ", ioffset, 7, oleaf7);
|
||||
PRINTLEAF("Before, dest", ioffset, 7, oleaf7_2);
|
||||
JU_DELETECOPY_ODD(oleaf7_2, oleaf7, INDEXES, ioffset, 7);
|
||||
PRINTLEAF("After, src ", ioffset, 7, oleaf7);
|
||||
PrintLeaf("After, dest", ioffset, 7, oleaf7_2);
|
||||
}
|
||||
#endif // JU_64BIT
|
||||
|
||||
return(0);
|
||||
|
||||
} // main()
|
||||
|
||||
#endif // TEST_INSDEL
|
771
libnetdata/libjudy/src/JudyHS/JudyHS.c
Normal file
771
libnetdata/libjudy/src/JudyHS/JudyHS.c
Normal file
|
@ -0,0 +1,771 @@
|
|||
// @(#) $Revision: 4.1 $ $Source: /judy/src/JudyHS/JudyHS.c
|
||||
//=======================================================================
|
||||
// Author Douglas L. Baskins, Dec 2003.
|
||||
// Permission to use this code is freely granted, provided that this
|
||||
// statement is retained.
|
||||
// email - doug@sourcejudy.com -or- dougbaskins@yahoo.com
|
||||
//=======================================================================
|
||||
|
||||
#include <string.h> // for memcmp(), memcpy()
|
||||
|
||||
#include <Judy.h> // for JudyL* routines/macros
|
||||
|
||||
/*
|
||||
This routine is a very fast "string" version of an ADT that stores
|
||||
(JudyHSIns()), retrieves (JudyHSGet()), deletes (JudyHSDel()) and
|
||||
frees the entire ADT (JudyHSFreeArray()) strings. It uses the "Judy
|
||||
arrays" JudyL() API as the main workhorse. The length of the string
|
||||
is included in the calling parameters so that strings with embedded
|
||||
\0s can be used. The string lengths can be from 0 bytes to whatever
|
||||
malloc() can handle (~2GB).
|
||||
|
||||
Compile:
|
||||
|
||||
cc -O JudyHS.c -c needs to link with -lJudy (libJudy.a)
|
||||
|
||||
Note: in gcc version 3.3.1, -O2 generates faster code than -O
|
||||
Note: in gcc version 3.3.2, -O3 generates faster code than -O2
|
||||
|
||||
NOTES:
|
||||
|
||||
1) There may be some performance issues with 64 bit machines, because I
|
||||
have not characterized that it yet.
|
||||
|
||||
2) It appears that a modern CPU (>2Ghz) that the instruction times are
|
||||
much faster that a RAM access, so building up a word from bytes takes
|
||||
no longer that a whole word access. I am taking advantage of this to
|
||||
make this code endian neutral. A side effect of this is strings do
|
||||
not need to be aligned, nor tested to be on to a word boundry. In
|
||||
older and in slow (RISC) machines, this may be a performance issue.
|
||||
I have given up trying to optimize for machines that have very slow
|
||||
mpy, mod, variable shifts and call returns.
|
||||
|
||||
3) JudyHS is very scalable from 1 string to billions (with enough RAM).
|
||||
The memory usage is also scales with population. I have attempted to
|
||||
combine the best characteristics of JudyL arrays with Hashing methods
|
||||
and well designed modern processors (such as the 1.3Ghz Intel
|
||||
Centrino this is being written on).
|
||||
|
||||
HOW JudyHS WORKS: ( 4[8] means 4 bytes in 32 bit machine and 8 in 64)
|
||||
|
||||
A) A JudyL array is used to separate strings of equal lengths into
|
||||
their own structures (a different hash table is used for each length
|
||||
of string). The additional time overhead is very near zero because
|
||||
of the CPU cache. The space efficiency is improved because the
|
||||
length need not be stored with the string (ls_t). The "JLHash" ADT
|
||||
in the test program "StringCompare" is verification of both these
|
||||
assumptions.
|
||||
|
||||
B) A 32 bit hash value is produced from the string. Many thanks to
|
||||
the Internet and the author (Bob Jenkins) for coming up with a very
|
||||
good and fast universal string hash. Next the 32 bit hash number is
|
||||
used as an Index to another JudyL array. Notice that one (1) JudyL
|
||||
array is used as a hash table per each string length. If there are
|
||||
no hash collisions (normally) then the string is copied to a
|
||||
structure (ls_t) along with room for storing a Value. A flag is
|
||||
added to the pointer to note it is pointing to a ls_t structure.
|
||||
Since the lengths of the strings are the same, there is no need to
|
||||
stored length of string in the ls_t structure. This saves about a
|
||||
word per string of memory.
|
||||
|
||||
C) When there is a hashing collision (very rare), a JudyL array is
|
||||
used to decode the next 4[8] bytes of the string. That is, the next
|
||||
4[8] bytes of the string are used as the Index. This process is
|
||||
repeated until the remaining string is unique. The remaining string
|
||||
(if any) is stored in a (now smaller) ls_t structure. If the
|
||||
remaining string is less or equal to 4[8] bytes, then the ls_t
|
||||
structure is not needed and the Value area in the JudyL array is
|
||||
used. A compile option -DDONOTUSEHASH is available to test this
|
||||
structure without using hashing (only the JudyL tree is used). This
|
||||
is equivalent to having all strings hashed to the same bucket. The
|
||||
speed is still better than all other tree based ADTs I have tested.
|
||||
An added benefit of this is a very fast "hash collision" resolving.
|
||||
It could foil hackers that exploit the slow synonym (linked-list)
|
||||
collision handling property used with most hashing algorithms. If
|
||||
this is not a necessary property, then a simpler ADT "JLHash" that is
|
||||
documented the the test program "StringCompare.c" may be used with a
|
||||
little loss of memory efficiency (because it includes the string
|
||||
length with the ls_t structure). JudyHS was written to be the
|
||||
fastest, very scalable, memory efficient, general purpose string ADT
|
||||
possible. (However, I would like to eat those words someday). (dlb)
|
||||
|
||||
*/
|
||||
|
||||
#ifdef EXAMPLE_CODE
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Judy.h>
|
||||
|
||||
//#include "JudyHS.h" // for Judy.h without JudyHS*()
|
||||
|
||||
// By Doug Baskins Apr 2004 - for JudyHS man page
|
||||
|
||||
#define MAXLINE 1000000 /* max length of line */
|
||||
char Index[MAXLINE]; // string to check
|
||||
|
||||
int // Usage: CheckDupLines < file
|
||||
main()
|
||||
{
|
||||
Pvoid_t PJArray = (PWord_t)NULL; // Judy array.
|
||||
PWord_t PValue; // ^ Judy array element.
|
||||
Word_t Bytes; // size of JudyHS array.
|
||||
Word_t LineNumb = 0; // current line number
|
||||
Word_t Dups = 0; // number of duplicate lines
|
||||
|
||||
while (fgets(Index, MAXLINE, stdin) != (char *)NULL)
|
||||
{
|
||||
LineNumb++; // line number
|
||||
|
||||
// store string into array
|
||||
JHSI(PValue, PJArray, Index, strlen(Index));
|
||||
if (*PValue) // check if duplicate
|
||||
{
|
||||
Dups++; // count duplicates
|
||||
printf("Duplicate lines %lu:%lu:%s", *PValue, LineNumb, Index);
|
||||
}
|
||||
else
|
||||
{
|
||||
*PValue = LineNumb; // store Line number
|
||||
}
|
||||
}
|
||||
printf("%lu Duplicates, free JudyHS array of %lu Lines\n",
|
||||
Dups, LineNumb - Dups);
|
||||
JHSFA(Bytes, PJArray); // free array
|
||||
printf("The JudyHS array allocated %lu bytes of memory\n", Bytes);
|
||||
return (0);
|
||||
}
|
||||
#endif // EXAMPLE_CODE
|
||||
|
||||
// Note: Use JLAP_INVALID, which is non-zero, to mark pointers to a ls_t
|
||||
// This makes it compatable with previous versions of JudyL()
|
||||
|
||||
#define IS_PLS(PLS) (((Word_t) (PLS)) & JLAP_INVALID)
|
||||
#define CLEAR_PLS(PLS) (((Word_t) (PLS)) & (~JLAP_INVALID))
|
||||
#define SET_PLS(PLS) (((Word_t) (PLS)) | JLAP_INVALID)
|
||||
|
||||
#define WORDSIZE (sizeof(Word_t))
|
||||
|
||||
// this is the struct used for "leaf" strings. Note that
|
||||
// the Value is followed by a "variable" length ls_String array.
|
||||
//
|
||||
typedef struct L_EAFSTRING
|
||||
{
|
||||
Word_t ls_Value; // Value area (cannot change size)
|
||||
uint8_t ls_String[WORDSIZE]; // to fill out to a Word_t size
|
||||
} ls_t , *Pls_t;
|
||||
|
||||
#define LS_STRUCTOVD (sizeof(ls_t) - WORDSIZE)
|
||||
|
||||
// Calculate size of ls_t including the string of length of LEN.
|
||||
//
|
||||
#define LS_WORDLEN(LEN) (((LEN) + LS_STRUCTOVD + WORDSIZE - 1) / WORDSIZE)
|
||||
|
||||
// Copy from 0..4[8] bytes from string to a Word_t
|
||||
// NOTE: the copy in in little-endian order to take advantage of improved
|
||||
// memory efficiency of JudyLIns() with smaller numbers
|
||||
//
|
||||
#define COPYSTRING4toWORD(WORD,STR,LEN) \
|
||||
{ \
|
||||
WORD = 0; \
|
||||
switch(LEN) \
|
||||
{ \
|
||||
default: /* four and greater */ \
|
||||
case 4: \
|
||||
WORD += (Word_t)(((uint8_t *)(STR))[3] << 24); \
|
||||
case 3: \
|
||||
WORD += (Word_t)(((uint8_t *)(STR))[2] << 16); \
|
||||
case 2: \
|
||||
WORD += (Word_t)(((uint8_t *)(STR))[1] << 8); \
|
||||
case 1: \
|
||||
WORD += (Word_t)(((uint8_t *)(STR))[0]); \
|
||||
case 0: break; \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef JU_64BIT
|
||||
|
||||
// copy from 0..8 bytes from string to Word_t
|
||||
//
|
||||
#define COPYSTRING8toWORD(WORD,STR,LEN) \
|
||||
{ \
|
||||
WORD = 0UL; \
|
||||
switch(LEN) \
|
||||
{ \
|
||||
default: /* eight and greater */ \
|
||||
case 8: \
|
||||
WORD += ((Word_t)((uint8_t *)(STR))[7] << 56); \
|
||||
case 7: \
|
||||
WORD += ((Word_t)((uint8_t *)(STR))[6] << 48); \
|
||||
case 6: \
|
||||
WORD += ((Word_t)((uint8_t *)(STR))[5] << 40); \
|
||||
case 5: \
|
||||
WORD += ((Word_t)((uint8_t *)(STR))[4] << 32); \
|
||||
case 4: \
|
||||
WORD += ((Word_t)((uint8_t *)(STR))[3] << 24); \
|
||||
case 3: \
|
||||
WORD += ((Word_t)((uint8_t *)(STR))[2] << 16); \
|
||||
case 2: \
|
||||
WORD += ((Word_t)((uint8_t *)(STR))[1] << 8); \
|
||||
case 1: \
|
||||
WORD += ((Word_t)((uint8_t *)(STR))[0]); \
|
||||
case 0: break; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COPYSTRINGtoWORD COPYSTRING8toWORD
|
||||
|
||||
#else // JU_32BIT
|
||||
|
||||
#define COPYSTRINGtoWORD COPYSTRING4toWORD
|
||||
|
||||
#endif // JU_32BIT
|
||||
|
||||
// set JError_t locally
|
||||
|
||||
#define JU_SET_ERRNO(PJERROR, JERRNO) \
|
||||
{ \
|
||||
if (PJERROR != (PJError_t) NULL) \
|
||||
{ \
|
||||
if (JERRNO) \
|
||||
JU_ERRNO(PJError) = (JERRNO); \
|
||||
JU_ERRID(PJERROR) = __LINE__; \
|
||||
} \
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// This routine must hash string to 24..32 bits. The "goodness" of
|
||||
// the hash is not as important as its speed.
|
||||
//=======================================================================
|
||||
|
||||
// hash to no more than 32 bits
|
||||
|
||||
// extern Word_t gHmask; for hash bits experiments
|
||||
|
||||
#define JUDYHASHSTR(HVALUE,STRING,LENGTH) \
|
||||
{ \
|
||||
uint8_t *p_ = (uint8_t *)(STRING); \
|
||||
uint8_t *q_ = p_ + (LENGTH); \
|
||||
uint32_t c_ = 0; \
|
||||
for (; p_ != q_; ++p_) \
|
||||
{ \
|
||||
c_ = (c_ * 31) + *p_; \
|
||||
} \
|
||||
/* c_ &= gHmask; see above */ \
|
||||
(HVALUE) = c_; \
|
||||
}
|
||||
|
||||
// Find String of Len in JudyHS structure, return pointer to associated Value
|
||||
|
||||
PPvoid_t
|
||||
JudyHSGet(Pcvoid_t PArray, // pointer (^) to structure
|
||||
void * Str, // pointer to string
|
||||
Word_t Len // length of string
|
||||
)
|
||||
{
|
||||
uint8_t *String = (uint8_t *)Str;
|
||||
PPvoid_t PPValue; // pointer to Value
|
||||
Word_t Index; // 4[8] bytes of String
|
||||
|
||||
JLG(PPValue, PArray, Len); // find hash table for strings of Len
|
||||
if (PPValue == (PPvoid_t) NULL)
|
||||
return ((PPvoid_t) NULL); // no strings of this Len
|
||||
|
||||
// check for caller error (null pointer)
|
||||
//
|
||||
if ((String == (void *) NULL) && (Len != 0))
|
||||
return ((PPvoid_t) NULL); // avoid null-pointer dereference
|
||||
|
||||
#ifndef DONOTUSEHASH
|
||||
if (Len > WORDSIZE) // Hash table not necessary with short
|
||||
{
|
||||
uint32_t HValue; // hash of input string
|
||||
JUDYHASHSTR(HValue, String, Len); // hash to no more than 32 bits
|
||||
JLG(PPValue, *PPValue, (Word_t)HValue); // get ^ to hash bucket
|
||||
if (PPValue == (PPvoid_t) NULL)
|
||||
return ((PPvoid_t) NULL); // no entry in Hash table
|
||||
}
|
||||
#endif // DONOTUSEHASH
|
||||
|
||||
/*
|
||||
Each JudyL array decodes 4[8] bytes of the string. Since the hash
|
||||
collisions occur very infrequently, the performance is not important.
|
||||
However, even if the Hash code is not used this method still is
|
||||
significantly faster than common tree methods (AVL, Red-Black, Splay,
|
||||
b-tree, etc..). You can compare it yourself with #define DONOTUSEHASH
|
||||
1 or putting -DDONOTUSEHASH in the cc line. Use the "StringCompare.c"
|
||||
code to compare (9Dec2003 dlb).
|
||||
*/
|
||||
while (Len > WORDSIZE) // traverse tree of JudyL arrays
|
||||
{
|
||||
if (IS_PLS(*PPValue)) // ^ to JudyL array or ls_t struct?
|
||||
{
|
||||
Pls_t Pls; // ls_t struct, termination of tree
|
||||
Pls = (Pls_t) CLEAR_PLS(*PPValue); // remove flag from ^
|
||||
|
||||
// if remaining string matches, return ^ to Value, else NULL
|
||||
|
||||
if (memcmp(String, Pls->ls_String, Len) == 0)
|
||||
return ((PPvoid_t) (&(Pls->ls_Value)));
|
||||
else
|
||||
return ((PPvoid_t) NULL); // string does not match
|
||||
}
|
||||
else
|
||||
{
|
||||
COPYSTRINGtoWORD(Index, String, WORDSIZE);
|
||||
|
||||
JLG(PPValue, *PPValue, Index); // decode next 4[8] bytes
|
||||
if (PPValue == (PPvoid_t) NULL) // if NULL array, bail out
|
||||
return ((PPvoid_t) NULL); // string does not match
|
||||
|
||||
String += WORDSIZE; // advance
|
||||
Len -= WORDSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// Get remaining 1..4[8] bytes left in string
|
||||
|
||||
COPYSTRINGtoWORD(Index, String, Len);
|
||||
JLG(PPValue, *PPValue, Index); // decode last 1-4[8] bytes
|
||||
return (PPValue);
|
||||
}
|
||||
|
||||
// Add string to a tree of JudyL arrays (all lengths must be same)
|
||||
|
||||
static PPvoid_t
|
||||
insStrJudyLTree(uint8_t * String, // string to add to tree of JudyL arrays
|
||||
Word_t Len, // length of string
|
||||
PPvoid_t PPValue, // pointer to root pointer
|
||||
PJError_t PJError // for returning error info
|
||||
)
|
||||
{
|
||||
Word_t Index; // next 4[8] bytes of String
|
||||
|
||||
while (Len > WORDSIZE) // add to JudyL tree
|
||||
{
|
||||
// CASE 1, pointer is to a NULL, make a new ls_t leaf
|
||||
|
||||
if (*PPValue == (Pvoid_t)NULL)
|
||||
{
|
||||
Pls_t Pls; // memory for a ls_t
|
||||
Pls = (Pls_t) JudyMalloc(LS_WORDLEN(Len));
|
||||
if (Pls == NULL)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_NOMEM);
|
||||
return (PPJERR);
|
||||
}
|
||||
Pls->ls_Value = 0; // clear Value word
|
||||
memcpy(Pls->ls_String, String, Len); // copy to new struct
|
||||
*PPValue = (Pvoid_t)SET_PLS(Pls); // mark pointer
|
||||
return ((PPvoid_t) (&Pls->ls_Value)); // return ^ to Value
|
||||
} // no exit here
|
||||
// CASE 2: is a ls_t, free (and shorten), then decode into JudyL tree
|
||||
|
||||
if (IS_PLS(*PPValue)) // pointer to a ls_t? (leaf)
|
||||
{
|
||||
Pls_t Pls; // ^ to ls_t
|
||||
uint8_t *String0; // ^ to string in ls_t
|
||||
Word_t Index0; // 4[8] bytes in string
|
||||
Word_t FreeLen; // length of ls_t
|
||||
PPvoid_t PPsplit;
|
||||
|
||||
FreeLen = LS_WORDLEN(Len); // length of ls_t
|
||||
|
||||
Pls = (Pls_t) CLEAR_PLS(*PPValue); // demangle ^ to ls_t
|
||||
String0 = Pls->ls_String;
|
||||
if (memcmp(String, String0, Len) == 0) // check if match?
|
||||
{
|
||||
return ((PPvoid_t) (&Pls->ls_Value)); // yes, duplicate
|
||||
}
|
||||
|
||||
*PPValue = NULL; // clear ^ to ls_t and make JudyL
|
||||
|
||||
// This do loop is technically not required, saves multiple JudyFree()
|
||||
// when storing already sorted strings into structure
|
||||
|
||||
do // decode next 4[8] bytes of string
|
||||
{ // with a JudyL array
|
||||
// Note: string0 is always aligned
|
||||
|
||||
COPYSTRINGtoWORD(Index0, String0, WORDSIZE);
|
||||
String0 += WORDSIZE;
|
||||
COPYSTRINGtoWORD(Index, String, WORDSIZE);
|
||||
String += WORDSIZE;
|
||||
Len -= WORDSIZE;
|
||||
PPsplit = PPValue; // save for split below
|
||||
PPValue = JudyLIns(PPValue, Index0, PJError);
|
||||
if (PPValue == PPJERR)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, 0);
|
||||
return (PPJERR);
|
||||
}
|
||||
|
||||
} while ((Index0 == Index) && (Len > WORDSIZE));
|
||||
|
||||
// finish storing remainder of string that was in the ls_t
|
||||
|
||||
PPValue = insStrJudyLTree(String0, Len, PPValue, PJError);
|
||||
if (PPValue == PPJERR)
|
||||
{
|
||||
return (PPJERR);
|
||||
}
|
||||
// copy old Value to Value in new struct
|
||||
|
||||
*(PWord_t)PPValue = Pls->ls_Value;
|
||||
|
||||
// free the string buffer (ls_t)
|
||||
|
||||
JudyFree((Pvoid_t)Pls, FreeLen);
|
||||
PPValue = JudyLIns(PPsplit, Index, PJError);
|
||||
if (PPValue == PPJERR)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, 0);
|
||||
return (PPValue);
|
||||
}
|
||||
|
||||
// finish remainder of newly inserted string
|
||||
|
||||
PPValue = insStrJudyLTree(String, Len, PPValue, PJError);
|
||||
return (PPValue);
|
||||
} // no exit here
|
||||
// CASE 3, more JudyL arrays, decode to next tree
|
||||
|
||||
COPYSTRINGtoWORD(Index, String, WORDSIZE);
|
||||
Len -= WORDSIZE;
|
||||
String += WORDSIZE;
|
||||
|
||||
PPValue = JudyLIns(PPValue, Index, PJError); // next 4[8] bytes
|
||||
if (PPValue == PPJERR)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, 0);
|
||||
return (PPValue);
|
||||
}
|
||||
}
|
||||
// this is done outside of loop so "Len" can be an unsigned number
|
||||
|
||||
COPYSTRINGtoWORD(Index, String, Len);
|
||||
PPValue = JudyLIns(PPValue, Index, PJError); // remaining 4[8] bytes
|
||||
|
||||
return (PPValue);
|
||||
}
|
||||
|
||||
|
||||
// Insert string to JudyHS structure, return pointer to associated Value
|
||||
|
||||
PPvoid_t
|
||||
JudyHSIns(PPvoid_t PPArray, // ^ to JudyHashArray name
|
||||
void * Str, // pointer to string
|
||||
Word_t Len, // length of string
|
||||
PJError_t PJError // optional, for returning error info
|
||||
)
|
||||
{
|
||||
uint8_t * String = (uint8_t *)Str;
|
||||
PPvoid_t PPValue;
|
||||
|
||||
// string can only be NULL if Len is 0.
|
||||
|
||||
if ((String == (uint8_t *) NULL) && (Len != 0UL))
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
|
||||
return (PPJERR);
|
||||
}
|
||||
JLG(PPValue, *PPArray, Len); // JudyL hash table for strings of Len
|
||||
if (PPValue == (PPvoid_t) NULL) // make new if missing, (very rare)
|
||||
{
|
||||
PPValue = JudyLIns(PPArray, Len, PJError);
|
||||
if (PPValue == PPJERR)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, 0);
|
||||
return (PPJERR);
|
||||
}
|
||||
}
|
||||
#ifndef DONOTUSEHASH
|
||||
if (Len > WORDSIZE)
|
||||
{
|
||||
uint32_t HValue; // hash of input string
|
||||
JUDYHASHSTR(HValue, String, Len); // hash to no more than 32 bits
|
||||
PPValue = JudyLIns(PPValue, (Word_t)HValue, PJError);
|
||||
if (PPValue == PPJERR)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, 0);
|
||||
return (PPJERR);
|
||||
}
|
||||
}
|
||||
#endif // DONOTUSEHASH
|
||||
|
||||
PPValue = insStrJudyLTree(String, Len, PPValue, PJError); // add string
|
||||
return (PPValue); // ^ to Value
|
||||
}
|
||||
|
||||
// Delete string from tree of JudyL arrays (all Lens must be same)
|
||||
|
||||
static int
|
||||
delStrJudyLTree(uint8_t * String, // delete from tree of JudyL arrays
|
||||
Word_t Len, // length of string
|
||||
PPvoid_t PPValue, // ^ to hash bucket
|
||||
PJError_t PJError // for returning error info
|
||||
)
|
||||
{
|
||||
PPvoid_t PPValueN; // next pointer
|
||||
Word_t Index;
|
||||
int Ret; // -1=failed, 1=success, 2=quit del
|
||||
|
||||
if (IS_PLS(*PPValue)) // is pointer to ls_t?
|
||||
{
|
||||
Pls_t Pls;
|
||||
Pls = (Pls_t) CLEAR_PLS(*PPValue); // demangle pointer
|
||||
JudyFree((Pvoid_t)Pls, LS_WORDLEN(Len)); // free the ls_t
|
||||
|
||||
*PPValue = (Pvoid_t)NULL; // clean pointer
|
||||
return (1); // successfully deleted
|
||||
}
|
||||
|
||||
if (Len > WORDSIZE) // delete from JudyL tree, not leaf
|
||||
{
|
||||
COPYSTRINGtoWORD(Index, String, WORDSIZE); // get Index
|
||||
JLG(PPValueN, *PPValue, Index); // get pointer to next JudyL array
|
||||
|
||||
String += WORDSIZE; // advance to next 4[8] bytes
|
||||
Len -= WORDSIZE;
|
||||
|
||||
Ret = delStrJudyLTree(String, Len, PPValueN, PJError);
|
||||
if (Ret != 1) return(Ret);
|
||||
|
||||
if (*PPValueN == (PPvoid_t) NULL)
|
||||
{
|
||||
// delete JudyL element from tree
|
||||
|
||||
Ret = JudyLDel(PPValue, Index, PJError);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COPYSTRINGtoWORD(Index, String, Len); // get leaf element
|
||||
|
||||
// delete last 1-4[8] bytes from leaf element
|
||||
|
||||
Ret = JudyLDel(PPValue, Index, PJError);
|
||||
}
|
||||
return (Ret);
|
||||
}
|
||||
|
||||
// Delete string from JHS structure
|
||||
|
||||
int
|
||||
JudyHSDel(PPvoid_t PPArray, // ^ to JudyHashArray struct
|
||||
void * Str, // pointer to string
|
||||
Word_t Len, // length of string
|
||||
PJError_t PJError // optional, for returning error info
|
||||
)
|
||||
{
|
||||
uint8_t * String = (uint8_t *)Str;
|
||||
PPvoid_t PPBucket, PPHtble;
|
||||
int Ret; // return bool from Delete routine
|
||||
#ifndef DONOTUSEHASH
|
||||
uint32_t HValue = 0; // hash value of input string
|
||||
#endif // DONOTUSEHASH
|
||||
|
||||
if (PPArray == NULL)
|
||||
return (0); // no pointer, return not found
|
||||
|
||||
// This is a little slower than optimum method, but not much in new CPU
|
||||
// Verify that string is in the structure -- simplifies future assumptions
|
||||
|
||||
if (JudyHSGet(*PPArray, String, Len) == (PPvoid_t) NULL)
|
||||
return (0); // string not found, return
|
||||
|
||||
// string is in structure, so testing for absence is not necessary
|
||||
|
||||
JLG(PPHtble, *PPArray, Len); // JudyL hash table for strings of Len
|
||||
|
||||
#ifdef DONOTUSEHASH
|
||||
PPBucket = PPHtble; // simulate below code
|
||||
#else // USEHASH
|
||||
if (Len > WORDSIZE)
|
||||
{
|
||||
JUDYHASHSTR(HValue, String, Len); // hash to no more than 32 bits
|
||||
|
||||
// get pointer to hash bucket
|
||||
|
||||
JLG(PPBucket, *PPHtble, (Word_t)HValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
PPBucket = PPHtble; // no bucket to JLGet
|
||||
}
|
||||
#endif // USEHASH
|
||||
|
||||
// delete from JudyL tree
|
||||
//
|
||||
Ret = delStrJudyLTree(String, Len, PPBucket, PJError);
|
||||
if (Ret != 1)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, 0);
|
||||
return(-1);
|
||||
}
|
||||
// handle case of missing JudyL array from hash table and length table
|
||||
|
||||
if (*PPBucket == (Pvoid_t)NULL) // if JudyL tree gone
|
||||
{
|
||||
#ifndef DONOTUSEHASH
|
||||
if (Len > WORDSIZE)
|
||||
{
|
||||
// delete entry in Hash table
|
||||
|
||||
Ret = JudyLDel(PPHtble, (Word_t)HValue, PJError);
|
||||
if (Ret != 1)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, 0);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
#endif // USEHASH
|
||||
if (*PPHtble == (PPvoid_t) NULL) // if Hash table gone
|
||||
{
|
||||
// delete entry from the String length table
|
||||
|
||||
Ret = JudyLDel(PPArray, Len, PJError);
|
||||
if (Ret != 1)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, 0);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (1); // success
|
||||
}
|
||||
|
||||
static Word_t
|
||||
delJudyLTree(PPvoid_t PPValue, // ^ to JudyL root pointer
|
||||
Word_t Len, // length of string
|
||||
PJError_t PJError) // for returning error info
|
||||
{
|
||||
Word_t bytes_freed = 0; // bytes freed at point
|
||||
Word_t bytes_total = 0; // accumulated bytes freed
|
||||
PPvoid_t PPValueN;
|
||||
|
||||
// Pointer is to another tree of JudyL arrays or ls_t struct
|
||||
|
||||
if (Len > WORDSIZE) // more depth to tree
|
||||
{
|
||||
Word_t NEntry;
|
||||
|
||||
// Pointer is to a ls_t struct
|
||||
|
||||
if (IS_PLS(*PPValue))
|
||||
{
|
||||
Pls_t Pls;
|
||||
Word_t freewords;
|
||||
|
||||
freewords = LS_WORDLEN(Len); // calculate length
|
||||
Pls = (Pls_t)CLEAR_PLS(*PPValue); // demangle pointer
|
||||
|
||||
// *PPValue = (Pvoid_t)NULL; // clean pointer
|
||||
JudyFree((Pvoid_t)Pls, freewords); // free the ls_t
|
||||
|
||||
return(freewords * WORDSIZE);
|
||||
}
|
||||
// else
|
||||
// Walk all the entrys in the JudyL array
|
||||
|
||||
NEntry = 0; // start at beginning
|
||||
for (PPValueN = JudyLFirst(*PPValue, &NEntry, PJError);
|
||||
(PPValueN != (PPvoid_t) NULL) && (PPValueN != PPJERR);
|
||||
PPValueN = JudyLNext(*PPValue, &NEntry, PJError))
|
||||
{
|
||||
// recurse to the next level in the tree of arrays
|
||||
|
||||
bytes_freed = delJudyLTree(PPValueN, Len - WORDSIZE, PJError);
|
||||
if (bytes_freed == JERR) return(JERR);
|
||||
bytes_total += bytes_freed;
|
||||
}
|
||||
if (PPValueN == PPJERR) return(JERR);
|
||||
|
||||
// now free this JudyL array
|
||||
|
||||
bytes_freed = JudyLFreeArray(PPValue, PJError);
|
||||
if (bytes_freed == JERR) return(JERR);
|
||||
bytes_total += bytes_freed;
|
||||
|
||||
return(bytes_total); // return amount freed
|
||||
}
|
||||
// else
|
||||
|
||||
// Pointer to simple JudyL array
|
||||
|
||||
bytes_freed = JudyLFreeArray(PPValue, PJError);
|
||||
|
||||
return(bytes_freed);
|
||||
}
|
||||
|
||||
|
||||
Word_t // bytes freed
|
||||
JudyHSFreeArray(PPvoid_t PPArray, // ^ to JudyHashArray struct
|
||||
PJError_t PJError // optional, for returning error info
|
||||
)
|
||||
{
|
||||
Word_t Len; // start at beginning
|
||||
Word_t bytes_freed; // bytes freed at this level.
|
||||
Word_t bytes_total; // bytes total at all levels.
|
||||
PPvoid_t PPHtble;
|
||||
|
||||
if (PPArray == NULL)
|
||||
return (0); // no pointer, return none
|
||||
|
||||
// Walk the string length table for subsidary hash structs
|
||||
// NOTE: This is necessary to determine the depth of the tree
|
||||
|
||||
bytes_freed = 0;
|
||||
bytes_total = 0;
|
||||
Len = 0; // walk to length table
|
||||
|
||||
for (PPHtble = JudyLFirst(*PPArray, &Len, PJError);
|
||||
(PPHtble != (PPvoid_t) NULL) && (PPHtble != PPJERR);
|
||||
PPHtble = JudyLNext(*PPArray, &Len, PJError))
|
||||
{
|
||||
PPvoid_t PPValueH;
|
||||
|
||||
#ifndef DONOTUSEHASH
|
||||
if (Len > WORDSIZE)
|
||||
{
|
||||
Word_t HEntry = 0; // walk the hash tables
|
||||
|
||||
for (PPValueH = JudyLFirst(*PPHtble, &HEntry, PJError);
|
||||
(PPValueH != (PPvoid_t) NULL) && (PPValueH != PPJERR);
|
||||
PPValueH = JudyLNext(*PPHtble, &HEntry, PJError))
|
||||
{
|
||||
bytes_freed = delJudyLTree(PPValueH, Len, PJError);
|
||||
if (bytes_freed == JERR) return(JERR);
|
||||
bytes_total += bytes_freed;
|
||||
}
|
||||
|
||||
if (PPValueH == PPJERR) return(JERR);
|
||||
|
||||
// free the Hash table for this length of string
|
||||
|
||||
bytes_freed = JudyLFreeArray(PPHtble, PJError);
|
||||
if (bytes_freed == JERR) return(JERR);
|
||||
bytes_total += bytes_freed;
|
||||
}
|
||||
else
|
||||
#endif // DONOTUSEHASH
|
||||
{
|
||||
PPValueH = PPHtble; // simulate hash table
|
||||
|
||||
bytes_freed = delJudyLTree(PPValueH, Len, PJError);
|
||||
if (bytes_freed == JERR) return(JERR);
|
||||
bytes_total += bytes_freed;
|
||||
}
|
||||
}
|
||||
if (PPHtble == PPJERR) return(JERR);
|
||||
|
||||
// free the length table
|
||||
|
||||
bytes_freed = JudyLFreeArray(PPArray, PJError);
|
||||
if (bytes_freed == JERR) return(JERR);
|
||||
|
||||
bytes_total += bytes_freed;
|
||||
|
||||
return(bytes_total); // return bytes freed
|
||||
}
|
505
libnetdata/libjudy/src/JudyL/JudyL.h
Normal file
505
libnetdata/libjudy/src/JudyL/JudyL.h
Normal file
|
@ -0,0 +1,505 @@
|
|||
#ifndef _JUDYL_INCLUDED
|
||||
#define _JUDYL_INCLUDED
|
||||
// _________________
|
||||
//
|
||||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.41 $ $Source: /judy/src/JudyL/JudyL.h $
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDYL -- SMALL/LARGE AND/OR CLUSTERED/SPARSE ARRAYS
|
||||
//
|
||||
// -by-
|
||||
//
|
||||
// Douglas L. Baskins
|
||||
// doug@sourcejudy.com
|
||||
//
|
||||
// Judy arrays are designed to be used instead of arrays. The performance
|
||||
// suggests the reason why Judy arrays are thought of as arrays, instead of
|
||||
// trees. They are remarkably memory efficient at all populations.
|
||||
// Implemented as a hybrid digital tree (but really a state machine, see
|
||||
// below), Judy arrays feature fast insert/retrievals, fast near neighbor
|
||||
// searching, and contain a population tree for extremely fast ordinal related
|
||||
// retrievals.
|
||||
//
|
||||
// CONVENTIONS:
|
||||
//
|
||||
// - The comments here refer to 32-bit [64-bit] systems.
|
||||
//
|
||||
// - BranchL, LeafL refer to linear branches and leaves (small populations),
|
||||
// except LeafL does not actually appear as such; rather, Leaf1..3 [Leaf1..7]
|
||||
// is used to represent leaf Index sizes, and LeafW refers to a Leaf with
|
||||
// full (Long) word Indexes, which is also a type of linear leaf. Note that
|
||||
// root-level LeafW (Leaf4 [Leaf8]) leaves are called LEAFW.
|
||||
//
|
||||
// - BranchB, LeafB1 refer to bitmap branches and leaves (intermediate
|
||||
// populations).
|
||||
//
|
||||
// - BranchU refers to uncompressed branches. An uncompressed branch has 256
|
||||
// JPs, some of which could be null. Note: All leaves are compressed (and
|
||||
// sorted), or else an expanse is full (FullPopu), so there is no LeafU
|
||||
// equivalent to BranchU.
|
||||
//
|
||||
// - "Popu" is short for "Population".
|
||||
// - "Pop1" refers to actual population (base 1).
|
||||
// - "Pop0" refers to Pop1 - 1 (base 0), the way populations are stored in data
|
||||
// structures.
|
||||
//
|
||||
// - Branches and Leaves are both named by the number of bytes in their Pop0
|
||||
// field. In the case of Leaves, the same number applies to the Index sizes.
|
||||
//
|
||||
// - The representation of many numbers as hex is a relatively safe and
|
||||
// portable way to get desired bitpatterns as unsigned longs.
|
||||
//
|
||||
// - Some preprocessors cant handle single apostrophe characters within
|
||||
// #ifndef code, so here, delete all instead.
|
||||
|
||||
|
||||
#include "JudyPrivate.h" // includes Judy.h in turn.
|
||||
#include "JudyPrivateBranch.h" // support for branches.
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDYL ROOT POINTER (JRP) AND JUDYL POINTER (JP) TYPE FIELDS
|
||||
// ****************************************************************************
|
||||
|
||||
typedef enum // uint8_t -- but C does not support this type of enum.
|
||||
{
|
||||
|
||||
// JP NULL TYPES:
|
||||
//
|
||||
// There is a series of cJL_JPNULL* Types because each one pre-records a
|
||||
// different Index Size for when the first Index is inserted in the previously
|
||||
// null JP. They must start >= 8 (three bits).
|
||||
//
|
||||
// Note: These Types must be in sequential order for doing relative
|
||||
// calculations between them.
|
||||
|
||||
cJL_JPNULL1 = 1,
|
||||
// Index Size 1[1] byte when 1 Index inserted.
|
||||
cJL_JPNULL2, // Index Size 2[2] bytes when 1 Index inserted.
|
||||
cJL_JPNULL3, // Index Size 3[3] bytes when 1 Index inserted.
|
||||
|
||||
#ifndef JU_64BIT
|
||||
#define cJL_JPNULLMAX cJL_JPNULL3
|
||||
#else
|
||||
cJL_JPNULL4, // Index Size 4[4] bytes when 1 Index inserted.
|
||||
cJL_JPNULL5, // Index Size 5[5] bytes when 1 Index inserted.
|
||||
cJL_JPNULL6, // Index Size 6[6] bytes when 1 Index inserted.
|
||||
cJL_JPNULL7, // Index Size 7[7] bytes when 1 Index inserted.
|
||||
#define cJL_JPNULLMAX cJL_JPNULL7
|
||||
#endif
|
||||
|
||||
|
||||
// JP BRANCH TYPES:
|
||||
//
|
||||
// Note: There are no state-1 branches; only leaves reside at state 1.
|
||||
|
||||
// Linear branches:
|
||||
//
|
||||
// Note: These Types must be in sequential order for doing relative
|
||||
// calculations between them.
|
||||
|
||||
cJL_JPBRANCH_L2, // 2[2] bytes Pop0, 1[5] bytes Dcd.
|
||||
cJL_JPBRANCH_L3, // 3[3] bytes Pop0, 0[4] bytes Dcd.
|
||||
|
||||
#ifdef JU_64BIT
|
||||
cJL_JPBRANCH_L4, // [4] bytes Pop0, [3] bytes Dcd.
|
||||
cJL_JPBRANCH_L5, // [5] bytes Pop0, [2] bytes Dcd.
|
||||
cJL_JPBRANCH_L6, // [6] bytes Pop0, [1] byte Dcd.
|
||||
cJL_JPBRANCH_L7, // [7] bytes Pop0, [0] bytes Dcd.
|
||||
#endif
|
||||
|
||||
cJL_JPBRANCH_L, // note: DcdPopO field not used.
|
||||
|
||||
// Bitmap branches:
|
||||
//
|
||||
// Note: These Types must be in sequential order for doing relative
|
||||
// calculations between them.
|
||||
|
||||
cJL_JPBRANCH_B2, // 2[2] bytes Pop0, 1[5] bytes Dcd.
|
||||
cJL_JPBRANCH_B3, // 3[3] bytes Pop0, 0[4] bytes Dcd.
|
||||
|
||||
#ifdef JU_64BIT
|
||||
cJL_JPBRANCH_B4, // [4] bytes Pop0, [3] bytes Dcd.
|
||||
cJL_JPBRANCH_B5, // [5] bytes Pop0, [2] bytes Dcd.
|
||||
cJL_JPBRANCH_B6, // [6] bytes Pop0, [1] byte Dcd.
|
||||
cJL_JPBRANCH_B7, // [7] bytes Pop0, [0] bytes Dcd.
|
||||
#endif
|
||||
|
||||
cJL_JPBRANCH_B, // note: DcdPopO field not used.
|
||||
|
||||
// Uncompressed branches:
|
||||
//
|
||||
// Note: These Types must be in sequential order for doing relative
|
||||
// calculations between them.
|
||||
|
||||
cJL_JPBRANCH_U2, // 2[2] bytes Pop0, 1[5] bytes Dcd.
|
||||
cJL_JPBRANCH_U3, // 3[3] bytes Pop0, 0[4] bytes Dcd.
|
||||
|
||||
#ifdef JU_64BIT
|
||||
cJL_JPBRANCH_U4, // [4] bytes Pop0, [3] bytes Dcd.
|
||||
cJL_JPBRANCH_U5, // [5] bytes Pop0, [2] bytes Dcd.
|
||||
cJL_JPBRANCH_U6, // [6] bytes Pop0, [1] byte Dcd.
|
||||
cJL_JPBRANCH_U7, // [7] bytes Pop0, [0] bytes Dcd.
|
||||
#endif
|
||||
|
||||
cJL_JPBRANCH_U, // note: DcdPopO field not used.
|
||||
|
||||
|
||||
// JP LEAF TYPES:
|
||||
|
||||
// Linear leaves:
|
||||
//
|
||||
// Note: These Types must be in sequential order for doing relative
|
||||
// calculations between them.
|
||||
//
|
||||
// Note: There is no full-word (4-byte [8-byte]) Index leaf under a JP because
|
||||
// non-root-state leaves only occur under branches that decode at least one
|
||||
// byte. Full-word, root-state leaves are under a JRP, not a JP. However, in
|
||||
// the code a "fake" JP can be created temporarily above a root-state leaf.
|
||||
|
||||
cJL_JPLEAF1, // 1[1] byte Pop0, 2 bytes Dcd.
|
||||
cJL_JPLEAF2, // 2[2] bytes Pop0, 1[5] bytes Dcd.
|
||||
cJL_JPLEAF3, // 3[3] bytes Pop0, 0[4] bytes Dcd.
|
||||
|
||||
#ifdef JU_64BIT
|
||||
cJL_JPLEAF4, // [4] bytes Pop0, [3] bytes Dcd.
|
||||
cJL_JPLEAF5, // [5] bytes Pop0, [2] bytes Dcd.
|
||||
cJL_JPLEAF6, // [6] bytes Pop0, [1] byte Dcd.
|
||||
cJL_JPLEAF7, // [7] bytes Pop0, [0] bytes Dcd.
|
||||
#endif
|
||||
|
||||
// Bitmap leaf; Index Size == 1:
|
||||
//
|
||||
// Note: These are currently only supported at state 1. At other states the
|
||||
// bitmap would grow from 256 to 256^2, 256^3, ... bits, which would not be
|
||||
// efficient..
|
||||
|
||||
cJL_JPLEAF_B1, // 1[1] byte Pop0, 2[6] bytes Dcd.
|
||||
|
||||
// Full population; Index Size == 1 virtual leaf:
|
||||
//
|
||||
// Note: JudyL has no cJL_JPFULLPOPU1 equivalent to cJ1_JPFULLPOPU1, because
|
||||
// in the JudyL case this could result in a values-only leaf of up to 256 words
|
||||
// (value areas) that would be slow to insert/delete.
|
||||
|
||||
|
||||
// JP IMMEDIATES; leaves (Indexes) stored inside a JP:
|
||||
//
|
||||
// The second numeric suffix is the Pop1 for each type. As the Index Size
|
||||
// increases, the maximum possible population decreases.
|
||||
//
|
||||
// Note: These Types must be in sequential order in each group (Index Size),
|
||||
// and the groups in correct order too, for doing relative calculations between
|
||||
// them. For example, since these Types enumerate the Pop1 values (unlike
|
||||
// other JP Types where there is a Pop0 value in the JP), the maximum Pop1 for
|
||||
// each Index Size is computable.
|
||||
//
|
||||
// All enums equal or above this point are cJL_JPIMMEDs.
|
||||
|
||||
cJL_JPIMMED_1_01, // Index Size = 1, Pop1 = 1.
|
||||
cJL_JPIMMED_2_01, // Index Size = 2, Pop1 = 1.
|
||||
cJL_JPIMMED_3_01, // Index Size = 3, Pop1 = 1.
|
||||
|
||||
#ifdef JU_64BIT
|
||||
cJL_JPIMMED_4_01, // Index Size = 4, Pop1 = 1.
|
||||
cJL_JPIMMED_5_01, // Index Size = 5, Pop1 = 1.
|
||||
cJL_JPIMMED_6_01, // Index Size = 6, Pop1 = 1.
|
||||
cJL_JPIMMED_7_01, // Index Size = 7, Pop1 = 1.
|
||||
#endif
|
||||
|
||||
cJL_JPIMMED_1_02, // Index Size = 1, Pop1 = 2.
|
||||
cJL_JPIMMED_1_03, // Index Size = 1, Pop1 = 3.
|
||||
|
||||
#ifdef JU_64BIT
|
||||
cJL_JPIMMED_1_04, // Index Size = 1, Pop1 = 4.
|
||||
cJL_JPIMMED_1_05, // Index Size = 1, Pop1 = 5.
|
||||
cJL_JPIMMED_1_06, // Index Size = 1, Pop1 = 6.
|
||||
cJL_JPIMMED_1_07, // Index Size = 1, Pop1 = 7.
|
||||
|
||||
cJL_JPIMMED_2_02, // Index Size = 2, Pop1 = 2.
|
||||
cJL_JPIMMED_2_03, // Index Size = 2, Pop1 = 3.
|
||||
|
||||
cJL_JPIMMED_3_02, // Index Size = 3, Pop1 = 2.
|
||||
#endif
|
||||
|
||||
// This special Type is merely a sentinel for doing relative calculations.
|
||||
// This value should not be used in switch statements (to avoid allocating code
|
||||
// for it), which is also why it appears at the end of the enum list.
|
||||
|
||||
cJL_JPIMMED_CAP
|
||||
|
||||
} jpL_Type_t;
|
||||
|
||||
|
||||
// RELATED VALUES:
|
||||
|
||||
// Index Size (state) for leaf JP, and JP type based on Index Size (state):
|
||||
|
||||
#define JL_LEAFINDEXSIZE(jpType) ((jpType) - cJL_JPLEAF1 + 1)
|
||||
#define JL_LEAFTYPE(IndexSize) ((IndexSize) + cJL_JPLEAF1 - 1)
|
||||
|
||||
|
||||
// MAXIMUM POPULATIONS OF LINEAR LEAVES:
|
||||
|
||||
#ifndef JU_64BIT // 32-bit
|
||||
|
||||
#define J_L_MAXB (sizeof(Word_t) * 64)
|
||||
#define ALLOCSIZES { 3, 5, 7, 11, 15, 23, 32, 47, 64, TERMINATOR } // in words.
|
||||
#define cJL_LEAF1_MAXWORDS (32) // max Leaf1 size in words.
|
||||
|
||||
// Note: cJL_LEAF1_MAXPOP1 is chosen such that the index portion is less than
|
||||
// 32 bytes -- the number of bytes the index takes in a bitmap leaf.
|
||||
|
||||
#define cJL_LEAF1_MAXPOP1 \
|
||||
((cJL_LEAF1_MAXWORDS * cJU_BYTESPERWORD)/(1 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAF2_MAXPOP1 (J_L_MAXB / (2 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAF3_MAXPOP1 (J_L_MAXB / (3 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAFW_MAXPOP1 \
|
||||
((J_L_MAXB - cJU_BYTESPERWORD) / (2 * cJU_BYTESPERWORD))
|
||||
|
||||
#else // 64-bit
|
||||
|
||||
#define J_L_MAXB (sizeof(Word_t) * 64)
|
||||
#define ALLOCSIZES { 3, 5, 7, 11, 15, 23, 32, 47, 64, TERMINATOR } // in words.
|
||||
#define cJL_LEAF1_MAXWORDS (15) // max Leaf1 size in words.
|
||||
|
||||
#define cJL_LEAF1_MAXPOP1 \
|
||||
((cJL_LEAF1_MAXWORDS * cJU_BYTESPERWORD)/(1 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAF2_MAXPOP1 (J_L_MAXB / (2 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAF3_MAXPOP1 (J_L_MAXB / (3 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAF4_MAXPOP1 (J_L_MAXB / (4 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAF5_MAXPOP1 (J_L_MAXB / (5 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAF6_MAXPOP1 (J_L_MAXB / (6 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAF7_MAXPOP1 (J_L_MAXB / (7 + cJU_BYTESPERWORD))
|
||||
#define cJL_LEAFW_MAXPOP1 \
|
||||
((J_L_MAXB - cJU_BYTESPERWORD) / (2 * cJU_BYTESPERWORD))
|
||||
|
||||
#endif // 64-bit
|
||||
|
||||
|
||||
// MAXIMUM POPULATIONS OF IMMEDIATE JPs:
|
||||
//
|
||||
// These specify the maximum Population of immediate JPs with various Index
|
||||
// Sizes (== sizes of remaining undecoded Index bits). Since the JP Types enum
|
||||
// already lists all the immediates in order by state and size, calculate these
|
||||
// values from it to avoid redundancy.
|
||||
|
||||
#define cJL_IMMED1_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 1) // 3 [7].
|
||||
#define cJL_IMMED2_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 2) // 1 [3].
|
||||
#define cJL_IMMED3_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 3) // 1 [2].
|
||||
|
||||
#ifdef JU_64BIT
|
||||
#define cJL_IMMED4_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 4) // [1].
|
||||
#define cJL_IMMED5_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 5) // [1].
|
||||
#define cJL_IMMED6_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 6) // [1].
|
||||
#define cJL_IMMED7_MAXPOP1 ((cJU_BYTESPERWORD - 1) / 7) // [1].
|
||||
#endif
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// JUDYL LEAF BITMAP (JLLB) SUPPORT
|
||||
// ****************************************************************************
|
||||
//
|
||||
// Assemble bitmap leaves out of smaller units that put bitmap subexpanses
|
||||
// close to their associated pointers. Why not just use a bitmap followed by a
|
||||
// series of pointers? (See 4.27.) Turns out this wastes a cache fill on
|
||||
// systems with smaller cache lines than the assumed value cJU_WORDSPERCL.
|
||||
|
||||
#define JL_JLB_BITMAP(Pjlb, Subexp) ((Pjlb)->jLlb_jLlbs[Subexp].jLlbs_Bitmap)
|
||||
#define JL_JLB_PVALUE(Pjlb, Subexp) ((Pjlb)->jLlb_jLlbs[Subexp].jLlbs_PValue)
|
||||
|
||||
typedef struct J__UDYL_LEAF_BITMAP_SUBEXPANSE
|
||||
{
|
||||
BITMAPL_t jLlbs_Bitmap;
|
||||
Pjv_t jLlbs_PValue;
|
||||
|
||||
} jLlbs_t;
|
||||
|
||||
typedef struct J__UDYL_LEAF_BITMAP
|
||||
{
|
||||
jLlbs_t jLlb_jLlbs[cJU_NUMSUBEXPL];
|
||||
|
||||
} jLlb_t, * PjLlb_t;
|
||||
|
||||
// Words per bitmap leaf:
|
||||
|
||||
#define cJL_WORDSPERLEAFB1 (sizeof(jLlb_t) / cJU_BYTESPERWORD)
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// MEMORY ALLOCATION SUPPORT
|
||||
// ****************************************************************************
|
||||
|
||||
// ARRAY-GLOBAL INFORMATION:
|
||||
//
|
||||
// At the cost of an occasional additional cache fill, this object, which is
|
||||
// pointed at by a JRP and in turn points to a JP_BRANCH*, carries array-global
|
||||
// information about a JudyL array that has sufficient population to amortize
|
||||
// the cost. The jpm_Pop0 field prevents having to add up the total population
|
||||
// for the array in insert, delete, and count code. The jpm_JP field prevents
|
||||
// having to build a fake JP for entry to a state machine; however, the
|
||||
// jp_DcdPopO field in jpm_JP, being one byte too small, is not used.
|
||||
//
|
||||
// Note: Struct fields are ordered to keep "hot" data in the first 8 words
|
||||
// (see left-margin comments) for machines with 8-word cache lines, and to keep
|
||||
// sub-word fields together for efficient packing.
|
||||
|
||||
typedef struct J_UDYL_POPULATION_AND_MEMORY
|
||||
{
|
||||
/* 1 */ Word_t jpm_Pop0; // total population-1 in array.
|
||||
/* 2 */ jp_t jpm_JP; // JP to first branch; see above.
|
||||
/* 4 */ Word_t jpm_LastUPop0; // last jpm_Pop0 when convert to BranchU
|
||||
/* 7 */ Pjv_t jpm_PValue; // pointer to value to return.
|
||||
// Note: Field names match PJError_t for convenience in macros:
|
||||
/* 8 */ char je_Errno; // one of the enums in Judy.h.
|
||||
/* 8/9 */ int je_ErrID; // often an internal source line number.
|
||||
/* 9/10 */ Word_t jpm_TotalMemWords; // words allocated in array.
|
||||
} jLpm_t, *PjLpm_t;
|
||||
|
||||
|
||||
// TABLES FOR DETERMINING IF LEAVES HAVE ROOM TO GROW:
|
||||
//
|
||||
// These tables indicate if a given memory chunk can support growth of a given
|
||||
// object into wasted (rounded-up) memory in the chunk. Note: This violates
|
||||
// the hiddenness of the JudyMalloc code.
|
||||
|
||||
extern const uint8_t j__L_Leaf1PopToWords[cJL_LEAF1_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf2PopToWords[cJL_LEAF2_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf3PopToWords[cJL_LEAF3_MAXPOP1 + 1];
|
||||
#ifdef JU_64BIT
|
||||
extern const uint8_t j__L_Leaf4PopToWords[cJL_LEAF4_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf5PopToWords[cJL_LEAF5_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf6PopToWords[cJL_LEAF6_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf7PopToWords[cJL_LEAF7_MAXPOP1 + 1];
|
||||
#endif
|
||||
extern const uint8_t j__L_LeafWPopToWords[cJL_LEAFW_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_LeafVPopToWords[];
|
||||
|
||||
// These tables indicate where value areas start:
|
||||
|
||||
extern const uint8_t j__L_Leaf1Offset [cJL_LEAF1_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf2Offset [cJL_LEAF2_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf3Offset [cJL_LEAF3_MAXPOP1 + 1];
|
||||
#ifdef JU_64BIT
|
||||
extern const uint8_t j__L_Leaf4Offset [cJL_LEAF4_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf5Offset [cJL_LEAF5_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf6Offset [cJL_LEAF6_MAXPOP1 + 1];
|
||||
extern const uint8_t j__L_Leaf7Offset [cJL_LEAF7_MAXPOP1 + 1];
|
||||
#endif
|
||||
extern const uint8_t j__L_LeafWOffset [cJL_LEAFW_MAXPOP1 + 1];
|
||||
|
||||
// Also define macros to hide the details in the code using these tables.
|
||||
|
||||
#define JL_LEAF1GROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJL_LEAF1_MAXPOP1, j__L_Leaf1PopToWords)
|
||||
#define JL_LEAF2GROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJL_LEAF2_MAXPOP1, j__L_Leaf2PopToWords)
|
||||
#define JL_LEAF3GROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJL_LEAF3_MAXPOP1, j__L_Leaf3PopToWords)
|
||||
#ifdef JU_64BIT
|
||||
#define JL_LEAF4GROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJL_LEAF4_MAXPOP1, j__L_Leaf4PopToWords)
|
||||
#define JL_LEAF5GROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJL_LEAF5_MAXPOP1, j__L_Leaf5PopToWords)
|
||||
#define JL_LEAF6GROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJL_LEAF6_MAXPOP1, j__L_Leaf6PopToWords)
|
||||
#define JL_LEAF7GROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJL_LEAF7_MAXPOP1, j__L_Leaf7PopToWords)
|
||||
#endif
|
||||
#define JL_LEAFWGROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJL_LEAFW_MAXPOP1, j__L_LeafWPopToWords)
|
||||
#define JL_LEAFVGROWINPLACE(Pop1) \
|
||||
J__U_GROWCK(Pop1, cJU_BITSPERSUBEXPL, j__L_LeafVPopToWords)
|
||||
|
||||
#define JL_LEAF1VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf1Offset[Pop1])
|
||||
#define JL_LEAF2VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf2Offset[Pop1])
|
||||
#define JL_LEAF3VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf3Offset[Pop1])
|
||||
#ifdef JU_64BIT
|
||||
#define JL_LEAF4VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf4Offset[Pop1])
|
||||
#define JL_LEAF5VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf5Offset[Pop1])
|
||||
#define JL_LEAF6VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf6Offset[Pop1])
|
||||
#define JL_LEAF7VALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_Leaf7Offset[Pop1])
|
||||
#endif
|
||||
#define JL_LEAFWVALUEAREA(Pjv,Pop1) (((PWord_t)(Pjv)) + j__L_LeafWOffset[Pop1])
|
||||
|
||||
#define JL_LEAF1POPTOWORDS(Pop1) (j__L_Leaf1PopToWords[Pop1])
|
||||
#define JL_LEAF2POPTOWORDS(Pop1) (j__L_Leaf2PopToWords[Pop1])
|
||||
#define JL_LEAF3POPTOWORDS(Pop1) (j__L_Leaf3PopToWords[Pop1])
|
||||
#ifdef JU_64BIT
|
||||
#define JL_LEAF4POPTOWORDS(Pop1) (j__L_Leaf4PopToWords[Pop1])
|
||||
#define JL_LEAF5POPTOWORDS(Pop1) (j__L_Leaf5PopToWords[Pop1])
|
||||
#define JL_LEAF6POPTOWORDS(Pop1) (j__L_Leaf6PopToWords[Pop1])
|
||||
#define JL_LEAF7POPTOWORDS(Pop1) (j__L_Leaf7PopToWords[Pop1])
|
||||
#endif
|
||||
#define JL_LEAFWPOPTOWORDS(Pop1) (j__L_LeafWPopToWords[Pop1])
|
||||
#define JL_LEAFVPOPTOWORDS(Pop1) (j__L_LeafVPopToWords[Pop1])
|
||||
|
||||
|
||||
// FUNCTIONS TO ALLOCATE OBJECTS:
|
||||
|
||||
PjLpm_t j__udyLAllocJLPM(void); // constant size.
|
||||
|
||||
Pjbl_t j__udyLAllocJBL( PjLpm_t); // constant size.
|
||||
Pjbb_t j__udyLAllocJBB( PjLpm_t); // constant size.
|
||||
Pjp_t j__udyLAllocJBBJP(Word_t, PjLpm_t);
|
||||
Pjbu_t j__udyLAllocJBU( PjLpm_t); // constant size.
|
||||
|
||||
Pjll_t j__udyLAllocJLL1( Word_t, PjLpm_t);
|
||||
Pjll_t j__udyLAllocJLL2( Word_t, PjLpm_t);
|
||||
Pjll_t j__udyLAllocJLL3( Word_t, PjLpm_t);
|
||||
|
||||
#ifdef JU_64BIT
|
||||
Pjll_t j__udyLAllocJLL4( Word_t, PjLpm_t);
|
||||
Pjll_t j__udyLAllocJLL5( Word_t, PjLpm_t);
|
||||
Pjll_t j__udyLAllocJLL6( Word_t, PjLpm_t);
|
||||
Pjll_t j__udyLAllocJLL7( Word_t, PjLpm_t);
|
||||
#endif
|
||||
|
||||
Pjlw_t j__udyLAllocJLW( Word_t ); // no PjLpm_t needed.
|
||||
PjLlb_t j__udyLAllocJLB1( PjLpm_t); // constant size.
|
||||
Pjv_t j__udyLAllocJV( Word_t, PjLpm_t);
|
||||
|
||||
|
||||
// FUNCTIONS TO FREE OBJECTS:
|
||||
|
||||
void j__udyLFreeJLPM( PjLpm_t, PjLpm_t); // constant size.
|
||||
|
||||
void j__udyLFreeJBL( Pjbl_t, PjLpm_t); // constant size.
|
||||
void j__udyLFreeJBB( Pjbb_t, PjLpm_t); // constant size.
|
||||
void j__udyLFreeJBBJP(Pjp_t, Word_t, PjLpm_t);
|
||||
void j__udyLFreeJBU( Pjbu_t, PjLpm_t); // constant size.
|
||||
|
||||
void j__udyLFreeJLL1( Pjll_t, Word_t, PjLpm_t);
|
||||
void j__udyLFreeJLL2( Pjll_t, Word_t, PjLpm_t);
|
||||
void j__udyLFreeJLL3( Pjll_t, Word_t, PjLpm_t);
|
||||
|
||||
#ifdef JU_64BIT
|
||||
void j__udyLFreeJLL4( Pjll_t, Word_t, PjLpm_t);
|
||||
void j__udyLFreeJLL5( Pjll_t, Word_t, PjLpm_t);
|
||||
void j__udyLFreeJLL6( Pjll_t, Word_t, PjLpm_t);
|
||||
void j__udyLFreeJLL7( Pjll_t, Word_t, PjLpm_t);
|
||||
#endif
|
||||
|
||||
void j__udyLFreeJLW( Pjlw_t, Word_t, PjLpm_t);
|
||||
void j__udyLFreeJLB1( PjLlb_t, PjLpm_t); // constant size.
|
||||
void j__udyLFreeJV( Pjv_t, Word_t, PjLpm_t);
|
||||
void j__udyLFreeSM( Pjp_t, PjLpm_t); // everything below Pjp.
|
||||
|
||||
#endif // ! _JUDYL_INCLUDED
|
954
libnetdata/libjudy/src/JudyL/JudyLByCount.c
Normal file
954
libnetdata/libjudy/src/JudyL/JudyLByCount.c
Normal file
|
@ -0,0 +1,954 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.28 $ $Source: /judy/src/JudyCommon/JudyByCount.c $
|
||||
//
|
||||
// Judy*ByCount() function for Judy1 and JudyL.
|
||||
// Compile with one of -DJUDY1 or -DJUDYL.
|
||||
//
|
||||
// Compile with -DNOSMARTJBB, -DNOSMARTJBU, and/or -DNOSMARTJLB to build a
|
||||
// version with cache line optimizations deleted, for testing.
|
||||
//
|
||||
// Judy*ByCount() is a conceptual although not literal inverse of Judy*Count().
|
||||
// Judy*Count() takes a pair of Indexes, and allows finding the ordinal of a
|
||||
// given Index (that is, its position in the list of valid indexes from the
|
||||
// beginning) as a degenerate case, because in general the count between two
|
||||
// Indexes, inclusive, is not always just the difference in their ordinals.
|
||||
// However, it suffices for Judy*ByCount() to simply be an ordinal-to-Index
|
||||
// mapper.
|
||||
//
|
||||
// Note: Like Judy*Count(), this code must "count sideways" in branches, which
|
||||
// can result in a lot of cache line fills. However, unlike Judy*Count(), this
|
||||
// code does not receive a specific Index, hence digit, where to start in each
|
||||
// branch, so it cant accurately calculate cache line fills required in each
|
||||
// direction. The best it can do is an approximation based on the total
|
||||
// population of the expanse (pop1 from Pjp) and the ordinal of the target
|
||||
// Index (see SETOFFSET()) within the expanse.
|
||||
//
|
||||
// Compile with -DSMARTMETRICS to obtain global variables containing smart
|
||||
// cache line metrics. Note: Dont turn this on simultaneously for this file
|
||||
// and JudyCount.c because they export the same globals.
|
||||
// ****************************************************************************
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
#include "JudyPrivate1L.h"
|
||||
|
||||
// These are imported from JudyCount.c:
|
||||
//
|
||||
// TBD: Should this be in common code? Exported from a header file?
|
||||
|
||||
#ifdef JUDY1
|
||||
extern Word_t j__udy1JPPop1(const Pjp_t Pjp);
|
||||
#define j__udyJPPop1 j__udy1JPPop1
|
||||
#else
|
||||
extern Word_t j__udyLJPPop1(const Pjp_t Pjp);
|
||||
#define j__udyJPPop1 j__udyLJPPop1
|
||||
#endif
|
||||
|
||||
// Avoid duplicate symbols since this file is multi-compiled:
|
||||
|
||||
#ifdef SMARTMETRICS
|
||||
#ifdef JUDY1
|
||||
Word_t jbb_upward = 0; // counts of directions taken:
|
||||
Word_t jbb_downward = 0;
|
||||
Word_t jbu_upward = 0;
|
||||
Word_t jbu_downward = 0;
|
||||
Word_t jlb_upward = 0;
|
||||
Word_t jlb_downward = 0;
|
||||
#else
|
||||
extern Word_t jbb_upward;
|
||||
extern Word_t jbb_downward;
|
||||
extern Word_t jbu_upward;
|
||||
extern Word_t jbu_downward;
|
||||
extern Word_t jlb_upward;
|
||||
extern Word_t jlb_downward;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y 1 B Y C O U N T
|
||||
// J U D Y L B Y C O U N T
|
||||
//
|
||||
// See the manual entry.
|
||||
|
||||
#ifdef JUDY1
|
||||
FUNCTION int Judy1ByCount
|
||||
#else
|
||||
FUNCTION PPvoid_t JudyLByCount
|
||||
#endif
|
||||
(
|
||||
Pcvoid_t PArray, // root pointer to first branch/leaf in SM.
|
||||
Word_t Count, // ordinal of Index to find, 1..MAX.
|
||||
Word_t * PIndex, // to return found Index.
|
||||
PJError_t PJError // optional, for returning error info.
|
||||
)
|
||||
{
|
||||
Word_t Count0; // Count, base-0, to match pop0.
|
||||
Word_t state; // current state in SM.
|
||||
Word_t pop1; // of current branch or leaf, or of expanse.
|
||||
Word_t pop1lower; // pop1 of expanses (JPs) below that for Count.
|
||||
Word_t digit; // current word in branch.
|
||||
Word_t jpcount; // JPs in a BranchB subexpanse.
|
||||
long jpnum; // JP number in a branch (base 0).
|
||||
long subexp; // for stepping through layer 1 (subexpanses).
|
||||
int offset; // index ordinal within a leaf, base 0.
|
||||
|
||||
Pjp_t Pjp; // current JP in branch.
|
||||
Pjll_t Pjll; // current Judy linear leaf.
|
||||
|
||||
|
||||
// CHECK FOR EMPTY ARRAY OR NULL PINDEX:
|
||||
|
||||
if (PArray == (Pvoid_t) NULL) JU_RET_NOTFOUND;
|
||||
|
||||
if (PIndex == (PWord_t) NULL)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
|
||||
// Convert Count to Count0; assume special case of Count = 0 maps to ~0, as
|
||||
// desired, to represent the last index in a full array:
|
||||
//
|
||||
// Note: Think of Count0 as a reliable "number of Indexes below the target."
|
||||
|
||||
Count0 = Count - 1;
|
||||
assert((Count || Count0 == ~0)); // ensure CPU is sane about 0 - 1.
|
||||
pop1lower = 0;
|
||||
|
||||
if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
|
||||
{
|
||||
Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
|
||||
|
||||
if (Count0 > Pjlw[0]) JU_RET_NOTFOUND; // too high.
|
||||
|
||||
*PIndex = Pjlw[Count]; // Index, base 1.
|
||||
|
||||
JU_RET_FOUND_LEAFW(Pjlw, Pjlw[0] + 1, Count0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Pjpm_t Pjpm = P_JPM(PArray);
|
||||
|
||||
if (Count0 > (Pjpm->jpm_Pop0)) JU_RET_NOTFOUND; // too high.
|
||||
|
||||
Pjp = &(Pjpm->jpm_JP);
|
||||
pop1 = (Pjpm->jpm_Pop0) + 1;
|
||||
|
||||
// goto SMByCount;
|
||||
}
|
||||
|
||||
// COMMON CODE:
|
||||
//
|
||||
// Prepare to handle a root-level or lower-level branch: Save the current
|
||||
// state, obtain the total population for the branch in a state-dependent way,
|
||||
// and then branch to common code for multiple cases.
|
||||
//
|
||||
// For root-level branches, the state is always cJU_ROOTSTATE, and the array
|
||||
// population must already be set in pop1; it is not available in jp_DcdPopO.
|
||||
//
|
||||
// Note: The total population is only needed in cases where the common code
|
||||
// "counts down" instead of up to minimize cache line fills. However, its
|
||||
// available cheaply, and its better to do it with a constant shift (constant
|
||||
// state value) instead of a variable shift later "when needed".
|
||||
|
||||
#define PREPB_ROOT(Next) \
|
||||
state = cJU_ROOTSTATE; \
|
||||
goto Next
|
||||
|
||||
// Use PREPB_DCD() to first copy the Dcd bytes to *PIndex if there are any
|
||||
// (only if state < cJU_ROOTSTATE - 1):
|
||||
|
||||
#define PREPB_DCD(Pjp,cState,Next) \
|
||||
JU_SETDCD(*PIndex, Pjp, cState); \
|
||||
PREPB((Pjp), cState, Next)
|
||||
|
||||
#define PREPB(Pjp,cState,Next) \
|
||||
state = (cState); \
|
||||
pop1 = JU_JPBRANCH_POP0(Pjp, (cState)) + 1; \
|
||||
goto Next
|
||||
|
||||
// Calculate whether the ordinal of an Index within a given expanse falls in
|
||||
// the lower or upper half of the expanses population, taking care with
|
||||
// unsigned math and boundary conditions:
|
||||
//
|
||||
// Note: Assume the ordinal falls within the expanses population, that is,
|
||||
// 0 < (Count - Pop1lower) <= Pop1exp (assuming infinite math).
|
||||
//
|
||||
// Note: If the ordinal is the middle element, it doesnt matter whether
|
||||
// LOWERHALF() is TRUE or FALSE.
|
||||
|
||||
#define LOWERHALF(Count0,Pop1lower,Pop1exp) \
|
||||
(((Count0) - (Pop1lower)) < ((Pop1exp) / 2))
|
||||
|
||||
// Calculate the (signed) offset within a leaf to the desired ordinal (Count -
|
||||
// Pop1lower; offset is one less), and optionally ensure its in range:
|
||||
|
||||
#define SETOFFSET(Offset,Count0,Pop1lower,Pjp) \
|
||||
(Offset) = (Count0) - (Pop1lower); \
|
||||
assert((Offset) >= 0); \
|
||||
assert((Offset) <= JU_JPLEAF_POP0(Pjp))
|
||||
|
||||
// Variations for immediate indexes, with and without pop1-specific assertions:
|
||||
|
||||
#define SETOFFSET_IMM_CK(Offset,Count0,Pop1lower,cPop1) \
|
||||
(Offset) = (Count0) - (Pop1lower); \
|
||||
assert((Offset) >= 0); \
|
||||
assert((Offset) < (cPop1))
|
||||
|
||||
#define SETOFFSET_IMM(Offset,Count0,Pop1lower) \
|
||||
(Offset) = (Count0) - (Pop1lower)
|
||||
|
||||
|
||||
// STATE MACHINE -- TRAVERSE TREE:
|
||||
//
|
||||
// In branches, look for the expanse (digit), if any, where the total pop1
|
||||
// below or at that expanse would meet or exceed Count, meaning the Index must
|
||||
// be in this expanse.
|
||||
|
||||
SMByCount: // return here for next branch/leaf.
|
||||
|
||||
switch (JU_JPTYPE(Pjp))
|
||||
{
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LINEAR BRANCH; count populations in JPs in the JBL upwards until finding the
|
||||
// expanse (digit) containing Count, and "recurse".
|
||||
//
|
||||
// Note: There are no null JPs in a JBL; watch out for pop1 == 0.
|
||||
//
|
||||
// Note: A JBL should always fit in one cache line => no need to count up
|
||||
// versus down to save cache line fills.
|
||||
//
|
||||
// TBD: The previous is no longer true. Consider enhancing this code to count
|
||||
// up/down, but it can wait for a later tuning phase. In the meantime, PREPB()
|
||||
// sets pop1 for the whole array, but that value is not used here. 001215:
|
||||
// Maybe its true again?
|
||||
|
||||
case cJU_JPBRANCH_L2: PREPB_DCD(Pjp, 2, BranchL);
|
||||
#ifndef JU_64BIT
|
||||
case cJU_JPBRANCH_L3: PREPB( Pjp, 3, BranchL);
|
||||
#else
|
||||
case cJU_JPBRANCH_L3: PREPB_DCD(Pjp, 3, BranchL);
|
||||
case cJU_JPBRANCH_L4: PREPB_DCD(Pjp, 4, BranchL);
|
||||
case cJU_JPBRANCH_L5: PREPB_DCD(Pjp, 5, BranchL);
|
||||
case cJU_JPBRANCH_L6: PREPB_DCD(Pjp, 6, BranchL);
|
||||
case cJU_JPBRANCH_L7: PREPB( Pjp, 7, BranchL);
|
||||
#endif
|
||||
case cJU_JPBRANCH_L: PREPB_ROOT( BranchL);
|
||||
{
|
||||
Pjbl_t Pjbl;
|
||||
|
||||
// Common code (state-independent) for all cases of linear branches:
|
||||
|
||||
BranchL:
|
||||
Pjbl = P_JBL(Pjp->jp_Addr);
|
||||
|
||||
for (jpnum = 0; jpnum < (Pjbl->jbl_NumJPs); ++jpnum)
|
||||
{
|
||||
if ((pop1 = j__udyJPPop1((Pjbl->jbl_jp) + jpnum))
|
||||
== cJU_ALLONES)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
assert(pop1 != 0);
|
||||
|
||||
// Warning: pop1lower and pop1 are unsigned, so do not subtract 1 and compare
|
||||
// >=, but instead use the following expression:
|
||||
|
||||
if (pop1lower + pop1 > Count0) // Index is in this expanse.
|
||||
{
|
||||
JU_SETDIGIT(*PIndex, Pjbl->jbl_Expanse[jpnum], state);
|
||||
Pjp = (Pjbl->jbl_jp) + jpnum;
|
||||
goto SMByCount; // look under this expanse.
|
||||
}
|
||||
|
||||
pop1lower += pop1; // add this JPs pop1.
|
||||
}
|
||||
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // should never get here.
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
|
||||
} // case cJU_JPBRANCH_L
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// BITMAP BRANCH; count populations in JPs in the JBB upwards or downwards
|
||||
// until finding the expanse (digit) containing Count, and "recurse".
|
||||
//
|
||||
// Note: There are no null JPs in a JBB; watch out for pop1 == 0.
|
||||
|
||||
case cJU_JPBRANCH_B2: PREPB_DCD(Pjp, 2, BranchB);
|
||||
#ifndef JU_64BIT
|
||||
case cJU_JPBRANCH_B3: PREPB( Pjp, 3, BranchB);
|
||||
#else
|
||||
case cJU_JPBRANCH_B3: PREPB_DCD(Pjp, 3, BranchB);
|
||||
case cJU_JPBRANCH_B4: PREPB_DCD(Pjp, 4, BranchB);
|
||||
case cJU_JPBRANCH_B5: PREPB_DCD(Pjp, 5, BranchB);
|
||||
case cJU_JPBRANCH_B6: PREPB_DCD(Pjp, 6, BranchB);
|
||||
case cJU_JPBRANCH_B7: PREPB( Pjp, 7, BranchB);
|
||||
#endif
|
||||
case cJU_JPBRANCH_B: PREPB_ROOT( BranchB);
|
||||
{
|
||||
Pjbb_t Pjbb;
|
||||
|
||||
// Common code (state-independent) for all cases of bitmap branches:
|
||||
|
||||
BranchB:
|
||||
Pjbb = P_JBB(Pjp->jp_Addr);
|
||||
|
||||
// Shorthand for one subexpanse in a bitmap and for one JP in a bitmap branch:
|
||||
//
|
||||
// Note: BMPJP0 exists separately to support assertions.
|
||||
|
||||
#define BMPJP0(Subexp) (P_JP(JU_JBB_PJP(Pjbb, Subexp)))
|
||||
#define BMPJP(Subexp,JPnum) (BMPJP0(Subexp) + (JPnum))
|
||||
|
||||
|
||||
// Common code for descending through a JP:
|
||||
//
|
||||
// Determine the digit for the expanse and save it in *PIndex; then "recurse".
|
||||
|
||||
#define JBB_FOUNDEXPANSE \
|
||||
{ \
|
||||
JU_BITMAPDIGITB(digit, subexp, JU_JBB_BITMAP(Pjbb,subexp), jpnum); \
|
||||
JU_SETDIGIT(*PIndex, digit, state); \
|
||||
Pjp = BMPJP(subexp, jpnum); \
|
||||
goto SMByCount; \
|
||||
}
|
||||
|
||||
|
||||
#ifndef NOSMARTJBB // enable to turn off smart code for comparison purposes.
|
||||
|
||||
// FIGURE OUT WHICH DIRECTION CAUSES FEWER CACHE LINE FILLS; adding the pop1s
|
||||
// in JPs upwards, or subtracting the pop1s in JPs downwards:
|
||||
//
|
||||
// See header comments about limitations of this for Judy*ByCount().
|
||||
|
||||
#endif
|
||||
|
||||
// COUNT UPWARD, adding each "below" JPs pop1:
|
||||
|
||||
#ifndef NOSMARTJBB // enable to turn off smart code for comparison purposes.
|
||||
|
||||
if (LOWERHALF(Count0, pop1lower, pop1))
|
||||
{
|
||||
#endif
|
||||
#ifdef SMARTMETRICS
|
||||
++jbb_upward;
|
||||
#endif
|
||||
for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
|
||||
{
|
||||
if ((jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb,subexp)))
|
||||
&& (BMPJP0(subexp) == (Pjp_t) NULL))
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // null ptr.
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
|
||||
// Note: An empty subexpanse (jpcount == 0) is handled "for free":
|
||||
|
||||
for (jpnum = 0; jpnum < jpcount; ++jpnum)
|
||||
{
|
||||
if ((pop1 = j__udyJPPop1(BMPJP(subexp, jpnum)))
|
||||
== cJU_ALLONES)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
assert(pop1 != 0);
|
||||
|
||||
// Warning: pop1lower and pop1 are unsigned, see earlier comment:
|
||||
|
||||
if (pop1lower + pop1 > Count0)
|
||||
JBB_FOUNDEXPANSE; // Index is in this expanse.
|
||||
|
||||
pop1lower += pop1; // add this JPs pop1.
|
||||
}
|
||||
}
|
||||
#ifndef NOSMARTJBB // enable to turn off smart code for comparison purposes.
|
||||
}
|
||||
|
||||
|
||||
// COUNT DOWNWARD, subtracting each "above" JPs pop1 from the whole expanses
|
||||
// pop1:
|
||||
|
||||
else
|
||||
{
|
||||
#ifdef SMARTMETRICS
|
||||
++jbb_downward;
|
||||
#endif
|
||||
pop1lower += pop1; // add whole branch to start.
|
||||
|
||||
for (subexp = cJU_NUMSUBEXPB - 1; subexp >= 0; --subexp)
|
||||
{
|
||||
if ((jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp)))
|
||||
&& (BMPJP0(subexp) == (Pjp_t) NULL))
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // null ptr.
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
|
||||
// Note: An empty subexpanse (jpcount == 0) is handled "for free":
|
||||
|
||||
for (jpnum = jpcount - 1; jpnum >= 0; --jpnum)
|
||||
{
|
||||
if ((pop1 = j__udyJPPop1(BMPJP(subexp, jpnum)))
|
||||
== cJU_ALLONES)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
assert(pop1 != 0);
|
||||
|
||||
// Warning: pop1lower and pop1 are unsigned, see earlier comment:
|
||||
|
||||
pop1lower -= pop1;
|
||||
|
||||
// Beware unsigned math problems:
|
||||
|
||||
if ((pop1lower == 0) || (pop1lower - 1 < Count0))
|
||||
JBB_FOUNDEXPANSE; // Index is in this expanse.
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // NOSMARTJBB
|
||||
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // should never get here.
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
|
||||
} // case cJU_JPBRANCH_B
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// UNCOMPRESSED BRANCH; count populations in JPs in the JBU upwards or
|
||||
// downwards until finding the expanse (digit) containing Count, and "recurse".
|
||||
|
||||
case cJU_JPBRANCH_U2: PREPB_DCD(Pjp, 2, BranchU);
|
||||
#ifndef JU_64BIT
|
||||
case cJU_JPBRANCH_U3: PREPB( Pjp, 3, BranchU);
|
||||
#else
|
||||
case cJU_JPBRANCH_U3: PREPB_DCD(Pjp, 3, BranchU);
|
||||
case cJU_JPBRANCH_U4: PREPB_DCD(Pjp, 4, BranchU);
|
||||
case cJU_JPBRANCH_U5: PREPB_DCD(Pjp, 5, BranchU);
|
||||
case cJU_JPBRANCH_U6: PREPB_DCD(Pjp, 6, BranchU);
|
||||
case cJU_JPBRANCH_U7: PREPB( Pjp, 7, BranchU);
|
||||
#endif
|
||||
case cJU_JPBRANCH_U: PREPB_ROOT( BranchU);
|
||||
{
|
||||
Pjbu_t Pjbu;
|
||||
|
||||
// Common code (state-independent) for all cases of uncompressed branches:
|
||||
|
||||
BranchU:
|
||||
Pjbu = P_JBU(Pjp->jp_Addr);
|
||||
|
||||
// Common code for descending through a JP:
|
||||
//
|
||||
// Save the digit for the expanse in *PIndex, then "recurse".
|
||||
|
||||
#define JBU_FOUNDEXPANSE \
|
||||
{ \
|
||||
JU_SETDIGIT(*PIndex, jpnum, state); \
|
||||
Pjp = (Pjbu->jbu_jp) + jpnum; \
|
||||
goto SMByCount; \
|
||||
}
|
||||
|
||||
|
||||
#ifndef NOSMARTJBU // enable to turn off smart code for comparison purposes.
|
||||
|
||||
// FIGURE OUT WHICH DIRECTION CAUSES FEWER CACHE LINE FILLS; adding the pop1s
|
||||
// in JPs upwards, or subtracting the pop1s in JPs downwards:
|
||||
//
|
||||
// See header comments about limitations of this for Judy*ByCount().
|
||||
|
||||
#endif
|
||||
|
||||
// COUNT UPWARD, simply adding the pop1 of each JP:
|
||||
|
||||
#ifndef NOSMARTJBU // enable to turn off smart code for comparison purposes.
|
||||
|
||||
if (LOWERHALF(Count0, pop1lower, pop1))
|
||||
{
|
||||
#endif
|
||||
#ifdef SMARTMETRICS
|
||||
++jbu_upward;
|
||||
#endif
|
||||
|
||||
for (jpnum = 0; jpnum < cJU_BRANCHUNUMJPS; ++jpnum)
|
||||
{
|
||||
// shortcut, save a function call:
|
||||
|
||||
if ((Pjbu->jbu_jp[jpnum].jp_Type) <= cJU_JPNULLMAX)
|
||||
continue;
|
||||
|
||||
if ((pop1 = j__udyJPPop1((Pjbu->jbu_jp) + jpnum))
|
||||
== cJU_ALLONES)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
assert(pop1 != 0);
|
||||
|
||||
// Warning: pop1lower and pop1 are unsigned, see earlier comment:
|
||||
|
||||
if (pop1lower + pop1 > Count0)
|
||||
JBU_FOUNDEXPANSE; // Index is in this expanse.
|
||||
|
||||
pop1lower += pop1; // add this JPs pop1.
|
||||
}
|
||||
#ifndef NOSMARTJBU // enable to turn off smart code for comparison purposes.
|
||||
}
|
||||
|
||||
|
||||
// COUNT DOWNWARD, subtracting the pop1 of each JP above from the whole
|
||||
// expanses pop1:
|
||||
|
||||
else
|
||||
{
|
||||
#ifdef SMARTMETRICS
|
||||
++jbu_downward;
|
||||
#endif
|
||||
pop1lower += pop1; // add whole branch to start.
|
||||
|
||||
for (jpnum = cJU_BRANCHUNUMJPS - 1; jpnum >= 0; --jpnum)
|
||||
{
|
||||
// shortcut, save a function call:
|
||||
|
||||
if ((Pjbu->jbu_jp[jpnum].jp_Type) <= cJU_JPNULLMAX)
|
||||
continue;
|
||||
|
||||
if ((pop1 = j__udyJPPop1(Pjbu->jbu_jp + jpnum))
|
||||
== cJU_ALLONES)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
assert(pop1 != 0);
|
||||
|
||||
// Warning: pop1lower and pop1 are unsigned, see earlier comment:
|
||||
|
||||
pop1lower -= pop1;
|
||||
|
||||
// Beware unsigned math problems:
|
||||
|
||||
if ((pop1lower == 0) || (pop1lower - 1 < Count0))
|
||||
JBU_FOUNDEXPANSE; // Index is in this expanse.
|
||||
}
|
||||
}
|
||||
#endif // NOSMARTJBU
|
||||
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // should never get here.
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
|
||||
} // case cJU_JPBRANCH_U
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LINEAR LEAF:
|
||||
//
|
||||
// Return the Index at the proper ordinal (see SETOFFSET()) in the leaf. First
|
||||
// copy Dcd bytes, if there are any (only if state < cJU_ROOTSTATE - 1), to
|
||||
// *PIndex.
|
||||
//
|
||||
// Note: The preceding branch traversal code MIGHT set pop1 for this expanse
|
||||
// (linear leaf) as a side-effect, but dont depend on that (for JUDYL, which
|
||||
// is the only cases that need it anyway).
|
||||
|
||||
#define PREPL_DCD(cState) \
|
||||
JU_SETDCD(*PIndex, Pjp, cState); \
|
||||
PREPL
|
||||
|
||||
#ifdef JUDY1
|
||||
#define PREPL_SETPOP1 // not needed in any cases.
|
||||
#else
|
||||
#define PREPL_SETPOP1 pop1 = JU_JPLEAF_POP0(Pjp) + 1
|
||||
#endif
|
||||
|
||||
#define PREPL \
|
||||
Pjll = P_JLL(Pjp->jp_Addr); \
|
||||
PREPL_SETPOP1; \
|
||||
SETOFFSET(offset, Count0, pop1lower, Pjp)
|
||||
|
||||
#if (defined(JUDYL) || (! defined(JU_64BIT)))
|
||||
case cJU_JPLEAF1:
|
||||
|
||||
PREPL_DCD(1);
|
||||
JU_SETDIGIT1(*PIndex, ((uint8_t *) Pjll)[offset]);
|
||||
JU_RET_FOUND_LEAF1(Pjll, pop1, offset);
|
||||
#endif
|
||||
|
||||
case cJU_JPLEAF2:
|
||||
|
||||
PREPL_DCD(2);
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
|
||||
| ((uint16_t *) Pjll)[offset];
|
||||
JU_RET_FOUND_LEAF2(Pjll, pop1, offset);
|
||||
|
||||
#ifndef JU_64BIT
|
||||
case cJU_JPLEAF3:
|
||||
{
|
||||
Word_t lsb;
|
||||
PREPL;
|
||||
JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
|
||||
JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
|
||||
}
|
||||
|
||||
#else
|
||||
case cJU_JPLEAF3:
|
||||
{
|
||||
Word_t lsb;
|
||||
PREPL_DCD(3);
|
||||
JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (3 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
|
||||
JU_RET_FOUND_LEAF3(Pjll, pop1, offset);
|
||||
}
|
||||
|
||||
case cJU_JPLEAF4:
|
||||
|
||||
PREPL_DCD(4);
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
|
||||
| ((uint32_t *) Pjll)[offset];
|
||||
JU_RET_FOUND_LEAF4(Pjll, pop1, offset);
|
||||
|
||||
case cJU_JPLEAF5:
|
||||
{
|
||||
Word_t lsb;
|
||||
PREPL_DCD(5);
|
||||
JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (5 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
|
||||
JU_RET_FOUND_LEAF5(Pjll, pop1, offset);
|
||||
}
|
||||
|
||||
case cJU_JPLEAF6:
|
||||
{
|
||||
Word_t lsb;
|
||||
PREPL_DCD(6);
|
||||
JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (6 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
|
||||
JU_RET_FOUND_LEAF6(Pjll, pop1, offset);
|
||||
}
|
||||
|
||||
case cJU_JPLEAF7:
|
||||
{
|
||||
Word_t lsb;
|
||||
PREPL;
|
||||
JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) Pjll) + (7 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
|
||||
JU_RET_FOUND_LEAF7(Pjll, pop1, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// BITMAP LEAF:
|
||||
//
|
||||
// Return the Index at the proper ordinal (see SETOFFSET()) in the leaf by
|
||||
// counting bits. First copy Dcd bytes (always present since state 1 <
|
||||
// cJU_ROOTSTATE) to *PIndex.
|
||||
//
|
||||
// Note: The preceding branch traversal code MIGHT set pop1 for this expanse
|
||||
// (bitmap leaf) as a side-effect, but dont depend on that.
|
||||
|
||||
case cJU_JPLEAF_B1:
|
||||
{
|
||||
Pjlb_t Pjlb;
|
||||
|
||||
JU_SETDCD(*PIndex, Pjp, 1);
|
||||
Pjlb = P_JLB(Pjp->jp_Addr);
|
||||
pop1 = JU_JPLEAF_POP0(Pjp) + 1;
|
||||
|
||||
// COUNT UPWARD, adding the pop1 of each subexpanse:
|
||||
//
|
||||
// The entire bitmap should fit in one cache line, but still try to save some
|
||||
// CPU time by counting the fewest possible number of subexpanses from the
|
||||
// bitmap.
|
||||
//
|
||||
// See header comments about limitations of this for Judy*ByCount().
|
||||
|
||||
#ifndef NOSMARTJLB // enable to turn off smart code for comparison purposes.
|
||||
|
||||
if (LOWERHALF(Count0, pop1lower, pop1))
|
||||
{
|
||||
#endif
|
||||
#ifdef SMARTMETRICS
|
||||
++jlb_upward;
|
||||
#endif
|
||||
for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
|
||||
{
|
||||
pop1 = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
|
||||
|
||||
// Warning: pop1lower and pop1 are unsigned, see earlier comment:
|
||||
|
||||
if (pop1lower + pop1 > Count0)
|
||||
goto LeafB1; // Index is in this subexpanse.
|
||||
|
||||
pop1lower += pop1; // add this subexpanses pop1.
|
||||
}
|
||||
#ifndef NOSMARTJLB // enable to turn off smart code for comparison purposes.
|
||||
}
|
||||
|
||||
|
||||
// COUNT DOWNWARD, subtracting each "above" subexpanses pop1 from the whole
|
||||
// expanses pop1:
|
||||
|
||||
else
|
||||
{
|
||||
#ifdef SMARTMETRICS
|
||||
++jlb_downward;
|
||||
#endif
|
||||
pop1lower += pop1; // add whole leaf to start.
|
||||
|
||||
for (subexp = cJU_NUMSUBEXPL - 1; subexp >= 0; --subexp)
|
||||
{
|
||||
pop1lower -= j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
|
||||
|
||||
// Beware unsigned math problems:
|
||||
|
||||
if ((pop1lower == 0) || (pop1lower - 1 < Count0))
|
||||
goto LeafB1; // Index is in this subexpanse.
|
||||
}
|
||||
}
|
||||
#endif // NOSMARTJLB
|
||||
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); // should never get here.
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
|
||||
|
||||
// RETURN INDEX FOUND:
|
||||
//
|
||||
// Come here with subexp set to the correct subexpanse, and pop1lower set to
|
||||
// the sum for all lower expanses and subexpanses in the Judy tree. Calculate
|
||||
// and save in *PIndex the digit corresponding to the ordinal in this
|
||||
// subexpanse.
|
||||
|
||||
LeafB1:
|
||||
SETOFFSET(offset, Count0, pop1lower, Pjp);
|
||||
JU_BITMAPDIGITL(digit, subexp, JU_JLB_BITMAP(Pjlb, subexp), offset);
|
||||
JU_SETDIGIT1(*PIndex, digit);
|
||||
JU_RET_FOUND_LEAF_B1(Pjlb, subexp, offset);
|
||||
// == return((PPvoid_t) (P_JV(JL_JLB_PVALUE(Pjlb, subexp)) + offset))
|
||||
|
||||
} // case cJU_JPLEAF_B1
|
||||
|
||||
|
||||
#ifdef JUDY1
|
||||
// ----------------------------------------------------------------------------
|
||||
// FULL POPULATION:
|
||||
//
|
||||
// Copy Dcd bytes (always present since state 1 < cJU_ROOTSTATE) to *PIndex,
|
||||
// then set the appropriate digit for the ordinal (see SETOFFSET()) in the leaf
|
||||
// as the LSB in *PIndex.
|
||||
|
||||
case cJ1_JPFULLPOPU1:
|
||||
|
||||
JU_SETDCD(*PIndex, Pjp, 1);
|
||||
SETOFFSET(offset, Count0, pop1lower, Pjp);
|
||||
assert(offset >= 0);
|
||||
assert(offset <= cJU_JPFULLPOPU1_POP0);
|
||||
JU_SETDIGIT1(*PIndex, offset);
|
||||
JU_RET_FOUND_FULLPOPU1;
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// IMMEDIATE:
|
||||
//
|
||||
// Locate the Index with the proper ordinal (see SETOFFSET()) in the Immediate,
|
||||
// depending on leaf Index Size and pop1. Note: There are no Dcd bytes in an
|
||||
// Immediate JP, but in a cJU_JPIMMED_*_01 JP, the field holds the least bytes
|
||||
// of the immediate Index.
|
||||
|
||||
#define SET_01(cState) JU_SETDIGITS(*PIndex, JU_JPDCDPOP0(Pjp), cState)
|
||||
|
||||
case cJU_JPIMMED_1_01: SET_01(1); goto Imm_01;
|
||||
case cJU_JPIMMED_2_01: SET_01(2); goto Imm_01;
|
||||
case cJU_JPIMMED_3_01: SET_01(3); goto Imm_01;
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPIMMED_4_01: SET_01(4); goto Imm_01;
|
||||
case cJU_JPIMMED_5_01: SET_01(5); goto Imm_01;
|
||||
case cJU_JPIMMED_6_01: SET_01(6); goto Imm_01;
|
||||
case cJU_JPIMMED_7_01: SET_01(7); goto Imm_01;
|
||||
#endif
|
||||
|
||||
Imm_01:
|
||||
|
||||
DBGCODE(SETOFFSET_IMM_CK(offset, Count0, pop1lower, 1);)
|
||||
JU_RET_FOUND_IMM_01(Pjp);
|
||||
|
||||
// Shorthand for where to find start of Index bytes array:
|
||||
|
||||
#ifdef JUDY1
|
||||
#define PJI (Pjp->jp_1Index)
|
||||
#else
|
||||
#define PJI (Pjp->jp_LIndex)
|
||||
#endif
|
||||
|
||||
// Optional code to check the remaining ordinal (see SETOFFSET_IMM()) against
|
||||
// the Index Size of the Immediate:
|
||||
|
||||
#ifndef DEBUG // simple placeholder:
|
||||
#define IMM(cPop1,Next) \
|
||||
goto Next
|
||||
#else // extra pop1-specific checking:
|
||||
#define IMM(cPop1,Next) \
|
||||
SETOFFSET_IMM_CK(offset, Count0, pop1lower, cPop1); \
|
||||
goto Next
|
||||
#endif
|
||||
|
||||
case cJU_JPIMMED_1_02: IMM( 2, Imm1);
|
||||
case cJU_JPIMMED_1_03: IMM( 3, Imm1);
|
||||
#if (defined(JUDY1) || defined(JU_64BIT))
|
||||
case cJU_JPIMMED_1_04: IMM( 4, Imm1);
|
||||
case cJU_JPIMMED_1_05: IMM( 5, Imm1);
|
||||
case cJU_JPIMMED_1_06: IMM( 6, Imm1);
|
||||
case cJU_JPIMMED_1_07: IMM( 7, Imm1);
|
||||
#endif
|
||||
#if (defined(JUDY1) && defined(JU_64BIT))
|
||||
case cJ1_JPIMMED_1_08: IMM( 8, Imm1);
|
||||
case cJ1_JPIMMED_1_09: IMM( 9, Imm1);
|
||||
case cJ1_JPIMMED_1_10: IMM(10, Imm1);
|
||||
case cJ1_JPIMMED_1_11: IMM(11, Imm1);
|
||||
case cJ1_JPIMMED_1_12: IMM(12, Imm1);
|
||||
case cJ1_JPIMMED_1_13: IMM(13, Imm1);
|
||||
case cJ1_JPIMMED_1_14: IMM(14, Imm1);
|
||||
case cJ1_JPIMMED_1_15: IMM(15, Imm1);
|
||||
#endif
|
||||
|
||||
Imm1: SETOFFSET_IMM(offset, Count0, pop1lower);
|
||||
JU_SETDIGIT1(*PIndex, ((uint8_t *) PJI)[offset]);
|
||||
JU_RET_FOUND_IMM(Pjp, offset);
|
||||
|
||||
#if (defined(JUDY1) || defined(JU_64BIT))
|
||||
case cJU_JPIMMED_2_02: IMM(2, Imm2);
|
||||
case cJU_JPIMMED_2_03: IMM(3, Imm2);
|
||||
#endif
|
||||
#if (defined(JUDY1) && defined(JU_64BIT))
|
||||
case cJ1_JPIMMED_2_04: IMM(4, Imm2);
|
||||
case cJ1_JPIMMED_2_05: IMM(5, Imm2);
|
||||
case cJ1_JPIMMED_2_06: IMM(6, Imm2);
|
||||
case cJ1_JPIMMED_2_07: IMM(7, Imm2);
|
||||
#endif
|
||||
|
||||
#if (defined(JUDY1) || defined(JU_64BIT))
|
||||
Imm2: SETOFFSET_IMM(offset, Count0, pop1lower);
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(2)))
|
||||
| ((uint16_t *) PJI)[offset];
|
||||
JU_RET_FOUND_IMM(Pjp, offset);
|
||||
#endif
|
||||
|
||||
#if (defined(JUDY1) || defined(JU_64BIT))
|
||||
case cJU_JPIMMED_3_02: IMM(2, Imm3);
|
||||
#endif
|
||||
#if (defined(JUDY1) && defined(JU_64BIT))
|
||||
case cJ1_JPIMMED_3_03: IMM(3, Imm3);
|
||||
case cJ1_JPIMMED_3_04: IMM(4, Imm3);
|
||||
case cJ1_JPIMMED_3_05: IMM(5, Imm3);
|
||||
#endif
|
||||
|
||||
#if (defined(JUDY1) || defined(JU_64BIT))
|
||||
Imm3:
|
||||
{
|
||||
Word_t lsb;
|
||||
SETOFFSET_IMM(offset, Count0, pop1lower);
|
||||
JU_COPY3_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (3 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(3))) | lsb;
|
||||
JU_RET_FOUND_IMM(Pjp, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(JUDY1) && defined(JU_64BIT))
|
||||
case cJ1_JPIMMED_4_02: IMM(2, Imm4);
|
||||
case cJ1_JPIMMED_4_03: IMM(3, Imm4);
|
||||
|
||||
Imm4: SETOFFSET_IMM(offset, Count0, pop1lower);
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(4)))
|
||||
| ((uint32_t *) PJI)[offset];
|
||||
JU_RET_FOUND_IMM(Pjp, offset);
|
||||
|
||||
case cJ1_JPIMMED_5_02: IMM(2, Imm5);
|
||||
case cJ1_JPIMMED_5_03: IMM(3, Imm5);
|
||||
|
||||
Imm5:
|
||||
{
|
||||
Word_t lsb;
|
||||
SETOFFSET_IMM(offset, Count0, pop1lower);
|
||||
JU_COPY5_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (5 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(5))) | lsb;
|
||||
JU_RET_FOUND_IMM(Pjp, offset);
|
||||
}
|
||||
|
||||
case cJ1_JPIMMED_6_02: IMM(2, Imm6);
|
||||
|
||||
Imm6:
|
||||
{
|
||||
Word_t lsb;
|
||||
SETOFFSET_IMM(offset, Count0, pop1lower);
|
||||
JU_COPY6_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (6 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(6))) | lsb;
|
||||
JU_RET_FOUND_IMM(Pjp, offset);
|
||||
}
|
||||
|
||||
case cJ1_JPIMMED_7_02: IMM(2, Imm7);
|
||||
|
||||
Imm7:
|
||||
{
|
||||
Word_t lsb;
|
||||
SETOFFSET_IMM(offset, Count0, pop1lower);
|
||||
JU_COPY7_PINDEX_TO_LONG(lsb, ((uint8_t *) PJI) + (7 * offset));
|
||||
*PIndex = (*PIndex & (~JU_LEASTBYTESMASK(7))) | lsb;
|
||||
JU_RET_FOUND_IMM(Pjp, offset);
|
||||
}
|
||||
#endif // (JUDY1 && JU_64BIT)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// UNEXPECTED JP TYPES:
|
||||
|
||||
default: JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
|
||||
} // SMByCount switch.
|
||||
|
||||
/*NOTREACHED*/
|
||||
|
||||
} // Judy1ByCount() / JudyLByCount()
|
1942
libnetdata/libjudy/src/JudyL/JudyLCascade.c
Normal file
1942
libnetdata/libjudy/src/JudyL/JudyLCascade.c
Normal file
File diff suppressed because it is too large
Load diff
1195
libnetdata/libjudy/src/JudyL/JudyLCount.c
Normal file
1195
libnetdata/libjudy/src/JudyL/JudyLCount.c
Normal file
File diff suppressed because it is too large
Load diff
314
libnetdata/libjudy/src/JudyL/JudyLCreateBranch.c
Normal file
314
libnetdata/libjudy/src/JudyL/JudyLCreateBranch.c
Normal file
|
@ -0,0 +1,314 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.26 $ $Source: /judy/src/JudyCommon/JudyCreateBranch.c $
|
||||
|
||||
// Branch creation functions for Judy1 and JudyL.
|
||||
// Compile with one of -DJUDY1 or -DJUDYL.
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
#include "JudyPrivate1L.h"
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y C R E A T E B R A N C H L
|
||||
//
|
||||
// Build a BranchL from an array of JPs and associated 1 byte digits
|
||||
// (expanses). Return with Pjp pointing to the BranchL. Caller must
|
||||
// deallocate passed arrays, if necessary.
|
||||
//
|
||||
// We have no idea what kind of BranchL it is, so caller must set the jp_Type.
|
||||
//
|
||||
// Return -1 if error (details in Pjpm), otherwise return 1.
|
||||
|
||||
FUNCTION int j__udyCreateBranchL(
|
||||
Pjp_t Pjp, // Build JPs from this place
|
||||
Pjp_t PJPs, // Array of JPs to put into Bitmap branch
|
||||
uint8_t Exp[], // Array of expanses to put into bitmap
|
||||
Word_t ExpCnt, // Number of above JPs and Expanses
|
||||
Pvoid_t Pjpm)
|
||||
{
|
||||
Pjbl_t PjblRaw; // pointer to linear branch.
|
||||
Pjbl_t Pjbl;
|
||||
|
||||
assert(ExpCnt <= cJU_BRANCHLMAXJPS);
|
||||
|
||||
PjblRaw = j__udyAllocJBL(Pjpm);
|
||||
if (PjblRaw == (Pjbl_t) NULL) return(-1);
|
||||
Pjbl = P_JBL(PjblRaw);
|
||||
|
||||
// Build a Linear Branch
|
||||
Pjbl->jbl_NumJPs = ExpCnt;
|
||||
|
||||
// Copy from the Linear branch from splayed leaves
|
||||
JU_COPYMEM(Pjbl->jbl_Expanse, Exp, ExpCnt);
|
||||
JU_COPYMEM(Pjbl->jbl_jp, PJPs, ExpCnt);
|
||||
|
||||
// Pass back new pointer to the Linear branch in JP
|
||||
Pjp->jp_Addr = (Word_t) PjblRaw;
|
||||
|
||||
return(1);
|
||||
|
||||
} // j__udyCreateBranchL()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y C R E A T E B R A N C H B
|
||||
//
|
||||
// Build a BranchB from an array of JPs and associated 1 byte digits
|
||||
// (expanses). Return with Pjp pointing to the BranchB. Caller must
|
||||
// deallocate passed arrays, if necessary.
|
||||
//
|
||||
// We have no idea what kind of BranchB it is, so caller must set the jp_Type.
|
||||
//
|
||||
// Return -1 if error (details in Pjpm), otherwise return 1.
|
||||
|
||||
FUNCTION int j__udyCreateBranchB(
|
||||
Pjp_t Pjp, // Build JPs from this place
|
||||
Pjp_t PJPs, // Array of JPs to put into Bitmap branch
|
||||
uint8_t Exp[], // Array of expanses to put into bitmap
|
||||
Word_t ExpCnt, // Number of above JPs and Expanses
|
||||
Pvoid_t Pjpm)
|
||||
{
|
||||
Pjbb_t PjbbRaw; // pointer to bitmap branch.
|
||||
Pjbb_t Pjbb;
|
||||
Word_t ii, jj; // Temps
|
||||
uint8_t CurrSubExp; // Current sub expanse for BM
|
||||
|
||||
// This assertion says the number of populated subexpanses is not too large.
|
||||
// This function is only called when a BranchL overflows to a BranchB or when a
|
||||
// cascade occurs, meaning a leaf overflows. Either way ExpCnt cant be very
|
||||
// large, in fact a lot smaller than cJU_BRANCHBMAXJPS. (Otherwise a BranchU
|
||||
// would be used.) Popping this assertion means something (unspecified) has
|
||||
// gone very wrong, or else Judys design criteria have changed, although in
|
||||
// fact there should be no HARM in creating a BranchB with higher actual
|
||||
// fanout.
|
||||
|
||||
assert(ExpCnt <= cJU_BRANCHBMAXJPS);
|
||||
|
||||
// Get memory for a Bitmap branch
|
||||
PjbbRaw = j__udyAllocJBB(Pjpm);
|
||||
if (PjbbRaw == (Pjbb_t) NULL) return(-1);
|
||||
Pjbb = P_JBB(PjbbRaw);
|
||||
|
||||
// Get 1st "sub" expanse (0..7) of bitmap branch
|
||||
CurrSubExp = Exp[0] / cJU_BITSPERSUBEXPB;
|
||||
|
||||
// Index thru all 1 byte sized expanses:
|
||||
|
||||
for (jj = ii = 0; ii <= ExpCnt; ii++)
|
||||
{
|
||||
Word_t SubExp; // Cannot be a uint8_t
|
||||
|
||||
// Make sure we cover the last one
|
||||
if (ii == ExpCnt)
|
||||
{
|
||||
SubExp = cJU_ALLONES; // Force last one
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculate the "sub" expanse of the byte expanse
|
||||
SubExp = Exp[ii] / cJU_BITSPERSUBEXPB; // Bits 5..7.
|
||||
|
||||
// Set the bit that represents the expanse in Exp[]
|
||||
JU_JBB_BITMAP(Pjbb, SubExp) |= JU_BITPOSMASKB(Exp[ii]);
|
||||
}
|
||||
// Check if a new "sub" expanse range needed
|
||||
if (SubExp != CurrSubExp)
|
||||
{
|
||||
// Get number of JPs in this sub expanse
|
||||
Word_t NumJP = ii - jj;
|
||||
Pjp_t PjpRaw;
|
||||
Pjp_t Pjp;
|
||||
|
||||
PjpRaw = j__udyAllocJBBJP(NumJP, Pjpm);
|
||||
Pjp = P_JP(PjpRaw);
|
||||
|
||||
if (PjpRaw == (Pjp_t) NULL) // out of memory.
|
||||
{
|
||||
|
||||
// Free any previous allocations:
|
||||
|
||||
while(CurrSubExp--)
|
||||
{
|
||||
NumJP = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb,
|
||||
CurrSubExp));
|
||||
if (NumJP)
|
||||
{
|
||||
j__udyFreeJBBJP(JU_JBB_PJP(Pjbb,
|
||||
CurrSubExp), NumJP, Pjpm);
|
||||
}
|
||||
}
|
||||
j__udyFreeJBB(PjbbRaw, Pjpm);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// Place the array of JPs in bitmap branch:
|
||||
|
||||
JU_JBB_PJP(Pjbb, CurrSubExp) = PjpRaw;
|
||||
|
||||
// Copy the JPs to new leaf:
|
||||
|
||||
JU_COPYMEM(Pjp, PJPs + jj, NumJP);
|
||||
|
||||
// On to the next bitmap branch "sub" expanse:
|
||||
|
||||
jj = ii;
|
||||
CurrSubExp = SubExp;
|
||||
}
|
||||
} // for each 1-byte expanse
|
||||
|
||||
// Pass back some of the JP to the new Bitmap branch:
|
||||
|
||||
Pjp->jp_Addr = (Word_t) PjbbRaw;
|
||||
|
||||
return(1);
|
||||
|
||||
} // j__udyCreateBranchB()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y C R E A T E B R A N C H U
|
||||
//
|
||||
// Build a BranchU from a BranchB. Return with Pjp pointing to the BranchU.
|
||||
// Free the BranchB and its JP subarrays.
|
||||
//
|
||||
// Return -1 if error (details in Pjpm), otherwise return 1.
|
||||
|
||||
FUNCTION int j__udyCreateBranchU(
|
||||
Pjp_t Pjp,
|
||||
Pvoid_t Pjpm)
|
||||
{
|
||||
jp_t JPNull;
|
||||
Pjbu_t PjbuRaw;
|
||||
Pjbu_t Pjbu;
|
||||
Pjbb_t PjbbRaw;
|
||||
Pjbb_t Pjbb;
|
||||
Word_t ii, jj;
|
||||
BITMAPB_t BitMap;
|
||||
Pjp_t PDstJP;
|
||||
#ifdef JU_STAGED_EXP
|
||||
jbu_t BranchU; // Staged uncompressed branch
|
||||
#else
|
||||
|
||||
// Allocate memory for a BranchU:
|
||||
|
||||
PjbuRaw = j__udyAllocJBU(Pjpm);
|
||||
if (PjbuRaw == (Pjbu_t) NULL) return(-1);
|
||||
Pjbu = P_JBU(PjbuRaw);
|
||||
#endif
|
||||
JU_JPSETADT(&JPNull, 0, 0, JU_JPTYPE(Pjp) - cJU_JPBRANCH_B2 + cJU_JPNULL1);
|
||||
|
||||
// Get the pointer to the BranchB:
|
||||
|
||||
PjbbRaw = (Pjbb_t) (Pjp->jp_Addr);
|
||||
Pjbb = P_JBB(PjbbRaw);
|
||||
|
||||
// Set the pointer to the Uncompressed branch
|
||||
#ifdef JU_STAGED_EXP
|
||||
PDstJP = BranchU.jbu_jp;
|
||||
#else
|
||||
PDstJP = Pjbu->jbu_jp;
|
||||
#endif
|
||||
for (ii = 0; ii < cJU_NUMSUBEXPB; ii++)
|
||||
{
|
||||
Pjp_t PjpA;
|
||||
Pjp_t PjpB;
|
||||
|
||||
PjpB = PjpA = P_JP(JU_JBB_PJP(Pjbb, ii));
|
||||
|
||||
// Get the bitmap for this subexpanse
|
||||
BitMap = JU_JBB_BITMAP(Pjbb, ii);
|
||||
|
||||
// NULL empty subexpanses
|
||||
if (BitMap == 0)
|
||||
{
|
||||
// But, fill with NULLs
|
||||
for (jj = 0; jj < cJU_BITSPERSUBEXPB; jj++)
|
||||
{
|
||||
PDstJP[jj] = JPNull;
|
||||
}
|
||||
PDstJP += cJU_BITSPERSUBEXPB;
|
||||
continue;
|
||||
}
|
||||
// Check if Uncompressed subexpanse
|
||||
if (BitMap == cJU_FULLBITMAPB)
|
||||
{
|
||||
// Copy subexpanse to the Uncompressed branch intact
|
||||
JU_COPYMEM(PDstJP, PjpA, cJU_BITSPERSUBEXPB);
|
||||
|
||||
// Bump to next subexpanse
|
||||
PDstJP += cJU_BITSPERSUBEXPB;
|
||||
|
||||
// Set length of subexpanse
|
||||
jj = cJU_BITSPERSUBEXPB;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (jj = 0; jj < cJU_BITSPERSUBEXPB; jj++)
|
||||
{
|
||||
// Copy JP or NULLJP depending on bit
|
||||
if (BitMap & 1) { *PDstJP = *PjpA++; }
|
||||
else { *PDstJP = JPNull; }
|
||||
|
||||
PDstJP++; // advance to next JP
|
||||
BitMap >>= 1;
|
||||
}
|
||||
jj = PjpA - PjpB;
|
||||
}
|
||||
|
||||
// Free the subexpanse:
|
||||
|
||||
j__udyFreeJBBJP(JU_JBB_PJP(Pjbb, ii), jj, Pjpm);
|
||||
|
||||
} // for each JP in BranchU
|
||||
|
||||
#ifdef JU_STAGED_EXP
|
||||
|
||||
// Allocate memory for a BranchU:
|
||||
|
||||
PjbuRaw = j__udyAllocJBU(Pjpm);
|
||||
if (PjbuRaw == (Pjbu_t) NULL) return(-1);
|
||||
Pjbu = P_JBU(PjbuRaw);
|
||||
|
||||
// Copy staged branch to newly allocated branch:
|
||||
//
|
||||
// TBD: I think this code is broken.
|
||||
|
||||
*Pjbu = BranchU;
|
||||
|
||||
#endif // JU_STAGED_EXP
|
||||
|
||||
// Finally free the BranchB and put the BranchU in its place:
|
||||
|
||||
j__udyFreeJBB(PjbbRaw, Pjpm);
|
||||
|
||||
Pjp->jp_Addr = (Word_t) PjbuRaw;
|
||||
Pjp->jp_Type += cJU_JPBRANCH_U - cJU_JPBRANCH_B;
|
||||
|
||||
return(1);
|
||||
|
||||
} // j__udyCreateBranchU()
|
1206
libnetdata/libjudy/src/JudyL/JudyLDecascade.c
Normal file
1206
libnetdata/libjudy/src/JudyL/JudyLDecascade.c
Normal file
File diff suppressed because it is too large
Load diff
2146
libnetdata/libjudy/src/JudyL/JudyLDel.c
Normal file
2146
libnetdata/libjudy/src/JudyL/JudyLDel.c
Normal file
File diff suppressed because it is too large
Load diff
213
libnetdata/libjudy/src/JudyL/JudyLFirst.c
Normal file
213
libnetdata/libjudy/src/JudyL/JudyLFirst.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.12 $ $Source: /judy/src/JudyCommon/JudyFirst.c $
|
||||
//
|
||||
// Judy*First[Empty]() and Judy*Last[Empty]() routines for Judy1 and JudyL.
|
||||
// Compile with one of -DJUDY1 or -DJUDYL.
|
||||
//
|
||||
// These are inclusive versions of Judy*Next[Empty]() and Judy*Prev[Empty]().
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y 1 F I R S T
|
||||
// J U D Y L F I R S T
|
||||
//
|
||||
// See the manual entry for details.
|
||||
|
||||
#ifdef JUDY1
|
||||
FUNCTION int Judy1First
|
||||
#else
|
||||
FUNCTION PPvoid_t JudyLFirst
|
||||
#endif
|
||||
(
|
||||
Pcvoid_t PArray, // Judy array to search.
|
||||
Word_t * PIndex, // starting point and result.
|
||||
PJError_t PJError // optional, for returning error info.
|
||||
)
|
||||
{
|
||||
if (PIndex == (PWord_t) NULL) // caller error:
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
|
||||
#ifdef JUDY1
|
||||
switch (Judy1Test(PArray, *PIndex, PJError))
|
||||
{
|
||||
case 1: return(1); // found *PIndex itself.
|
||||
case 0: return(Judy1Next(PArray, PIndex, PJError));
|
||||
default: return(JERRI);
|
||||
}
|
||||
#else
|
||||
{
|
||||
PPvoid_t PValue;
|
||||
|
||||
if ((PValue = JudyLGet(PArray, *PIndex, PJError)) == PPJERR)
|
||||
return(PPJERR);
|
||||
|
||||
if (PValue != (PPvoid_t) NULL) return(PValue); // found *PIndex.
|
||||
|
||||
return(JudyLNext(PArray, PIndex, PJError));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Judy1First() / JudyLFirst()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y 1 L A S T
|
||||
// J U D Y L L A S T
|
||||
//
|
||||
// See the manual entry for details.
|
||||
|
||||
#ifdef JUDY1
|
||||
FUNCTION int Judy1Last(
|
||||
#else
|
||||
FUNCTION PPvoid_t JudyLLast(
|
||||
#endif
|
||||
Pcvoid_t PArray, // Judy array to search.
|
||||
Word_t * PIndex, // starting point and result.
|
||||
PJError_t PJError) // optional, for returning error info.
|
||||
{
|
||||
if (PIndex == (PWord_t) NULL)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX); // caller error.
|
||||
JUDY1CODE(return(JERRI );)
|
||||
JUDYLCODE(return(PPJERR);)
|
||||
}
|
||||
|
||||
#ifdef JUDY1
|
||||
switch (Judy1Test(PArray, *PIndex, PJError))
|
||||
{
|
||||
case 1: return(1); // found *PIndex itself.
|
||||
case 0: return(Judy1Prev(PArray, PIndex, PJError));
|
||||
default: return(JERRI);
|
||||
}
|
||||
#else
|
||||
{
|
||||
PPvoid_t PValue;
|
||||
|
||||
if ((PValue = JudyLGet(PArray, *PIndex, PJError)) == PPJERR)
|
||||
return(PPJERR);
|
||||
|
||||
if (PValue != (PPvoid_t) NULL) return(PValue); // found *PIndex.
|
||||
|
||||
return(JudyLPrev(PArray, PIndex, PJError));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Judy1Last() / JudyLLast()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y 1 F I R S T E M P T Y
|
||||
// J U D Y L F I R S T E M P T Y
|
||||
//
|
||||
// See the manual entry for details.
|
||||
|
||||
#ifdef JUDY1
|
||||
FUNCTION int Judy1FirstEmpty(
|
||||
#else
|
||||
FUNCTION int JudyLFirstEmpty(
|
||||
#endif
|
||||
Pcvoid_t PArray, // Judy array to search.
|
||||
Word_t * PIndex, // starting point and result.
|
||||
PJError_t PJError) // optional, for returning error info.
|
||||
{
|
||||
if (PIndex == (PWord_t) NULL) // caller error:
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX);
|
||||
return(JERRI);
|
||||
}
|
||||
|
||||
#ifdef JUDY1
|
||||
switch (Judy1Test(PArray, *PIndex, PJError))
|
||||
{
|
||||
case 0: return(1); // found *PIndex itself.
|
||||
case 1: return(Judy1NextEmpty(PArray, PIndex, PJError));
|
||||
default: return(JERRI);
|
||||
}
|
||||
#else
|
||||
{
|
||||
PPvoid_t PValue;
|
||||
|
||||
if ((PValue = JudyLGet(PArray, *PIndex, PJError)) == PPJERR)
|
||||
return(JERRI);
|
||||
|
||||
if (PValue == (PPvoid_t) NULL) return(1); // found *PIndex.
|
||||
|
||||
return(JudyLNextEmpty(PArray, PIndex, PJError));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Judy1FirstEmpty() / JudyLFirstEmpty()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y 1 L A S T E M P T Y
|
||||
// J U D Y L L A S T E M P T Y
|
||||
//
|
||||
// See the manual entry for details.
|
||||
|
||||
#ifdef JUDY1
|
||||
FUNCTION int Judy1LastEmpty(
|
||||
#else
|
||||
FUNCTION int JudyLLastEmpty(
|
||||
#endif
|
||||
Pcvoid_t PArray, // Judy array to search.
|
||||
Word_t * PIndex, // starting point and result.
|
||||
PJError_t PJError) // optional, for returning error info.
|
||||
{
|
||||
if (PIndex == (PWord_t) NULL)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_NULLPINDEX); // caller error.
|
||||
return(JERRI);
|
||||
}
|
||||
|
||||
#ifdef JUDY1
|
||||
switch (Judy1Test(PArray, *PIndex, PJError))
|
||||
{
|
||||
case 0: return(1); // found *PIndex itself.
|
||||
case 1: return(Judy1PrevEmpty(PArray, PIndex, PJError));
|
||||
default: return(JERRI);
|
||||
}
|
||||
#else
|
||||
{
|
||||
PPvoid_t PValue;
|
||||
|
||||
if ((PValue = JudyLGet(PArray, *PIndex, PJError)) == PPJERR)
|
||||
return(JERRI);
|
||||
|
||||
if (PValue == (PPvoid_t) NULL) return(1); // found *PIndex.
|
||||
|
||||
return(JudyLPrevEmpty(PArray, PIndex, PJError));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Judy1LastEmpty() / JudyLLastEmpty()
|
363
libnetdata/libjudy/src/JudyL/JudyLFreeArray.c
Normal file
363
libnetdata/libjudy/src/JudyL/JudyLFreeArray.c
Normal file
|
@ -0,0 +1,363 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.51 $ $Source: /judy/src/JudyCommon/JudyFreeArray.c $
|
||||
//
|
||||
// Judy1FreeArray() and JudyLFreeArray() functions for Judy1 and JudyL.
|
||||
// Compile with one of -DJUDY1 or -DJUDYL.
|
||||
// Return the number of bytes freed from the array.
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
#include "JudyPrivate1L.h"
|
||||
|
||||
DBGCODE(extern void JudyCheckPop(Pvoid_t PArray);)
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y 1 F R E E A R R A Y
|
||||
// J U D Y L F R E E A R R A Y
|
||||
//
|
||||
// See the Judy*(3C) manual entry for details.
|
||||
//
|
||||
// This code is written recursively, at least at first, because thats much
|
||||
// simpler. Hope its fast enough.
|
||||
|
||||
#ifdef JUDY1
|
||||
FUNCTION Word_t Judy1FreeArray
|
||||
#else
|
||||
FUNCTION Word_t JudyLFreeArray
|
||||
#endif
|
||||
(
|
||||
PPvoid_t PPArray, // array to free.
|
||||
PJError_t PJError // optional, for returning error info.
|
||||
)
|
||||
{
|
||||
jpm_t jpm; // local to accumulate free statistics.
|
||||
|
||||
// CHECK FOR NULL POINTER (error by caller):
|
||||
|
||||
if (PPArray == (PPvoid_t) NULL)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_NULLPPARRAY);
|
||||
return(JERR);
|
||||
}
|
||||
|
||||
DBGCODE(JudyCheckPop(*PPArray);)
|
||||
|
||||
// Zero jpm.jpm_Pop0 (meaning the array will be empty in a moment) for accurate
|
||||
// logging in TRACEMI2.
|
||||
|
||||
jpm.jpm_Pop0 = 0; // see above.
|
||||
jpm.jpm_TotalMemWords = 0; // initialize memory freed.
|
||||
|
||||
// Empty array:
|
||||
|
||||
if (P_JLW(*PPArray) == (Pjlw_t) NULL) return(0);
|
||||
|
||||
// PROCESS TOP LEVEL "JRP" BRANCHES AND LEAF:
|
||||
|
||||
if (JU_LEAFW_POP0(*PPArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
|
||||
{
|
||||
Pjlw_t Pjlw = P_JLW(*PPArray); // first word of leaf.
|
||||
|
||||
j__udyFreeJLW(Pjlw, Pjlw[0] + 1, &jpm);
|
||||
*PPArray = (Pvoid_t) NULL; // make an empty array.
|
||||
return (-(jpm.jpm_TotalMemWords * cJU_BYTESPERWORD)); // see above.
|
||||
}
|
||||
else
|
||||
|
||||
// Rootstate leaves: just free the leaf:
|
||||
|
||||
// Common code for returning the amount of memory freed.
|
||||
//
|
||||
// Note: In a an ordinary LEAFW, pop0 = *PPArray[0].
|
||||
//
|
||||
// Accumulate (negative) words freed, while freeing objects.
|
||||
// Return the positive bytes freed.
|
||||
|
||||
{
|
||||
Pjpm_t Pjpm = P_JPM(*PPArray);
|
||||
Word_t TotalMem = Pjpm->jpm_TotalMemWords;
|
||||
|
||||
j__udyFreeSM(&(Pjpm->jpm_JP), &jpm); // recurse through tree.
|
||||
j__udyFreeJPM(Pjpm, &jpm);
|
||||
|
||||
// Verify the array was not corrupt. This means that amount of memory freed
|
||||
// (which is negative) is equal to the initial amount:
|
||||
|
||||
if (TotalMem + jpm.jpm_TotalMemWords)
|
||||
{
|
||||
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT);
|
||||
return(JERR);
|
||||
}
|
||||
|
||||
*PPArray = (Pvoid_t) NULL; // make an empty array.
|
||||
return (TotalMem * cJU_BYTESPERWORD);
|
||||
}
|
||||
|
||||
} // Judy1FreeArray() / JudyLFreeArray()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// __ J U D Y F R E E S M
|
||||
//
|
||||
// Given a pointer to a JP, recursively visit and free (depth first) all nodes
|
||||
// in a Judy array BELOW the JP, but not the JP itself. Accumulate in *Pjpm
|
||||
// the total words freed (as a negative value). "SM" = State Machine.
|
||||
//
|
||||
// Note: Corruption is not detected at this level because during a FreeArray,
|
||||
// if the code hasnt already core dumped, its better to remain silent, even
|
||||
// if some memory has not been freed, than to bother the caller about the
|
||||
// corruption. TBD: Is this true? If not, must list all legitimate JPNULL
|
||||
// and JPIMMED above first, and revert to returning bool_t (see 4.34).
|
||||
|
||||
FUNCTION void j__udyFreeSM(
|
||||
Pjp_t Pjp, // top of Judy (top-state).
|
||||
Pjpm_t Pjpm) // to return words freed.
|
||||
{
|
||||
Word_t Pop1;
|
||||
|
||||
switch (JU_JPTYPE(Pjp))
|
||||
{
|
||||
|
||||
#ifdef JUDY1
|
||||
|
||||
// FULL EXPANSE -- nothing to free for this jp_Type.
|
||||
|
||||
case cJ1_JPFULLPOPU1:
|
||||
break;
|
||||
#endif
|
||||
|
||||
// JUDY BRANCH -- free the sub-tree depth first:
|
||||
|
||||
// LINEAR BRANCH -- visit each JP in the JBLs list, then free the JBL:
|
||||
//
|
||||
// Note: There are no null JPs in a JBL.
|
||||
|
||||
case cJU_JPBRANCH_L:
|
||||
case cJU_JPBRANCH_L2:
|
||||
case cJU_JPBRANCH_L3:
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPBRANCH_L4:
|
||||
case cJU_JPBRANCH_L5:
|
||||
case cJU_JPBRANCH_L6:
|
||||
case cJU_JPBRANCH_L7:
|
||||
#endif // JU_64BIT
|
||||
{
|
||||
Pjbl_t Pjbl = P_JBL(Pjp->jp_Addr);
|
||||
Word_t offset;
|
||||
|
||||
for (offset = 0; offset < Pjbl->jbl_NumJPs; ++offset)
|
||||
j__udyFreeSM((Pjbl->jbl_jp) + offset, Pjpm);
|
||||
|
||||
j__udyFreeJBL((Pjbl_t) (Pjp->jp_Addr), Pjpm);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// BITMAP BRANCH -- visit each JP in the JBBs list based on the bitmap, also
|
||||
//
|
||||
// Note: There are no null JPs in a JBB.
|
||||
|
||||
case cJU_JPBRANCH_B:
|
||||
case cJU_JPBRANCH_B2:
|
||||
case cJU_JPBRANCH_B3:
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPBRANCH_B4:
|
||||
case cJU_JPBRANCH_B5:
|
||||
case cJU_JPBRANCH_B6:
|
||||
case cJU_JPBRANCH_B7:
|
||||
#endif // JU_64BIT
|
||||
{
|
||||
Word_t subexp;
|
||||
Word_t offset;
|
||||
Word_t jpcount;
|
||||
|
||||
Pjbb_t Pjbb = P_JBB(Pjp->jp_Addr);
|
||||
|
||||
for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
|
||||
{
|
||||
jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
|
||||
|
||||
if (jpcount)
|
||||
{
|
||||
for (offset = 0; offset < jpcount; ++offset)
|
||||
{
|
||||
j__udyFreeSM(P_JP(JU_JBB_PJP(Pjbb, subexp)) + offset,
|
||||
Pjpm);
|
||||
}
|
||||
j__udyFreeJBBJP(JU_JBB_PJP(Pjbb, subexp), jpcount, Pjpm);
|
||||
}
|
||||
}
|
||||
j__udyFreeJBB((Pjbb_t) (Pjp->jp_Addr), Pjpm);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// UNCOMPRESSED BRANCH -- visit each JP in the JBU array, then free the JBU
|
||||
// itself:
|
||||
//
|
||||
// Note: Null JPs are handled during recursion at a lower state.
|
||||
|
||||
case cJU_JPBRANCH_U:
|
||||
case cJU_JPBRANCH_U2:
|
||||
case cJU_JPBRANCH_U3:
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPBRANCH_U4:
|
||||
case cJU_JPBRANCH_U5:
|
||||
case cJU_JPBRANCH_U6:
|
||||
case cJU_JPBRANCH_U7:
|
||||
#endif // JU_64BIT
|
||||
{
|
||||
Word_t offset;
|
||||
Pjbu_t Pjbu = P_JBU(Pjp->jp_Addr);
|
||||
|
||||
for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
|
||||
j__udyFreeSM((Pjbu->jbu_jp) + offset, Pjpm);
|
||||
|
||||
j__udyFreeJBU((Pjbu_t) (Pjp->jp_Addr), Pjpm);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// -- Cases below here terminate and do not recurse. --
|
||||
|
||||
|
||||
// LINEAR LEAF -- just free the leaf; size is computed from jp_Type:
|
||||
//
|
||||
// Note: cJU_JPLEAF1 is a special case, see discussion in ../Judy1/Judy1.h
|
||||
|
||||
#if (defined(JUDYL) || (! defined(JU_64BIT)))
|
||||
case cJU_JPLEAF1:
|
||||
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
|
||||
j__udyFreeJLL1((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case cJU_JPLEAF2:
|
||||
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
|
||||
j__udyFreeJLL2((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
|
||||
case cJU_JPLEAF3:
|
||||
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
|
||||
j__udyFreeJLL3((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPLEAF4:
|
||||
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
|
||||
j__udyFreeJLL4((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
|
||||
case cJU_JPLEAF5:
|
||||
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
|
||||
j__udyFreeJLL5((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
|
||||
case cJU_JPLEAF6:
|
||||
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
|
||||
j__udyFreeJLL6((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
|
||||
case cJU_JPLEAF7:
|
||||
Pop1 = JU_JPLEAF_POP0(Pjp) + 1;
|
||||
j__udyFreeJLL7((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
#endif // JU_64BIT
|
||||
|
||||
|
||||
// BITMAP LEAF -- free sub-expanse arrays of JPs, then free the JBB.
|
||||
|
||||
case cJU_JPLEAF_B1:
|
||||
{
|
||||
#ifdef JUDYL
|
||||
Word_t subexp;
|
||||
Word_t jpcount;
|
||||
Pjlb_t Pjlb = P_JLB(Pjp->jp_Addr);
|
||||
|
||||
// Free the value areas in the bitmap leaf:
|
||||
|
||||
for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp)
|
||||
{
|
||||
jpcount = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp));
|
||||
|
||||
if (jpcount)
|
||||
j__udyLFreeJV(JL_JLB_PVALUE(Pjlb, subexp), jpcount, Pjpm);
|
||||
}
|
||||
#endif // JUDYL
|
||||
|
||||
j__udyFreeJLB1((Pjlb_t) (Pjp->jp_Addr), Pjpm);
|
||||
break;
|
||||
|
||||
} // case cJU_JPLEAF_B1
|
||||
|
||||
#ifdef JUDYL
|
||||
|
||||
|
||||
// IMMED*:
|
||||
//
|
||||
// For JUDYL, all non JPIMMED_*_01s have a LeafV which must be freed:
|
||||
|
||||
case cJU_JPIMMED_1_02:
|
||||
case cJU_JPIMMED_1_03:
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPIMMED_1_04:
|
||||
case cJU_JPIMMED_1_05:
|
||||
case cJU_JPIMMED_1_06:
|
||||
case cJU_JPIMMED_1_07:
|
||||
#endif
|
||||
Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_1_02 + 2;
|
||||
j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPIMMED_2_02:
|
||||
case cJU_JPIMMED_2_03:
|
||||
|
||||
Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_2_02 + 2;
|
||||
j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), Pop1, Pjpm);
|
||||
break;
|
||||
|
||||
case cJU_JPIMMED_3_02:
|
||||
j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), 2, Pjpm);
|
||||
break;
|
||||
|
||||
#endif // JU_64BIT
|
||||
#endif // JUDYL
|
||||
|
||||
|
||||
// OTHER JPNULL, JPIMMED, OR UNEXPECTED TYPE -- nothing to free for this type:
|
||||
//
|
||||
// Note: Lump together no-op and invalid JP types; see function header
|
||||
// comments.
|
||||
|
||||
default: break;
|
||||
|
||||
} // switch (JU_JPTYPE(Pjp))
|
||||
|
||||
} // j__udyFreeSM()
|
1094
libnetdata/libjudy/src/JudyL/JudyLGet.c
Normal file
1094
libnetdata/libjudy/src/JudyL/JudyLGet.c
Normal file
File diff suppressed because it is too large
Load diff
1873
libnetdata/libjudy/src/JudyL/JudyLIns.c
Normal file
1873
libnetdata/libjudy/src/JudyL/JudyLIns.c
Normal file
File diff suppressed because it is too large
Load diff
1178
libnetdata/libjudy/src/JudyL/JudyLInsArray.c
Normal file
1178
libnetdata/libjudy/src/JudyL/JudyLInsArray.c
Normal file
File diff suppressed because it is too large
Load diff
135
libnetdata/libjudy/src/JudyL/JudyLInsertBranch.c
Normal file
135
libnetdata/libjudy/src/JudyL/JudyLInsertBranch.c
Normal file
|
@ -0,0 +1,135 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.17 $ $Source: /judy/src/JudyCommon/JudyInsertBranch.c $
|
||||
|
||||
// BranchL insertion functions for Judy1 and JudyL.
|
||||
// Compile with one of -DJUDY1 or -DJUDYL.
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
#include "JudyPrivate1L.h"
|
||||
|
||||
extern int j__udyCreateBranchL(Pjp_t, Pjp_t, uint8_t *, Word_t, Pvoid_t);
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// __ J U D Y I N S E R T B R A N C H
|
||||
//
|
||||
// Insert 2-element BranchL in between Pjp and Pjp->jp_Addr.
|
||||
//
|
||||
// Return -1 if out of memory, otherwise return 1.
|
||||
|
||||
FUNCTION int j__udyInsertBranch(
|
||||
Pjp_t Pjp, // JP containing narrow pointer.
|
||||
Word_t Index, // outlier to Pjp.
|
||||
Word_t BranchLevel, // of what JP points to, mapped from JP type.
|
||||
Pjpm_t Pjpm) // for global accounting.
|
||||
{
|
||||
jp_t JP2 [2];
|
||||
jp_t JP;
|
||||
Pjp_t PjpNull;
|
||||
Word_t XorExp;
|
||||
Word_t Inew, Iold;
|
||||
Word_t DCDMask; // initially for original BranchLevel.
|
||||
int Ret;
|
||||
uint8_t Exp2[2];
|
||||
uint8_t DecodeByteN, DecodeByteO;
|
||||
|
||||
// Get the current mask for the DCD digits:
|
||||
|
||||
DCDMask = cJU_DCDMASK(BranchLevel);
|
||||
|
||||
// Obtain Dcd bits that differ between Index and JP, shifted so the
|
||||
// digit for BranchLevel is the LSB:
|
||||
|
||||
XorExp = ((Index ^ JU_JPDCDPOP0(Pjp)) & (cJU_ALLONES >> cJU_BITSPERBYTE))
|
||||
>> (BranchLevel * cJU_BITSPERBYTE);
|
||||
assert(XorExp); // Index must be an outlier.
|
||||
|
||||
// Count levels between object under narrow pointer and the level at which
|
||||
// the outlier diverges from it, which is always at least initial
|
||||
// BranchLevel + 1, to end up with the level (JP type) at which to insert
|
||||
// the new intervening BranchL:
|
||||
|
||||
do { ++BranchLevel; } while ((XorExp >>= cJU_BITSPERBYTE));
|
||||
assert((BranchLevel > 1) && (BranchLevel < cJU_ROOTSTATE));
|
||||
|
||||
// Get the MSB (highest digit) that differs between the old expanse and
|
||||
// the new Index to insert:
|
||||
|
||||
DecodeByteO = JU_DIGITATSTATE(JU_JPDCDPOP0(Pjp), BranchLevel);
|
||||
DecodeByteN = JU_DIGITATSTATE(Index, BranchLevel);
|
||||
|
||||
assert(DecodeByteO != DecodeByteN);
|
||||
|
||||
// Determine sorted order for old expanse and new Index digits:
|
||||
|
||||
if (DecodeByteN > DecodeByteO) { Iold = 0; Inew = 1; }
|
||||
else { Iold = 1; Inew = 0; }
|
||||
|
||||
// Copy old JP into staging area for new Branch
|
||||
JP2 [Iold] = *Pjp;
|
||||
Exp2[Iold] = DecodeByteO;
|
||||
Exp2[Inew] = DecodeByteN;
|
||||
|
||||
// Create a 2 Expanse Linear branch
|
||||
//
|
||||
// Note: Pjp->jp_Addr is set by j__udyCreateBranchL()
|
||||
|
||||
Ret = j__udyCreateBranchL(Pjp, JP2, Exp2, 2, Pjpm);
|
||||
if (Ret == -1) return(-1);
|
||||
|
||||
// Get Pjp to the NULL of where to do insert
|
||||
PjpNull = ((P_JBL(Pjp->jp_Addr))->jbl_jp) + Inew;
|
||||
|
||||
// Convert to a cJU_JPIMMED_*_01 at the correct level:
|
||||
// Build JP and set type below to: cJU_JPIMMED_X_01
|
||||
JU_JPSETADT(PjpNull, 0, Index, cJU_JPIMMED_1_01 - 2 + BranchLevel);
|
||||
|
||||
// Return pointer to Value area in cJU_JPIMMED_X_01
|
||||
JUDYLCODE(Pjpm->jpm_PValue = (Pjv_t) PjpNull;)
|
||||
|
||||
// The old JP now points to a BranchL that is at higher level. Therefore
|
||||
// it contains excess DCD bits (in the least significant position) that
|
||||
// must be removed (zeroed); that is, they become part of the Pop0
|
||||
// subfield. Note that the remaining (lower) bytes in the Pop0 field do
|
||||
// not change.
|
||||
//
|
||||
// Take from the old DCDMask, which went "down" to a lower BranchLevel,
|
||||
// and zero any high bits that are still in the mask at the new, higher
|
||||
// BranchLevel; then use this mask to zero the bits in jp_DcdPopO:
|
||||
|
||||
// Set old JP to a BranchL at correct level
|
||||
|
||||
Pjp->jp_Type = cJU_JPBRANCH_L2 - 2 + BranchLevel;
|
||||
DCDMask ^= cJU_DCDMASK(BranchLevel);
|
||||
DCDMask = ~DCDMask & JU_JPDCDPOP0(Pjp);
|
||||
JP = *Pjp;
|
||||
JU_JPSETADT(Pjp, JP.jp_Addr, DCDMask, JP.jp_Type);
|
||||
|
||||
return(1);
|
||||
|
||||
} // j__udyInsertBranch()
|
782
libnetdata/libjudy/src/JudyL/JudyLMallocIF.c
Normal file
782
libnetdata/libjudy/src/JudyL/JudyLMallocIF.c
Normal file
|
@ -0,0 +1,782 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.45 $ $Source: /judy/src/JudyCommon/JudyMallocIF.c $
|
||||
//
|
||||
// Judy malloc/free interface functions for Judy1 and JudyL.
|
||||
//
|
||||
// Compile with one of -DJUDY1 or -DJUDYL.
|
||||
//
|
||||
// Compile with -DTRACEMI (Malloc Interface) to turn on tracing of malloc/free
|
||||
// calls at the interface level. (See also TRACEMF in lower-level code.)
|
||||
// Use -DTRACEMI2 for a terser format suitable for trace analysis.
|
||||
//
|
||||
// There can be malloc namespace bits in the LSBs of "raw" addresses from most,
|
||||
// but not all, of the j__udy*Alloc*() functions; see also JudyPrivate.h. To
|
||||
// test the Judy code, compile this file with -DMALLOCBITS and use debug flavor
|
||||
// only (for assertions). This test ensures that (a) all callers properly mask
|
||||
// the namespace bits out before dereferencing a pointer (or else a core dump
|
||||
// occurs), and (b) all callers send "raw" (unmasked) addresses to
|
||||
// j__udy*Free*() calls.
|
||||
//
|
||||
// Note: Currently -DDEBUG turns on MALLOCBITS automatically.
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
#include "JudyPrivate1L.h"
|
||||
|
||||
// Set "hidden" global j__uMaxWords to the maximum number of words to allocate
|
||||
// to any one array (large enough to have a JPM, otherwise j__uMaxWords is
|
||||
// ignored), to trigger a fake malloc error when the number is exceeded. Note,
|
||||
// this code is always executed, not #ifdefd, because its virtually free.
|
||||
//
|
||||
// Note: To keep the MALLOC macro faster and simpler, set j__uMaxWords to
|
||||
// MAXINT, not zero, by default.
|
||||
|
||||
Word_t j__uMaxWords = ~0UL;
|
||||
|
||||
// This macro hides the faking of a malloc failure:
|
||||
//
|
||||
// Note: To keep this fast, just compare WordsPrev to j__uMaxWords without the
|
||||
// complexity of first adding WordsNow, meaning the trigger point is not
|
||||
// exactly where you might assume, but it shouldnt matter.
|
||||
|
||||
#define MALLOC(MallocFunc,WordsPrev,WordsNow) \
|
||||
(((WordsPrev) > j__uMaxWords) ? 0UL : MallocFunc(WordsNow))
|
||||
|
||||
// Clear words starting at address:
|
||||
//
|
||||
// Note: Only use this for objects that care; in other cases, it doesnt
|
||||
// matter if the objects memory is pre-zeroed.
|
||||
|
||||
#define ZEROWORDS(Addr,Words) \
|
||||
{ \
|
||||
Word_t Words__ = (Words); \
|
||||
PWord_t Addr__ = (PWord_t) (Addr); \
|
||||
while (Words__--) *Addr__++ = 0UL; \
|
||||
}
|
||||
|
||||
#ifdef TRACEMI
|
||||
|
||||
// TRACING SUPPORT:
|
||||
//
|
||||
// Note: For TRACEMI, use a format for address printing compatible with other
|
||||
// tracing facilities; in particular, %x not %lx, to truncate the "noisy" high
|
||||
// part on 64-bit systems.
|
||||
//
|
||||
// TBD: The trace macros need fixing for alternate address types.
|
||||
//
|
||||
// Note: TRACEMI2 supports trace analysis no matter the underlying malloc/free
|
||||
// engine used.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static Word_t j__udyMemSequence = 0L; // event sequence number.
|
||||
|
||||
#define TRACE_ALLOC5(a,b,c,d,e) (void) printf(a, (b), c, d)
|
||||
#define TRACE_FREE5( a,b,c,d,e) (void) printf(a, (b), c, d)
|
||||
#define TRACE_ALLOC6(a,b,c,d,e,f) (void) printf(a, (b), c, d, e)
|
||||
#define TRACE_FREE6( a,b,c,d,e,f) (void) printf(a, (b), c, d, e)
|
||||
|
||||
#else
|
||||
|
||||
#ifdef TRACEMI2
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define b_pw cJU_BYTESPERWORD
|
||||
|
||||
#define TRACE_ALLOC5(a,b,c,d,e) \
|
||||
(void) printf("a %lx %lx %lx\n", (b), (d) * b_pw, e)
|
||||
#define TRACE_FREE5( a,b,c,d,e) \
|
||||
(void) printf("f %lx %lx %lx\n", (b), (d) * b_pw, e)
|
||||
#define TRACE_ALLOC6(a,b,c,d,e,f) \
|
||||
(void) printf("a %lx %lx %lx\n", (b), (e) * b_pw, f)
|
||||
#define TRACE_FREE6( a,b,c,d,e,f) \
|
||||
(void) printf("f %lx %lx %lx\n", (b), (e) * b_pw, f)
|
||||
|
||||
static Word_t j__udyMemSequence = 0L; // event sequence number.
|
||||
|
||||
#else
|
||||
|
||||
#define TRACE_ALLOC5(a,b,c,d,e) // null.
|
||||
#define TRACE_FREE5( a,b,c,d,e) // null.
|
||||
#define TRACE_ALLOC6(a,b,c,d,e,f) // null.
|
||||
#define TRACE_FREE6( a,b,c,d,e,f) // null.
|
||||
|
||||
#endif // ! TRACEMI2
|
||||
#endif // ! TRACEMI
|
||||
|
||||
|
||||
// MALLOC NAMESPACE SUPPORT:
|
||||
|
||||
#if (defined(DEBUG) && (! defined(MALLOCBITS))) // for now, DEBUG => MALLOCBITS:
|
||||
#define MALLOCBITS 1
|
||||
#endif
|
||||
|
||||
#ifdef MALLOCBITS
|
||||
#define MALLOCBITS_VALUE 0x3 // bit pattern to use.
|
||||
#define MALLOCBITS_MASK 0x7 // note: matches mask__ in JudyPrivate.h.
|
||||
|
||||
#define MALLOCBITS_SET( Type,Addr) \
|
||||
((Addr) = (Type) ((Word_t) (Addr) | MALLOCBITS_VALUE))
|
||||
#define MALLOCBITS_TEST(Type,Addr) \
|
||||
assert((((Word_t) (Addr)) & MALLOCBITS_MASK) == MALLOCBITS_VALUE); \
|
||||
((Addr) = (Type) ((Word_t) (Addr) & ~MALLOCBITS_VALUE))
|
||||
#else
|
||||
#define MALLOCBITS_SET( Type,Addr) // null.
|
||||
#define MALLOCBITS_TEST(Type,Addr) // null.
|
||||
#endif
|
||||
|
||||
|
||||
// SAVE ERROR INFORMATION IN A Pjpm:
|
||||
//
|
||||
// "Small" (invalid) Addr values are used to distinguish overrun and no-mem
|
||||
// errors. (TBD, non-zero invalid values are no longer returned from
|
||||
// lower-level functions, that is, JU_ERRNO_OVERRUN is no longer detected.)
|
||||
|
||||
#define J__UDYSETALLOCERROR(Addr) \
|
||||
{ \
|
||||
JU_ERRID(Pjpm) = __LINE__; \
|
||||
if ((Word_t) (Addr) > 0) JU_ERRNO(Pjpm) = JU_ERRNO_OVERRUN; \
|
||||
else JU_ERRNO(Pjpm) = JU_ERRNO_NOMEM; \
|
||||
return(0); \
|
||||
}
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// ALLOCATION FUNCTIONS:
|
||||
//
|
||||
// To help the compiler catch coding errors, each function returns a specific
|
||||
// object type.
|
||||
//
|
||||
// Note: Only j__udyAllocJPM() and j__udyAllocJLW() return multiple values <=
|
||||
// sizeof(Word_t) to indicate the type of memory allocation failure. Other
|
||||
// allocation functions convert this failure to a JU_ERRNO.
|
||||
|
||||
|
||||
// Note: Unlike other j__udyAlloc*() functions, Pjpms are returned non-raw,
|
||||
// that is, without malloc namespace or root pointer type bits:
|
||||
|
||||
FUNCTION Pjpm_t j__udyAllocJPM(void)
|
||||
{
|
||||
Word_t Words = (sizeof(jpm_t) + cJU_BYTESPERWORD - 1) / cJU_BYTESPERWORD;
|
||||
Pjpm_t Pjpm = (Pjpm_t) MALLOC(JudyMalloc, Words, Words);
|
||||
|
||||
assert((Words * cJU_BYTESPERWORD) == sizeof(jpm_t));
|
||||
|
||||
if ((Word_t) Pjpm > sizeof(Word_t))
|
||||
{
|
||||
ZEROWORDS(Pjpm, Words);
|
||||
Pjpm->jpm_TotalMemWords = Words;
|
||||
}
|
||||
|
||||
TRACE_ALLOC5("0x%x %8lu = j__udyAllocJPM(), Words = %lu\n",
|
||||
Pjpm, j__udyMemSequence++, Words, cJU_LEAFW_MAXPOP1 + 1);
|
||||
// MALLOCBITS_SET(Pjpm_t, Pjpm); // see above.
|
||||
return(Pjpm);
|
||||
|
||||
} // j__udyAllocJPM()
|
||||
|
||||
|
||||
FUNCTION Pjbl_t j__udyAllocJBL(Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = sizeof(jbl_t) / cJU_BYTESPERWORD;
|
||||
Pjbl_t PjblRaw = (Pjbl_t) MALLOC(JudyMallocVirtual,
|
||||
Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
assert((Words * cJU_BYTESPERWORD) == sizeof(jbl_t));
|
||||
|
||||
if ((Word_t) PjblRaw > sizeof(Word_t))
|
||||
{
|
||||
ZEROWORDS(P_JBL(PjblRaw), Words);
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjblRaw); }
|
||||
|
||||
TRACE_ALLOC5("0x%x %8lu = j__udyAllocJBL(), Words = %lu\n", PjblRaw,
|
||||
j__udyMemSequence++, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjbl_t, PjblRaw);
|
||||
return(PjblRaw);
|
||||
|
||||
} // j__udyAllocJBL()
|
||||
|
||||
|
||||
FUNCTION Pjbb_t j__udyAllocJBB(Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = sizeof(jbb_t) / cJU_BYTESPERWORD;
|
||||
Pjbb_t PjbbRaw = (Pjbb_t) MALLOC(JudyMallocVirtual,
|
||||
Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
assert((Words * cJU_BYTESPERWORD) == sizeof(jbb_t));
|
||||
|
||||
if ((Word_t) PjbbRaw > sizeof(Word_t))
|
||||
{
|
||||
ZEROWORDS(P_JBB(PjbbRaw), Words);
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjbbRaw); }
|
||||
|
||||
TRACE_ALLOC5("0x%x %8lu = j__udyAllocJBB(), Words = %lu\n", PjbbRaw,
|
||||
j__udyMemSequence++, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjbb_t, PjbbRaw);
|
||||
return(PjbbRaw);
|
||||
|
||||
} // j__udyAllocJBB()
|
||||
|
||||
|
||||
FUNCTION Pjp_t j__udyAllocJBBJP(Word_t NumJPs, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_BRANCHJP_NUMJPSTOWORDS(NumJPs);
|
||||
Pjp_t PjpRaw;
|
||||
|
||||
PjpRaw = (Pjp_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjpRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjpRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJBBJP(%lu), Words = %lu\n", PjpRaw,
|
||||
j__udyMemSequence++, NumJPs, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjp_t, PjpRaw);
|
||||
return(PjpRaw);
|
||||
|
||||
} // j__udyAllocJBBJP()
|
||||
|
||||
|
||||
FUNCTION Pjbu_t j__udyAllocJBU(Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = sizeof(jbu_t) / cJU_BYTESPERWORD;
|
||||
Pjbu_t PjbuRaw = (Pjbu_t) MALLOC(JudyMallocVirtual,
|
||||
Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
assert((Words * cJU_BYTESPERWORD) == sizeof(jbu_t));
|
||||
|
||||
if ((Word_t) PjbuRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjbuRaw); }
|
||||
|
||||
TRACE_ALLOC5("0x%x %8lu = j__udyAllocJBU(), Words = %lu\n", PjbuRaw,
|
||||
j__udyMemSequence++, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjbu_t, PjbuRaw);
|
||||
return(PjbuRaw);
|
||||
|
||||
} // j__udyAllocJBU()
|
||||
|
||||
|
||||
#if (defined(JUDYL) || (! defined(JU_64BIT)))
|
||||
|
||||
FUNCTION Pjll_t j__udyAllocJLL1(Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF1POPTOWORDS(Pop1);
|
||||
Pjll_t PjllRaw;
|
||||
|
||||
PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjllRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjllRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL1(%lu), Words = %lu\n", PjllRaw,
|
||||
j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjll_t, PjllRaw);
|
||||
return(PjllRaw);
|
||||
|
||||
} // j__udyAllocJLL1()
|
||||
|
||||
#endif // (JUDYL || (! JU_64BIT))
|
||||
|
||||
|
||||
FUNCTION Pjll_t j__udyAllocJLL2(Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF2POPTOWORDS(Pop1);
|
||||
Pjll_t PjllRaw;
|
||||
|
||||
PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjllRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjllRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL2(%lu), Words = %lu\n", PjllRaw,
|
||||
j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjll_t, PjllRaw);
|
||||
return(PjllRaw);
|
||||
|
||||
} // j__udyAllocJLL2()
|
||||
|
||||
|
||||
FUNCTION Pjll_t j__udyAllocJLL3(Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF3POPTOWORDS(Pop1);
|
||||
Pjll_t PjllRaw;
|
||||
|
||||
PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjllRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjllRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL3(%lu), Words = %lu\n", PjllRaw,
|
||||
j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjll_t, PjllRaw);
|
||||
return(PjllRaw);
|
||||
|
||||
} // j__udyAllocJLL3()
|
||||
|
||||
|
||||
#ifdef JU_64BIT
|
||||
|
||||
FUNCTION Pjll_t j__udyAllocJLL4(Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF4POPTOWORDS(Pop1);
|
||||
Pjll_t PjllRaw;
|
||||
|
||||
PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjllRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjllRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL4(%lu), Words = %lu\n", PjllRaw,
|
||||
j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjll_t, PjllRaw);
|
||||
return(PjllRaw);
|
||||
|
||||
} // j__udyAllocJLL4()
|
||||
|
||||
|
||||
FUNCTION Pjll_t j__udyAllocJLL5(Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF5POPTOWORDS(Pop1);
|
||||
Pjll_t PjllRaw;
|
||||
|
||||
PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjllRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjllRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL5(%lu), Words = %lu\n", PjllRaw,
|
||||
j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjll_t, PjllRaw);
|
||||
return(PjllRaw);
|
||||
|
||||
} // j__udyAllocJLL5()
|
||||
|
||||
|
||||
FUNCTION Pjll_t j__udyAllocJLL6(Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF6POPTOWORDS(Pop1);
|
||||
Pjll_t PjllRaw;
|
||||
|
||||
PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjllRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjllRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL6(%lu), Words = %lu\n", PjllRaw,
|
||||
j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjll_t, PjllRaw);
|
||||
return(PjllRaw);
|
||||
|
||||
} // j__udyAllocJLL6()
|
||||
|
||||
|
||||
FUNCTION Pjll_t j__udyAllocJLL7(Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF7POPTOWORDS(Pop1);
|
||||
Pjll_t PjllRaw;
|
||||
|
||||
PjllRaw = (Pjll_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjllRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjllRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLL7(%lu), Words = %lu\n", PjllRaw,
|
||||
j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjll_t, PjllRaw);
|
||||
return(PjllRaw);
|
||||
|
||||
} // j__udyAllocJLL7()
|
||||
|
||||
#endif // JU_64BIT
|
||||
|
||||
|
||||
// Note: Root-level leaf addresses are always whole words (Pjlw_t), and unlike
|
||||
// other j__udyAlloc*() functions, they are returned non-raw, that is, without
|
||||
// malloc namespace or root pointer type bits (the latter are added later by
|
||||
// the caller):
|
||||
|
||||
FUNCTION Pjlw_t j__udyAllocJLW(Word_t Pop1)
|
||||
{
|
||||
Word_t Words = JU_LEAFWPOPTOWORDS(Pop1);
|
||||
Pjlw_t Pjlw = (Pjlw_t) MALLOC(JudyMalloc, Words, Words);
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyAllocJLW(%lu), Words = %lu\n", Pjlw,
|
||||
j__udyMemSequence++, Pop1, Words, Pop1);
|
||||
// MALLOCBITS_SET(Pjlw_t, Pjlw); // see above.
|
||||
return(Pjlw);
|
||||
|
||||
} // j__udyAllocJLW()
|
||||
|
||||
|
||||
FUNCTION Pjlb_t j__udyAllocJLB1(Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = sizeof(jlb_t) / cJU_BYTESPERWORD;
|
||||
Pjlb_t PjlbRaw;
|
||||
|
||||
PjlbRaw = (Pjlb_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
assert((Words * cJU_BYTESPERWORD) == sizeof(jlb_t));
|
||||
|
||||
if ((Word_t) PjlbRaw > sizeof(Word_t))
|
||||
{
|
||||
ZEROWORDS(P_JLB(PjlbRaw), Words);
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjlbRaw); }
|
||||
|
||||
TRACE_ALLOC5("0x%x %8lu = j__udyAllocJLB1(), Words = %lu\n", PjlbRaw,
|
||||
j__udyMemSequence++, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjlb_t, PjlbRaw);
|
||||
return(PjlbRaw);
|
||||
|
||||
} // j__udyAllocJLB1()
|
||||
|
||||
|
||||
#ifdef JUDYL
|
||||
|
||||
FUNCTION Pjv_t j__udyLAllocJV(Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JL_LEAFVPOPTOWORDS(Pop1);
|
||||
Pjv_t PjvRaw;
|
||||
|
||||
PjvRaw = (Pjv_t) MALLOC(JudyMalloc, Pjpm->jpm_TotalMemWords, Words);
|
||||
|
||||
if ((Word_t) PjvRaw > sizeof(Word_t))
|
||||
{
|
||||
Pjpm->jpm_TotalMemWords += Words;
|
||||
}
|
||||
else { J__UDYSETALLOCERROR(PjvRaw); }
|
||||
|
||||
TRACE_ALLOC6("0x%x %8lu = j__udyLAllocJV(%lu), Words = %lu\n", PjvRaw,
|
||||
j__udyMemSequence++, Pop1, Words, (Pjpm->jpm_Pop0) + 2);
|
||||
MALLOCBITS_SET(Pjv_t, PjvRaw);
|
||||
return(PjvRaw);
|
||||
|
||||
} // j__udyLAllocJV()
|
||||
|
||||
#endif // JUDYL
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// FREE FUNCTIONS:
|
||||
//
|
||||
// To help the compiler catch coding errors, each function takes a specific
|
||||
// object type to free.
|
||||
|
||||
|
||||
// Note: j__udyFreeJPM() receives a root pointer with NO root pointer type
|
||||
// bits present, that is, they must be stripped by the caller using P_JPM():
|
||||
|
||||
FUNCTION void j__udyFreeJPM(Pjpm_t PjpmFree, Pjpm_t PjpmStats)
|
||||
{
|
||||
Word_t Words = (sizeof(jpm_t) + cJU_BYTESPERWORD - 1) / cJU_BYTESPERWORD;
|
||||
|
||||
// MALLOCBITS_TEST(Pjpm_t, PjpmFree); // see above.
|
||||
JudyFree((Pvoid_t) PjpmFree, Words);
|
||||
|
||||
if (PjpmStats != (Pjpm_t) NULL) PjpmStats->jpm_TotalMemWords -= Words;
|
||||
|
||||
// Note: Log PjpmFree->jpm_Pop0, similar to other j__udyFree*() functions, not
|
||||
// an assumed value of cJU_LEAFW_MAXPOP1, for when the caller is
|
||||
// Judy*FreeArray(), jpm_Pop0 is set to 0, and the population after the free
|
||||
// really will be 0, not cJU_LEAFW_MAXPOP1.
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJPM(%lu), Words = %lu\n", PjpmFree,
|
||||
j__udyMemSequence++, Words, Words, PjpmFree->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJPM()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJBL(Pjbl_t Pjbl, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = sizeof(jbl_t) / cJU_BYTESPERWORD;
|
||||
|
||||
MALLOCBITS_TEST(Pjbl_t, Pjbl);
|
||||
JudyFreeVirtual((Pvoid_t) Pjbl, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE5("0x%x %8lu = j__udyFreeJBL(), Words = %lu\n", Pjbl,
|
||||
j__udyMemSequence++, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJBL()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJBB(Pjbb_t Pjbb, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = sizeof(jbb_t) / cJU_BYTESPERWORD;
|
||||
|
||||
MALLOCBITS_TEST(Pjbb_t, Pjbb);
|
||||
JudyFreeVirtual((Pvoid_t) Pjbb, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE5("0x%x %8lu = j__udyFreeJBB(), Words = %lu\n", Pjbb,
|
||||
j__udyMemSequence++, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJBB()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJBBJP(Pjp_t Pjp, Word_t NumJPs, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_BRANCHJP_NUMJPSTOWORDS(NumJPs);
|
||||
|
||||
MALLOCBITS_TEST(Pjp_t, Pjp);
|
||||
JudyFree((Pvoid_t) Pjp, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJBBJP(%lu), Words = %lu\n", Pjp,
|
||||
j__udyMemSequence++, NumJPs, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJBBJP()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJBU(Pjbu_t Pjbu, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = sizeof(jbu_t) / cJU_BYTESPERWORD;
|
||||
|
||||
MALLOCBITS_TEST(Pjbu_t, Pjbu);
|
||||
JudyFreeVirtual((Pvoid_t) Pjbu, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE5("0x%x %8lu = j__udyFreeJBU(), Words = %lu\n", Pjbu,
|
||||
j__udyMemSequence++, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJBU()
|
||||
|
||||
|
||||
#if (defined(JUDYL) || (! defined(JU_64BIT)))
|
||||
|
||||
FUNCTION void j__udyFreeJLL1(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF1POPTOWORDS(Pop1);
|
||||
|
||||
MALLOCBITS_TEST(Pjll_t, Pjll);
|
||||
JudyFree((Pvoid_t) Pjll, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJLL1(%lu), Words = %lu\n", Pjll,
|
||||
j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJLL1()
|
||||
|
||||
#endif // (JUDYL || (! JU_64BIT))
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJLL2(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF2POPTOWORDS(Pop1);
|
||||
|
||||
MALLOCBITS_TEST(Pjll_t, Pjll);
|
||||
JudyFree((Pvoid_t) Pjll, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJLL2(%lu), Words = %lu\n", Pjll,
|
||||
j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJLL2()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJLL3(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF3POPTOWORDS(Pop1);
|
||||
|
||||
MALLOCBITS_TEST(Pjll_t, Pjll);
|
||||
JudyFree((Pvoid_t) Pjll, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJLL3(%lu), Words = %lu\n", Pjll,
|
||||
j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJLL3()
|
||||
|
||||
|
||||
#ifdef JU_64BIT
|
||||
|
||||
FUNCTION void j__udyFreeJLL4(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF4POPTOWORDS(Pop1);
|
||||
|
||||
MALLOCBITS_TEST(Pjll_t, Pjll);
|
||||
JudyFree((Pvoid_t) Pjll, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJLL4(%lu), Words = %lu\n", Pjll,
|
||||
j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJLL4()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJLL5(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF5POPTOWORDS(Pop1);
|
||||
|
||||
MALLOCBITS_TEST(Pjll_t, Pjll);
|
||||
JudyFree((Pvoid_t) Pjll, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJLL5(%lu), Words = %lu\n", Pjll,
|
||||
j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJLL5()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJLL6(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF6POPTOWORDS(Pop1);
|
||||
|
||||
MALLOCBITS_TEST(Pjll_t, Pjll);
|
||||
JudyFree((Pvoid_t) Pjll, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJLL6(%lu), Words = %lu\n", Pjll,
|
||||
j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJLL6()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJLL7(Pjll_t Pjll, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAF7POPTOWORDS(Pop1);
|
||||
|
||||
MALLOCBITS_TEST(Pjll_t, Pjll);
|
||||
JudyFree((Pvoid_t) Pjll, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJLL7(%lu), Words = %lu\n", Pjll,
|
||||
j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJLL7()
|
||||
|
||||
#endif // JU_64BIT
|
||||
|
||||
|
||||
// Note: j__udyFreeJLW() receives a root pointer with NO root pointer type
|
||||
// bits present, that is, they are stripped by P_JLW():
|
||||
|
||||
FUNCTION void j__udyFreeJLW(Pjlw_t Pjlw, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JU_LEAFWPOPTOWORDS(Pop1);
|
||||
|
||||
// MALLOCBITS_TEST(Pjlw_t, Pjlw); // see above.
|
||||
JudyFree((Pvoid_t) Pjlw, Words);
|
||||
|
||||
if (Pjpm) Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyFreeJLW(%lu), Words = %lu\n", Pjlw,
|
||||
j__udyMemSequence++, Pop1, Words, Pop1 - 1);
|
||||
|
||||
|
||||
} // j__udyFreeJLW()
|
||||
|
||||
|
||||
FUNCTION void j__udyFreeJLB1(Pjlb_t Pjlb, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = sizeof(jlb_t) / cJU_BYTESPERWORD;
|
||||
|
||||
MALLOCBITS_TEST(Pjlb_t, Pjlb);
|
||||
JudyFree((Pvoid_t) Pjlb, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE5("0x%x %8lu = j__udyFreeJLB1(), Words = %lu\n", Pjlb,
|
||||
j__udyMemSequence++, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyFreeJLB1()
|
||||
|
||||
|
||||
#ifdef JUDYL
|
||||
|
||||
FUNCTION void j__udyLFreeJV(Pjv_t Pjv, Word_t Pop1, Pjpm_t Pjpm)
|
||||
{
|
||||
Word_t Words = JL_LEAFVPOPTOWORDS(Pop1);
|
||||
|
||||
MALLOCBITS_TEST(Pjv_t, Pjv);
|
||||
JudyFree((Pvoid_t) Pjv, Words);
|
||||
|
||||
Pjpm->jpm_TotalMemWords -= Words;
|
||||
|
||||
TRACE_FREE6("0x%x %8lu = j__udyLFreeJV(%lu), Words = %lu\n", Pjv,
|
||||
j__udyMemSequence++, Pop1, Words, Pjpm->jpm_Pop0);
|
||||
|
||||
|
||||
} // j__udyLFreeJV()
|
||||
|
||||
#endif // JUDYL
|
259
libnetdata/libjudy/src/JudyL/JudyLMemActive.c
Normal file
259
libnetdata/libjudy/src/JudyL/JudyLMemActive.c
Normal file
|
@ -0,0 +1,259 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.7 $ $Source: /judy/src/JudyCommon/JudyMemActive.c $
|
||||
//
|
||||
// Return number of bytes of memory used to support a Judy1/L array.
|
||||
// Compile with one of -DJUDY1 or -DJUDYL.
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
#include "JudyPrivate1L.h"
|
||||
|
||||
FUNCTION static Word_t j__udyGetMemActive(Pjp_t);
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// J U D Y 1 M E M A C T I V E
|
||||
// J U D Y L M E M A C T I V E
|
||||
|
||||
#ifdef JUDY1
|
||||
FUNCTION Word_t Judy1MemActive
|
||||
#else
|
||||
FUNCTION Word_t JudyLMemActive
|
||||
#endif
|
||||
(
|
||||
Pcvoid_t PArray // from which to retrieve.
|
||||
)
|
||||
{
|
||||
if (PArray == (Pcvoid_t)NULL) return(0);
|
||||
|
||||
if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
|
||||
{
|
||||
Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
|
||||
Word_t Words = Pjlw[0] + 1; // population.
|
||||
#ifdef JUDY1
|
||||
return((Words + 1) * sizeof(Word_t));
|
||||
#else
|
||||
return(((Words * 2) + 1) * sizeof(Word_t));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Pjpm_t Pjpm = P_JPM(PArray);
|
||||
return(j__udyGetMemActive(&Pjpm->jpm_JP) + sizeof(jpm_t));
|
||||
}
|
||||
|
||||
} // JudyMemActive()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// __ J U D Y G E T M E M A C T I V E
|
||||
|
||||
FUNCTION static Word_t j__udyGetMemActive(
|
||||
Pjp_t Pjp) // top of subtree.
|
||||
{
|
||||
Word_t offset; // in a branch.
|
||||
Word_t Bytes = 0; // actual bytes used at this level.
|
||||
Word_t IdxSz; // bytes per index in leaves
|
||||
|
||||
switch (JU_JPTYPE(Pjp))
|
||||
{
|
||||
|
||||
case cJU_JPBRANCH_L2:
|
||||
case cJU_JPBRANCH_L3:
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPBRANCH_L4:
|
||||
case cJU_JPBRANCH_L5:
|
||||
case cJU_JPBRANCH_L6:
|
||||
case cJU_JPBRANCH_L7:
|
||||
#endif
|
||||
case cJU_JPBRANCH_L:
|
||||
{
|
||||
Pjbl_t Pjbl = P_JBL(Pjp->jp_Addr);
|
||||
|
||||
for (offset = 0; offset < (Pjbl->jbl_NumJPs); ++offset)
|
||||
Bytes += j__udyGetMemActive((Pjbl->jbl_jp) + offset);
|
||||
|
||||
return(Bytes + sizeof(jbl_t));
|
||||
}
|
||||
|
||||
case cJU_JPBRANCH_B2:
|
||||
case cJU_JPBRANCH_B3:
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPBRANCH_B4:
|
||||
case cJU_JPBRANCH_B5:
|
||||
case cJU_JPBRANCH_B6:
|
||||
case cJU_JPBRANCH_B7:
|
||||
#endif
|
||||
case cJU_JPBRANCH_B:
|
||||
{
|
||||
Word_t subexp;
|
||||
Word_t jpcount;
|
||||
Pjbb_t Pjbb = P_JBB(Pjp->jp_Addr);
|
||||
|
||||
for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp)
|
||||
{
|
||||
jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp));
|
||||
Bytes += jpcount * sizeof(jp_t);
|
||||
|
||||
for (offset = 0; offset < jpcount; ++offset)
|
||||
{
|
||||
Bytes += j__udyGetMemActive(P_JP(JU_JBB_PJP(Pjbb, subexp))
|
||||
+ offset);
|
||||
}
|
||||
}
|
||||
|
||||
return(Bytes + sizeof(jbb_t));
|
||||
}
|
||||
|
||||
case cJU_JPBRANCH_U2:
|
||||
case cJU_JPBRANCH_U3:
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPBRANCH_U4:
|
||||
case cJU_JPBRANCH_U5:
|
||||
case cJU_JPBRANCH_U6:
|
||||
case cJU_JPBRANCH_U7:
|
||||
#endif
|
||||
case cJU_JPBRANCH_U:
|
||||
{
|
||||
Pjbu_t Pjbu = P_JBU(Pjp->jp_Addr);
|
||||
|
||||
for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset)
|
||||
{
|
||||
if (((Pjbu->jbu_jp[offset].jp_Type) >= cJU_JPNULL1)
|
||||
&& ((Pjbu->jbu_jp[offset].jp_Type) <= cJU_JPNULLMAX))
|
||||
{
|
||||
continue; // skip null JP to save time.
|
||||
}
|
||||
|
||||
Bytes += j__udyGetMemActive(Pjbu->jbu_jp + offset);
|
||||
}
|
||||
|
||||
return(Bytes + sizeof(jbu_t));
|
||||
}
|
||||
|
||||
|
||||
// -- Cases below here terminate and do not recurse. --
|
||||
|
||||
#if (defined(JUDYL) || (! defined(JU_64BIT)))
|
||||
case cJU_JPLEAF1: IdxSz = 1; goto LeafWords;
|
||||
#endif
|
||||
case cJU_JPLEAF2: IdxSz = 2; goto LeafWords;
|
||||
case cJU_JPLEAF3: IdxSz = 3; goto LeafWords;
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPLEAF4: IdxSz = 4; goto LeafWords;
|
||||
case cJU_JPLEAF5: IdxSz = 5; goto LeafWords;
|
||||
case cJU_JPLEAF6: IdxSz = 6; goto LeafWords;
|
||||
case cJU_JPLEAF7: IdxSz = 7; goto LeafWords;
|
||||
#endif
|
||||
LeafWords:
|
||||
|
||||
#ifdef JUDY1
|
||||
return(IdxSz * (JU_JPLEAF_POP0(Pjp) + 1));
|
||||
#else
|
||||
return((IdxSz + sizeof(Word_t))
|
||||
* (JU_JPLEAF_POP0(Pjp) + 1));
|
||||
#endif
|
||||
case cJU_JPLEAF_B1:
|
||||
{
|
||||
#ifdef JUDY1
|
||||
return(sizeof(jlb_t));
|
||||
#else
|
||||
Bytes = (JU_JPLEAF_POP0(Pjp) + 1) * sizeof(Word_t);
|
||||
|
||||
return(Bytes + sizeof(jlb_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
JUDY1CODE(case cJ1_JPFULLPOPU1: return(0);)
|
||||
|
||||
#ifdef JUDY1
|
||||
#define J__Mpy 0
|
||||
#else
|
||||
#define J__Mpy sizeof(Word_t)
|
||||
#endif
|
||||
|
||||
case cJU_JPIMMED_1_01: return(0);
|
||||
case cJU_JPIMMED_2_01: return(0);
|
||||
case cJU_JPIMMED_3_01: return(0);
|
||||
#ifdef JU_64BIT
|
||||
case cJU_JPIMMED_4_01: return(0);
|
||||
case cJU_JPIMMED_5_01: return(0);
|
||||
case cJU_JPIMMED_6_01: return(0);
|
||||
case cJU_JPIMMED_7_01: return(0);
|
||||
#endif
|
||||
|
||||
case cJU_JPIMMED_1_02: return(J__Mpy * 2);
|
||||
case cJU_JPIMMED_1_03: return(J__Mpy * 3);
|
||||
#if (defined(JUDY1) || defined(JU_64BIT))
|
||||
case cJU_JPIMMED_1_04: return(J__Mpy * 4);
|
||||
case cJU_JPIMMED_1_05: return(J__Mpy * 5);
|
||||
case cJU_JPIMMED_1_06: return(J__Mpy * 6);
|
||||
case cJU_JPIMMED_1_07: return(J__Mpy * 7);
|
||||
#endif
|
||||
#if (defined(JUDY1) && defined(JU_64BIT))
|
||||
case cJ1_JPIMMED_1_08: return(0);
|
||||
case cJ1_JPIMMED_1_09: return(0);
|
||||
case cJ1_JPIMMED_1_10: return(0);
|
||||
case cJ1_JPIMMED_1_11: return(0);
|
||||
case cJ1_JPIMMED_1_12: return(0);
|
||||
case cJ1_JPIMMED_1_13: return(0);
|
||||
case cJ1_JPIMMED_1_14: return(0);
|
||||
case cJ1_JPIMMED_1_15: return(0);
|
||||
#endif
|
||||
|
||||
#if (defined(JUDY1) || defined(JU_64BIT))
|
||||
case cJU_JPIMMED_2_02: return(J__Mpy * 2);
|
||||
case cJU_JPIMMED_2_03: return(J__Mpy * 3);
|
||||
#endif
|
||||
#if (defined(JUDY1) && defined(JU_64BIT))
|
||||
case cJ1_JPIMMED_2_04: return(0);
|
||||
case cJ1_JPIMMED_2_05: return(0);
|
||||
case cJ1_JPIMMED_2_06: return(0);
|
||||
case cJ1_JPIMMED_2_07: return(0);
|
||||
#endif
|
||||
|
||||
#if (defined(JUDY1) || defined(JU_64BIT))
|
||||
case cJU_JPIMMED_3_02: return(J__Mpy * 2);
|
||||
#endif
|
||||
#if (defined(JUDY1) && defined(JU_64BIT))
|
||||
case cJ1_JPIMMED_3_03: return(0);
|
||||
case cJ1_JPIMMED_3_04: return(0);
|
||||
case cJ1_JPIMMED_3_05: return(0);
|
||||
|
||||
case cJ1_JPIMMED_4_02: return(0);
|
||||
case cJ1_JPIMMED_4_03: return(0);
|
||||
case cJ1_JPIMMED_5_02: return(0);
|
||||
case cJ1_JPIMMED_5_03: return(0);
|
||||
case cJ1_JPIMMED_6_02: return(0);
|
||||
case cJ1_JPIMMED_7_02: return(0);
|
||||
#endif
|
||||
|
||||
} // switch (JU_JPTYPE(Pjp))
|
||||
|
||||
return(0); // to make some compilers happy.
|
||||
|
||||
} // j__udyGetMemActive()
|
61
libnetdata/libjudy/src/JudyL/JudyLMemUsed.c
Normal file
61
libnetdata/libjudy/src/JudyL/JudyLMemUsed.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.5 $ $Source: /judy/src/JudyCommon/JudyMemUsed.c $
|
||||
//
|
||||
// Return number of bytes of memory used to support a Judy1/L array.
|
||||
// Compile with one of -DJUDY1 or -DJUDYL.
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
#include "JudyPrivate1L.h"
|
||||
|
||||
#ifdef JUDY1
|
||||
FUNCTION Word_t Judy1MemUsed
|
||||
#else // JUDYL
|
||||
FUNCTION Word_t JudyLMemUsed
|
||||
#endif
|
||||
(
|
||||
Pcvoid_t PArray // from which to retrieve.
|
||||
)
|
||||
{
|
||||
Word_t Words = 0;
|
||||
|
||||
if (PArray == (Pcvoid_t) NULL) return(0);
|
||||
|
||||
if (JU_LEAFW_POP0(PArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW
|
||||
{
|
||||
Pjlw_t Pjlw = P_JLW(PArray); // first word of leaf.
|
||||
Words = JU_LEAFWPOPTOWORDS(Pjlw[0] + 1); // based on pop1.
|
||||
}
|
||||
else
|
||||
{
|
||||
Pjpm_t Pjpm = P_JPM(PArray);
|
||||
Words = Pjpm->jpm_TotalMemWords;
|
||||
}
|
||||
|
||||
return(Words * sizeof(Word_t)); // convert to bytes.
|
||||
|
||||
} // Judy1MemUsed() / JudyLMemUsed()
|
1890
libnetdata/libjudy/src/JudyL/JudyLNext.c
Normal file
1890
libnetdata/libjudy/src/JudyL/JudyLNext.c
Normal file
File diff suppressed because it is too large
Load diff
1390
libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c
Normal file
1390
libnetdata/libjudy/src/JudyL/JudyLNextEmpty.c
Normal file
File diff suppressed because it is too large
Load diff
1890
libnetdata/libjudy/src/JudyL/JudyLPrev.c
Normal file
1890
libnetdata/libjudy/src/JudyL/JudyLPrev.c
Normal file
File diff suppressed because it is too large
Load diff
1390
libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c
Normal file
1390
libnetdata/libjudy/src/JudyL/JudyLPrevEmpty.c
Normal file
File diff suppressed because it is too large
Load diff
296
libnetdata/libjudy/src/JudyL/JudyLTablesGen.c
Normal file
296
libnetdata/libjudy/src/JudyL/JudyLTablesGen.c
Normal file
|
@ -0,0 +1,296 @@
|
|||
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it
|
||||
// under the term of the GNU Lesser General Public License as published by the
|
||||
// Free Software Foundation; either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// _________________
|
||||
|
||||
// @(#) $Revision: 4.37 $ $Source: /judy/src/JudyCommon/JudyTables.c $
|
||||
|
||||
#ifndef JU_WIN
|
||||
#include <unistd.h> // unavailable on win_*.
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if (! (defined(JUDY1) || defined(JUDYL)))
|
||||
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
||||
#endif
|
||||
|
||||
#define TERMINATOR 999 // terminator for Alloc tables
|
||||
|
||||
#define BPW sizeof(Word_t) // define bytes per word
|
||||
|
||||
#ifdef JUDY1
|
||||
#include "Judy1.h"
|
||||
#else
|
||||
#include "JudyL.h"
|
||||
#endif
|
||||
|
||||
FILE *fd;
|
||||
|
||||
// Definitions come from header files Judy1.h and JudyL.h:
|
||||
|
||||
int AllocSizes[] = ALLOCSIZES;
|
||||
|
||||
#define ROUNDUP(BYTES,BPW,OFFSETW) \
|
||||
((((BYTES) + (BPW) - 1) / (BPW)) + (OFFSETW))
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// G E N T A B L E
|
||||
//
|
||||
// Note: "const" is required for newer compilers.
|
||||
|
||||
FUNCTION void GenTable(
|
||||
const char * TableName, // name of table string
|
||||
const char * TableSize, // dimentioned size string
|
||||
int IndexBytes, // bytes per Index
|
||||
int LeafSize, // number elements in object
|
||||
int ValueBytes, // bytes per Value
|
||||
int OffsetWords) // 1 for LEAFW
|
||||
{
|
||||
int * PAllocSizes = AllocSizes;
|
||||
int OWord;
|
||||
int CurWord;
|
||||
int IWord;
|
||||
int ii;
|
||||
int BytesOfIndex;
|
||||
int BytesOfObject;
|
||||
int Index;
|
||||
int LastWords;
|
||||
int Words [1000] = { 0 };
|
||||
int Offset[1000] = { 0 };
|
||||
int MaxWords;
|
||||
|
||||
MaxWords = ROUNDUP((IndexBytes + ValueBytes) * LeafSize, BPW, OffsetWords);
|
||||
Words[0] = 0;
|
||||
Offset[0] = 0;
|
||||
CurWord = TERMINATOR;
|
||||
|
||||
// Walk through all number of Indexes in table:
|
||||
|
||||
for (Index = 1; /* null */; ++Index)
|
||||
{
|
||||
|
||||
// Calculate byte required for next size:
|
||||
|
||||
BytesOfIndex = IndexBytes * Index;
|
||||
BytesOfObject = (IndexBytes + ValueBytes) * Index;
|
||||
|
||||
// Round up and calculate words required for next size:
|
||||
|
||||
OWord = ROUNDUP(BytesOfObject, BPW, OffsetWords);
|
||||
IWord = ROUNDUP(BytesOfIndex, BPW, OffsetWords);
|
||||
|
||||
// Root-level leaves of population of 1 and 2 do not have the 1 word offset:
|
||||
|
||||
// Save minimum value of offset:
|
||||
|
||||
Offset[Index] = IWord;
|
||||
|
||||
// Round up to next available size of words:
|
||||
|
||||
while (OWord > *PAllocSizes) PAllocSizes++;
|
||||
|
||||
if (Index == LeafSize)
|
||||
{
|
||||
CurWord = Words[Index] = OWord;
|
||||
break;
|
||||
}
|
||||
// end of available sizes ?
|
||||
|
||||
if (*PAllocSizes == TERMINATOR)
|
||||
{
|
||||
fprintf(stderr, "BUG, in %sPopToWords, sizes not big enough for object\n", TableName);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Save words required and last word:
|
||||
|
||||
if (*PAllocSizes < MaxWords) { CurWord = Words[Index] = *PAllocSizes; }
|
||||
else { CurWord = Words[Index] = MaxWords; }
|
||||
|
||||
} // for each index
|
||||
|
||||
LastWords = TERMINATOR;
|
||||
|
||||
// Round up to largest size in each group of malloc sizes:
|
||||
|
||||
for (ii = LeafSize; ii > 0; ii--)
|
||||
{
|
||||
if (LastWords > (Words[ii] - ii)) LastWords = Offset[ii];
|
||||
else Offset[ii] = LastWords;
|
||||
}
|
||||
|
||||
// Print the PopToWords[] table:
|
||||
|
||||
fprintf(fd,"\n//\tobject uses %d words\n", CurWord);
|
||||
fprintf(fd,"//\t%s = %d\n", TableSize, LeafSize);
|
||||
|
||||
fprintf(fd,"const uint8_t\n");
|
||||
fprintf(fd,"%sPopToWords[%s + 1] =\n", TableName, TableSize);
|
||||
fprintf(fd,"{\n\t 0,");
|
||||
|
||||
for (ii = 1; ii <= LeafSize; ii++)
|
||||
{
|
||||
|
||||
// 8 columns per line, starting with 1:
|
||||
|
||||
if ((ii % 8) == 1) fprintf(fd,"\n\t");
|
||||
|
||||
fprintf(fd,"%2d", Words[ii]);
|
||||
|
||||
// If not last number place comma:
|
||||
|
||||
if (ii != LeafSize) fprintf(fd,", ");
|
||||
}
|
||||
fprintf(fd,"\n};\n");
|
||||
|
||||
// Print the Offset table if needed:
|
||||
|
||||
if (! ValueBytes) return;
|
||||
|
||||
fprintf(fd,"const uint8_t\n");
|
||||
fprintf(fd,"%sOffset[%s + 1] =\n", TableName, TableSize);
|
||||
fprintf(fd,"{\n");
|
||||
fprintf(fd,"\t 0,");
|
||||
|
||||
for (ii = 1; ii <= LeafSize; ii++)
|
||||
{
|
||||
if ((ii % 8) == 1) fprintf(fd,"\n\t");
|
||||
|
||||
fprintf(fd,"%2d", Offset[ii]);
|
||||
|
||||
if (ii != LeafSize) fprintf(fd,", ");
|
||||
}
|
||||
fprintf(fd,"\n};\n");
|
||||
|
||||
} // GenTable()
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// M A I N
|
||||
|
||||
FUNCTION int main()
|
||||
{
|
||||
int ii;
|
||||
|
||||
#ifdef JUDY1
|
||||
char *fname = "Judy1Tables.c";
|
||||
#else
|
||||
char *fname = "JudyLTables.c";
|
||||
#endif
|
||||
|
||||
if ((fd = fopen(fname, "w")) == NULL){
|
||||
perror("FATAL ERROR: could not write to Judy[1L]Tables.c file\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
fprintf(fd,"// @(#) From generation tool: $Revision: 4.37 $ $Source: /judy/src/JudyCommon/JudyTables.c $\n");
|
||||
fprintf(fd,"//\n\n");
|
||||
|
||||
|
||||
// ================================ Judy1 =================================
|
||||
#ifdef JUDY1
|
||||
|
||||
fprintf(fd,"#include \"Judy1.h\"\n");
|
||||
|
||||
fprintf(fd,"// Leave the malloc() sizes readable in the binary (via "
|
||||
"strings(1)):\n");
|
||||
fprintf(fd,"const char * Judy1MallocSizes = \"Judy1MallocSizes =");
|
||||
|
||||
for (ii = 0; AllocSizes[ii] != TERMINATOR; ii++)
|
||||
fprintf(fd," %d,", AllocSizes[ii]);
|
||||
|
||||
#ifndef JU_64BIT
|
||||
fprintf(fd," Leaf1 = %d\";\n\n", cJ1_LEAF1_MAXPOP1);
|
||||
#else
|
||||
fprintf(fd,"\";\n\n"); // no Leaf1 in this case.
|
||||
#endif
|
||||
|
||||
// ================================ 32 bit ================================
|
||||
#ifndef JU_64BIT
|
||||
|
||||
GenTable("j__1_BranchBJP","cJU_BITSPERSUBEXPB", 8, cJU_BITSPERSUBEXPB,0,0);
|
||||
|
||||
GenTable("j__1_Leaf1", "cJ1_LEAF1_MAXPOP1", 1, cJ1_LEAF1_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_Leaf2", "cJ1_LEAF2_MAXPOP1", 2, cJ1_LEAF2_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_Leaf3", "cJ1_LEAF3_MAXPOP1", 3, cJ1_LEAF3_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_LeafW", "cJ1_LEAFW_MAXPOP1", 4, cJ1_LEAFW_MAXPOP1, 0, 1);
|
||||
|
||||
#endif
|
||||
|
||||
// ================================ 64 bit ================================
|
||||
#ifdef JU_64BIT
|
||||
GenTable("j__1_BranchBJP","cJU_BITSPERSUBEXPB",16, cJU_BITSPERSUBEXPB,0,0);
|
||||
|
||||
GenTable("j__1_Leaf2", "cJ1_LEAF2_MAXPOP1", 2, cJ1_LEAF2_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_Leaf3", "cJ1_LEAF3_MAXPOP1", 3, cJ1_LEAF3_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_Leaf4", "cJ1_LEAF4_MAXPOP1", 4, cJ1_LEAF4_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_Leaf5", "cJ1_LEAF5_MAXPOP1", 5, cJ1_LEAF5_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_Leaf6", "cJ1_LEAF6_MAXPOP1", 6, cJ1_LEAF6_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_Leaf7", "cJ1_LEAF7_MAXPOP1", 7, cJ1_LEAF7_MAXPOP1, 0, 0);
|
||||
GenTable("j__1_LeafW", "cJ1_LEAFW_MAXPOP1", 8, cJ1_LEAFW_MAXPOP1, 0, 1);
|
||||
#endif
|
||||
#endif // JUDY1
|
||||
|
||||
|
||||
// ================================ JudyL =================================
|
||||
#ifdef JUDYL
|
||||
|
||||
fprintf(fd,"#include \"JudyL.h\"\n");
|
||||
|
||||
fprintf(fd,"// Leave the malloc() sizes readable in the binary (via "
|
||||
"strings(1)):\n");
|
||||
fprintf(fd,"const char * JudyLMallocSizes = \"JudyLMallocSizes =");
|
||||
|
||||
for (ii = 0; AllocSizes[ii] != TERMINATOR; ii++)
|
||||
fprintf(fd," %d,", AllocSizes[ii]);
|
||||
|
||||
fprintf(fd," Leaf1 = %ld\";\n\n", (Word_t)cJL_LEAF1_MAXPOP1);
|
||||
|
||||
#ifndef JU_64BIT
|
||||
// ================================ 32 bit ================================
|
||||
GenTable("j__L_BranchBJP","cJU_BITSPERSUBEXPB", 8, cJU_BITSPERSUBEXPB, 0,0);
|
||||
|
||||
GenTable("j__L_Leaf1", "cJL_LEAF1_MAXPOP1", 1, cJL_LEAF1_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_Leaf2", "cJL_LEAF2_MAXPOP1", 2, cJL_LEAF2_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_Leaf3", "cJL_LEAF3_MAXPOP1", 3, cJL_LEAF3_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_LeafW", "cJL_LEAFW_MAXPOP1", 4, cJL_LEAFW_MAXPOP1, BPW,1);
|
||||
GenTable("j__L_LeafV", "cJU_BITSPERSUBEXPL", 4, cJU_BITSPERSUBEXPL, 0,0);
|
||||
#endif // 32 BIT
|
||||
|
||||
#ifdef JU_64BIT
|
||||
// ================================ 64 bit ================================
|
||||
GenTable("j__L_BranchBJP","cJU_BITSPERSUBEXPB",16, cJU_BITSPERSUBEXPB, 0,0);
|
||||
|
||||
GenTable("j__L_Leaf1", "cJL_LEAF1_MAXPOP1", 1, cJL_LEAF1_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_Leaf2", "cJL_LEAF2_MAXPOP1", 2, cJL_LEAF2_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_Leaf3", "cJL_LEAF3_MAXPOP1", 3, cJL_LEAF3_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_Leaf4", "cJL_LEAF4_MAXPOP1", 4, cJL_LEAF4_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_Leaf5", "cJL_LEAF5_MAXPOP1", 5, cJL_LEAF5_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_Leaf6", "cJL_LEAF6_MAXPOP1", 6, cJL_LEAF6_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_Leaf7", "cJL_LEAF7_MAXPOP1", 7, cJL_LEAF7_MAXPOP1, BPW,0);
|
||||
GenTable("j__L_LeafW", "cJL_LEAFW_MAXPOP1", 8, cJL_LEAFW_MAXPOP1, BPW,1);
|
||||
GenTable("j__L_LeafV", "cJU_BITSPERSUBEXPL", 8, cJU_BITSPERSUBEXPL, 0,0);
|
||||
#endif // 64 BIT
|
||||
|
||||
#endif // JUDYL
|
||||
fclose(fd);
|
||||
|
||||
return(0);
|
||||
|
||||
} // main()
|
1094
libnetdata/libjudy/src/JudyL/j__udyLGet.c
Normal file
1094
libnetdata/libjudy/src/JudyL/j__udyLGet.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -307,7 +307,6 @@ while [ -n "${1}" ]; do
|
|||
"--disable-https") NETDATA_CONFIGURE_OPTIONS="$(echo "${NETDATA_CONFIGURE_OPTIONS%--disable-https)}" | sed 's/$/ --disable-plugin-https/g')" ;;
|
||||
"--disable-dbengine")
|
||||
NETDATA_CONFIGURE_OPTIONS="$(echo "${NETDATA_CONFIGURE_OPTIONS%--disable-dbengine)}" | sed 's/$/ --disable-dbengine/g')"
|
||||
NETDATA_DISABLE_DBENGINE=1
|
||||
;;
|
||||
"--enable-plugin-nfacct") NETDATA_CONFIGURE_OPTIONS="$(echo "${NETDATA_CONFIGURE_OPTIONS%--enable-plugin-nfacct)}" | sed 's/$/ --enable-plugin-nfacct/g')" ;;
|
||||
"--disable-plugin-nfacct") NETDATA_CONFIGURE_OPTIONS="$(echo "${NETDATA_CONFIGURE_OPTIONS%--disable-plugin-nfacct)}" | sed 's/$/ --disable-plugin-nfacct/g')" ;;
|
||||
|
@ -367,9 +366,6 @@ while [ -n "${1}" ]; do
|
|||
"--build-json-c")
|
||||
NETDATA_BUILD_JSON_C=1
|
||||
;;
|
||||
"--build-judy")
|
||||
NETDATA_BUILD_JUDY=1
|
||||
;;
|
||||
"--install")
|
||||
NETDATA_PREFIX="${2}/netdata"
|
||||
shift 1
|
||||
|
@ -658,98 +654,6 @@ bundle_protobuf() {
|
|||
|
||||
bundle_protobuf
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
build_judy() {
|
||||
env_cmd=''
|
||||
libtoolize="libtoolize"
|
||||
|
||||
if [ -z "${DONT_SCRUB_CFLAGS_EVEN_THOUGH_IT_MAY_BREAK_THINGS}" ]; then
|
||||
env_cmd="env CFLAGS='-fPIC -pipe' CXXFLAGS='-fPIC -pipe' LDFLAGS="
|
||||
fi
|
||||
|
||||
if [ "$(uname)" = "Darwin" ]; then
|
||||
libtoolize="glibtoolize"
|
||||
fi
|
||||
|
||||
cd "${1}" > /dev/null || return 1
|
||||
if run eval "${env_cmd} ${libtoolize} --force --copy" &&
|
||||
run eval "${env_cmd} aclocal" &&
|
||||
run eval "${env_cmd} autoheader" &&
|
||||
run eval "${env_cmd} automake --add-missing --force --copy --include-deps" &&
|
||||
run eval "${env_cmd} autoconf" &&
|
||||
run eval "${env_cmd} ./configure" &&
|
||||
run eval "${env_cmd} ${make} ${MAKEOPTS} -C src" &&
|
||||
run eval "${env_cmd} ar -r src/libJudy.a src/Judy*/*.o"; then
|
||||
cd - > /dev/null || return 1
|
||||
else
|
||||
cd - > /dev/null || return 1
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
copy_judy() {
|
||||
target_dir="${PWD}/externaldeps/libJudy"
|
||||
|
||||
run mkdir -p "${target_dir}" || return 1
|
||||
|
||||
run cp "${1}/src/libJudy.a" "${target_dir}/libJudy.a" || return 1
|
||||
run cp "${1}/src/Judy.h" "${target_dir}/Judy.h" || return 1
|
||||
}
|
||||
|
||||
bundle_judy() {
|
||||
# If --build-judy flag or no Judy on the system and we're building the dbengine, bundle our own libJudy.
|
||||
# shellcheck disable=SC2235,SC2030,SC2031
|
||||
if [ -n "${NETDATA_DISABLE_DBENGINE}" ] || ([ -z "${NETDATA_BUILD_JUDY}" ] && [ -e /usr/include/Judy.h ]); then
|
||||
return 0
|
||||
elif [ -n "${NETDATA_BUILD_JUDY}" ]; then
|
||||
progress "User requested bundling of libJudy, building it now"
|
||||
elif [ ! -e /usr/include/Judy.h ]; then
|
||||
progress "/usr/include/Judy.h does not exist, but we need libJudy, building our own copy"
|
||||
fi
|
||||
|
||||
[ -n "${GITHUB_ACTIONS}" ] && echo "::group::Bundling libJudy."
|
||||
|
||||
progress "Prepare libJudy"
|
||||
|
||||
JUDY_PACKAGE_VERSION="$(cat packaging/judy.version)"
|
||||
|
||||
tmp="$(mktemp -d -t netdata-judy-XXXXXX)"
|
||||
JUDY_PACKAGE_BASENAME="v${JUDY_PACKAGE_VERSION}.tar.gz"
|
||||
|
||||
if fetch_and_verify "judy" \
|
||||
"https://github.com/netdata/libjudy/archive/${JUDY_PACKAGE_BASENAME}" \
|
||||
"${JUDY_PACKAGE_BASENAME}" \
|
||||
"${tmp}" \
|
||||
"${NETDATA_LOCAL_TARBALL_OVERRIDE_JUDY}"; then
|
||||
if run tar --no-same-owner -xf "${tmp}/${JUDY_PACKAGE_BASENAME}" -C "${tmp}" &&
|
||||
build_judy "${tmp}/libjudy-${JUDY_PACKAGE_VERSION}" &&
|
||||
copy_judy "${tmp}/libjudy-${JUDY_PACKAGE_VERSION}" &&
|
||||
rm -rf "${tmp}"; then
|
||||
run_ok "libJudy built and prepared."
|
||||
NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS} --with-bundled-libJudy"
|
||||
else
|
||||
if [ -n "${NETDATA_BUILD_JUDY}" ]; then
|
||||
[ -n "${GITHUB_ACTIONS}" ] && echo "::endgroup::"
|
||||
fatal "failed to build libJudy." I0003
|
||||
else
|
||||
run_failed "Failed to build libJudy, dbengine support will be disabled."
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [ -n "${NETDATA_BUILD_JUDY}" ]; then
|
||||
[ -n "${GITHUB_ACTIONS}" ] && echo "::endgroup::"
|
||||
fatal "Unable to fetch sources for libJudy, which is required for this build of Netdata." I0004
|
||||
else
|
||||
run_failed "Unable to fetch sources for libJudy, which is required for this build of Netdata."
|
||||
fi
|
||||
fi
|
||||
|
||||
[ -n "${GITHUB_ACTIONS}" ] && echo "::endgroup::"
|
||||
}
|
||||
|
||||
bundle_judy
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
build_jsonc() {
|
||||
env_cmd=''
|
||||
|
|
|
@ -143,14 +143,12 @@ BuildRequires: openssl-devel
|
|||
%if 0%{?suse_version}
|
||||
BuildRequires: protobuf-devel
|
||||
BuildRequires: libprotobuf-c-devel
|
||||
BuildRequires: judy-devel
|
||||
BuildRequires: liblz4-devel
|
||||
BuildRequires: libjson-c-devel
|
||||
%else
|
||||
%if 0%{?fedora}
|
||||
BuildRequires: protobuf-devel
|
||||
BuildRequires: protobuf-c-devel
|
||||
BuildRequires: Judy-devel
|
||||
BuildRequires: lz4-devel
|
||||
BuildRequires: json-c-devel
|
||||
%else
|
||||
|
@ -227,10 +225,6 @@ happened, on your systems and applications.
|
|||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
# Only bundle libJudy if this isn't Fedora or SUSE
|
||||
%if 0%{!?fedora:1} && 0%{!?suse_version:1}
|
||||
export CFLAGS="${CFLAGS} -fPIC" && ${RPM_BUILD_DIR}/%{name}-%{version}/packaging/bundle-judy.sh ${RPM_BUILD_DIR}/%{name}-%{version}
|
||||
%endif
|
||||
# Only bundle protobuf on CentOS 7 or earlier
|
||||
%if 0%{?centos_ver:1}
|
||||
%if %{centos_ver} < 8
|
||||
|
@ -259,9 +253,6 @@ autoreconf -ivf
|
|||
%if 0%{!?_have_ebpf}
|
||||
--disable-ebpf
|
||||
%endif
|
||||
%if 0%{!?fedora:1} && 0%{!?suse_version:1}
|
||||
--with-bundled-libJudy \
|
||||
%endif
|
||||
%if 0%{?centos_ver:1}
|
||||
%if %{centos_ver} < 8
|
||||
--with-bundled-protobuf \
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
JUDY_TARBALL="v$(cat "${1}/packaging/judy.version").tar.gz"
|
||||
JUDY_BUILD_PATH="${1}/externaldeps/libJudy/libjudy-$(cat "${1}/packaging/judy.version")"
|
||||
|
||||
mkdir -p "${1}/externaldeps/libJudy" || exit 1
|
||||
curl -sSL --connect-timeout 10 --retry 3 "https://github.com/netdata/libjudy/archive/${JUDY_TARBALL}" > "${JUDY_TARBALL}" || exit 1
|
||||
sha256sum -c "${1}/packaging/judy.checksums" || exit 1
|
||||
tar -xzf "${JUDY_TARBALL}" -C "${1}/externaldeps/libJudy" || exit 1
|
||||
OLDPWD="${PWD}"
|
||||
cd "${JUDY_BUILD_PATH}" || exit 1
|
||||
libtoolize --force --copy || exit 1
|
||||
aclocal || exit 1
|
||||
autoheader || exit 1
|
||||
automake --add-missing --force --copy --include-deps || exit 1
|
||||
autoconf || exit 1
|
||||
./configure --disable-dependency-tracking || exit 1
|
||||
make -C src || exit 1
|
||||
ar -r src/libJudy.a src/Judy*/*.o || exit 1
|
||||
cd "${OLDPWD}" || exit 1
|
||||
|
||||
cp -a "${JUDY_BUILD_PATH}/src/libJudy.a" "${1}/externaldeps/libJudy" || exit 1
|
||||
cp -a "${JUDY_BUILD_PATH}/src/Judy.h" "${1}/externaldeps/libJudy" || exit 1
|
|
@ -8,8 +8,6 @@ FROM netdata/builder:latest as builder
|
|||
# One of 'nightly' or 'stable'
|
||||
ARG RELEASE_CHANNEL=nightly
|
||||
|
||||
ENV JUDY_VER 1.0.5
|
||||
|
||||
ARG CFLAGS
|
||||
|
||||
ENV CFLAGS=$CFLAGS
|
||||
|
|
|
@ -24,7 +24,6 @@ declare -a package_tree=(
|
|||
libuv
|
||||
lz4
|
||||
openssl
|
||||
judy
|
||||
libelf
|
||||
git
|
||||
pkgconfig
|
||||
|
|
|
@ -139,9 +139,6 @@ validate_tree_centos() {
|
|||
echo >&2 " > Updating libarchive ..."
|
||||
dnf ${opts} install libarchive
|
||||
|
||||
echo >&2 " > Installing Judy-devel directly ..."
|
||||
dnf ${opts} install http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/Judy-devel-1.0.5-18.module_el8.3.0+757+d382997d.x86_64.rpm
|
||||
dnf makecache --refresh
|
||||
elif [[ $(os_version) =~ ^7(\..*)?$ ]]; then
|
||||
package_manager=yum
|
||||
echo >&2 " > Checking for EPEL ..."
|
||||
|
|
|
@ -31,7 +31,6 @@ package_tree="
|
|||
libuv1-dev
|
||||
liblz4-dev
|
||||
libssl-dev
|
||||
libjudy-dev
|
||||
libelf-dev
|
||||
python
|
||||
python3
|
||||
|
|
|
@ -43,7 +43,6 @@ declare -a package_tree=(
|
|||
libuv-devel
|
||||
lz4-devel
|
||||
openssl-devel
|
||||
Judy-devel
|
||||
elfutils-libelf-devel
|
||||
git
|
||||
pkgconfig
|
||||
|
|
|
@ -25,7 +25,6 @@ package_tree="
|
|||
libuv
|
||||
liblz4
|
||||
openssl
|
||||
Judy
|
||||
python3
|
||||
"
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ package_tree="
|
|||
dev-libs/libuv
|
||||
app-arch/lz4
|
||||
dev-libs/openssl
|
||||
dev-libs/judy
|
||||
virtual/libelf
|
||||
dev-lang/python
|
||||
dev-libs/libuv
|
||||
|
|
|
@ -29,7 +29,6 @@ declare -a package_tree=(
|
|||
libuv-devel
|
||||
liblz4-devel
|
||||
libopenssl-devel
|
||||
judy-devel
|
||||
libelf-devel
|
||||
git
|
||||
tar
|
||||
|
|
|
@ -31,7 +31,6 @@ package_tree="
|
|||
libuv1-dev
|
||||
liblz4-dev
|
||||
libssl-dev
|
||||
libjudy-dev
|
||||
libelf-dev
|
||||
python3
|
||||
"
|
||||
|
|
|
@ -665,13 +665,6 @@ declare -A pkg_automake=(
|
|||
['default']="automake"
|
||||
)
|
||||
|
||||
# required to bundle libJudy
|
||||
declare -A pkg_libtool=(
|
||||
['gentoo']="sys-devel/libtool"
|
||||
['clearlinux']="c-basic"
|
||||
['default']="libtool"
|
||||
)
|
||||
|
||||
# Required to build libwebsockets and libmosquitto on some systems.
|
||||
declare -A pkg_cmake=(
|
||||
['gentoo']="dev-util/cmake"
|
||||
|
@ -1112,17 +1105,6 @@ declare -A pkg_openssl=(
|
|||
['default']="openssl-devel"
|
||||
)
|
||||
|
||||
declare -A pkg_judy=(
|
||||
['debian']="libjudy-dev"
|
||||
['ubuntu']="libjudy-dev"
|
||||
['suse']="judy-devel"
|
||||
['gentoo']="dev-libs/judy"
|
||||
['arch']="judy"
|
||||
['freebsd']="Judy"
|
||||
['fedora']="Judy-devel"
|
||||
['default']="NOTREQUIRED"
|
||||
)
|
||||
|
||||
declare -A pkg_python3=(
|
||||
['gentoo']="dev-lang/python"
|
||||
['sabayon']="dev-lang/python:3.4"
|
||||
|
@ -1289,7 +1271,6 @@ packages() {
|
|||
suitable_package autoconf-archive
|
||||
require_cmd autogen || suitable_package autogen
|
||||
require_cmd automake || suitable_package automake
|
||||
require_cmd libtoolize || suitable_package libtool
|
||||
require_cmd pkg-config || suitable_package pkg-config
|
||||
require_cmd cmake || suitable_package cmake
|
||||
|
||||
|
@ -1361,7 +1342,6 @@ packages() {
|
|||
suitable_package libuv
|
||||
suitable_package lz4
|
||||
suitable_package openssl
|
||||
suitable_package judy
|
||||
fi
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
@ -1579,9 +1559,6 @@ validate_tree_centos() {
|
|||
echo >&2 " > Updating libarchive ..."
|
||||
run ${sudo} yum ${opts} install libarchive
|
||||
|
||||
echo >&2 " > Installing Judy-devel directly ..."
|
||||
run ${sudo} yum ${opts} install http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/Judy-devel-1.0.5-18.module_el8.3.0+757+d382997d.x86_64.rpm
|
||||
|
||||
elif [[ "${version}" =~ ^7(\..*)?$ ]]; then
|
||||
echo >&2 " > Checking for EPEL ..."
|
||||
if ! rpm -qa | grep epel-release > /dev/null; then
|
||||
|
|
|
@ -20,7 +20,7 @@ This is how to install the latest Netdata version on FreeBSD:
|
|||
Install required packages (**need root permission**):
|
||||
|
||||
```sh
|
||||
pkg install bash e2fsprogs-libuuid git curl autoconf automake pkgconf pidof Judy liblz4 libuv json-c cmake gmake
|
||||
pkg install bash e2fsprogs-libuuid git curl autoconf automake pkgconf pidof liblz4 libuv json-c cmake gmake
|
||||
```
|
||||
|
||||
Download Netdata:
|
||||
|
|
|
@ -25,9 +25,6 @@ and other operating systems and is regularly tested. You can find this tool [her
|
|||
- **Alpine** Linux and its derivatives
|
||||
- You have to install `bash` yourself, before using the installer.
|
||||
|
||||
- **Arch** Linux and its derivatives
|
||||
- You need arch/aur for package Judy.
|
||||
|
||||
- **Gentoo** Linux and its derivatives
|
||||
|
||||
- **Debian** Linux and its derivatives (including **Ubuntu**, **Mint**)
|
||||
|
@ -67,16 +64,16 @@ This is how to do it by hand:
|
|||
|
||||
```sh
|
||||
# Debian / Ubuntu
|
||||
apt-get install zlib1g-dev uuid-dev libuv1-dev liblz4-dev libjudy-dev libssl-dev libelf-dev libmnl-dev libprotobuf-dev protobuf-compiler gcc g++ make git autoconf autoconf-archive autogen automake pkg-config curl python cmake
|
||||
apt-get install zlib1g-dev uuid-dev libuv1-dev liblz4-dev libssl-dev libelf-dev libmnl-dev libprotobuf-dev protobuf-compiler gcc g++ make git autoconf autoconf-archive autogen automake pkg-config curl python cmake
|
||||
|
||||
# Fedora
|
||||
dnf install zlib-devel libuuid-devel libuv-devel lz4-devel Judy-devel openssl-devel elfutils-libelf-devel libmnl-devel protobuf-devel protobuf-compiler gcc gcc-c++ make git autoconf autoconf-archive autogen automake pkgconfig curl findutils python cmake
|
||||
dnf install zlib-devel libuuid-devel libuv-devel lz4-devel openssl-devel elfutils-libelf-devel libmnl-devel protobuf-devel protobuf-compiler gcc gcc-c++ make git autoconf autoconf-archive autogen automake pkgconfig curl findutils python cmake
|
||||
|
||||
# CentOS / Red Hat Enterprise Linux
|
||||
yum install autoconf automake curl gcc gcc-c++ git libmnl-devel libuuid-devel openssl-devel libuv-devel lz4-devel Judy-devel elfutils-libelf-devel protobuf protobuf-devel protobuf-compiler make nc pkgconfig python zlib-devel cmake
|
||||
yum install autoconf automake curl gcc gcc-c++ git libmnl-devel libuuid-devel openssl-devel libuv-devel lz4-devel elfutils-libelf-devel protobuf protobuf-devel protobuf-compiler make nc pkgconfig python zlib-devel cmake
|
||||
|
||||
# openSUSE
|
||||
zypper install zlib-devel libuuid-devel libuv-devel liblz4-devel judy-devel libopenssl-devel libelf-devel libmnl-devel protobuf-devel gcc gcc-c++ make git autoconf autoconf-archive autogen automake pkgconfig curl findutils python cmake
|
||||
zypper install zlib-devel libuuid-devel libuv-devel liblz4-devel libopenssl-devel libelf-devel libmnl-devel protobuf-devel gcc gcc-c++ make git autoconf autoconf-archive autogen automake pkgconfig curl findutils python cmake
|
||||
```
|
||||
|
||||
Once Netdata is compiled, to run it the following packages are required (already installed using the above commands):
|
||||
|
@ -117,7 +114,6 @@ Netdata DB engine can be enabled when these are installed (they are optional):
|
|||
| package | description|
|
||||
|:-----:|-----------|
|
||||
| `liblz4` | Extremely fast compression algorithm, version r129 or greater|
|
||||
| `Judy` | General purpose dynamic array|
|
||||
| `openssl`| Cryptography and SSL/TLS toolkit|
|
||||
|
||||
*Netdata will greatly benefit if you have the above packages installed, but it will still work without them.*
|
||||
|
@ -175,8 +171,6 @@ yum install -y http://repo.okay.com.mx/centos/8/x86_64/release/okay-release-1-3.
|
|||
# Install Devel Packages
|
||||
yum install autoconf automake curl gcc git cmake libuuid-devel openssl-devel libuv-devel lz4-devel make nc pkgconfig python3 zlib-devel
|
||||
|
||||
# Install Judy-Devel directly
|
||||
yum install -y http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/Judy-devel-1.0.5-18.module_el8.1.0+217+4d875839.x86_64.rpm
|
||||
```
|
||||
|
||||
## Install Netdata
|
||||
|
|
|
@ -25,7 +25,6 @@ pkg install -y pkgconf bash e2fsprogs-libuuid libuv nano
|
|||
Then run the following commands to download various dependencies from the FreeBSD repository.
|
||||
|
||||
```sh
|
||||
pkg add http://pkg.freebsd.org/FreeBSD:12:amd64/latest/All/Judy-1.0.5_3.txz
|
||||
pkg add http://pkg.freebsd.org/FreeBSD:12:amd64/latest/All/json-c-0.15_1.txz
|
||||
pkg add http://pkg.freebsd.org/FreeBSD:12:amd64/latest/All/py38-certifi-2021.10.8.txz
|
||||
pkg add http://pkg.freebsd.org/FreeBSD:12:amd64/latest/All/py38-asn1crypto-1.4.0.txz
|
||||
|
|
|
@ -32,7 +32,6 @@ Additionally, the following build time features require additional dependencies:
|
|||
- dbengine metric storage:
|
||||
- liblz4 r129 or newer
|
||||
- OpenSSL 1.0 or newer (LibreSSL _amy_ work, but is largely untested).
|
||||
- [libJudy](http://judy.sourceforge.net/)
|
||||
- Netdata Cloud support:
|
||||
- A working internet connection
|
||||
- A recent version of CMake
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
e623a06bf091758b43f5cd97c3609f8109442d1a0441bc44819b60f2861c61b1 v1.0.5-netdata2.tar.gz
|
|
@ -1 +0,0 @@
|
|||
1.0.5-netdata2
|
Loading…
Add table
Reference in a new issue