From 2863487991134c3243eae12726967eed2a9d140b Mon Sep 17 00:00:00 2001 From: Sears Russell Date: Wed, 23 Apr 2008 01:41:57 +0000 Subject: [PATCH] Documentation update; added more sections under modules, reduced amount of cruft generated by doxygen. --- Makefile.am | 1 - doc/Doxyfile-developers | 1166 +++++++++++++++++++++++++++-- doc/figures/StasisDBMS.png | Bin 0 -> 88512 bytes doc/figures/StasisDBMS.svg | 413 ++++++++++ doc/modules | 50 ++ src/stasis/bufferPool.c | 4 +- src/stasis/io/non_blocking.c | 2 +- src/stasis/logger/logger2.c | 4 +- src/stasis/operations/arrayList.c | 14 - src/stasis/recovery2.c | 8 +- src/stasis/transactional2.c | 2 - stasis/bufferManager.h | 2 +- stasis/logger/logger2.h | 4 +- stasis/operations.h | 13 +- stasis/operations/arrayList.h | 88 ++- stasis/operations/lsmTree.h | 10 +- stasis/page.h | 103 ++- stasis/transactional.h | 269 ++++--- 18 files changed, 1930 insertions(+), 223 deletions(-) create mode 100644 doc/figures/StasisDBMS.png create mode 100644 doc/figures/StasisDBMS.svg create mode 100644 doc/modules diff --git a/Makefile.am b/Makefile.am index c990590..1b767c3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,6 @@ ACLOCAL_AMFLAGS = -I m4 #-Wconversion docs: - doxygen doc/Doxyfile-api doxygen doc/Doxyfile-developers tidy: precoverage diff --git a/doc/Doxyfile-developers b/doc/Doxyfile-developers index 4b7cdf6..8d83c06 100644 --- a/doc/Doxyfile-developers +++ b/doc/Doxyfile-developers @@ -1,231 +1,1309 @@ -# Doxyfile 1.3.6-20040222 +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + PROJECT_NAME = "Stasis" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + PROJECT_NUMBER = 1 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + OUTPUT_DIRECTORY = doc/developers + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + SUBGROUPING = YES + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + QUIET = YES -WARNINGS = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = NO + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + WARN_IF_DOC_ERROR = YES -WARN_FORMAT = "$file:$line: $text" + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + WARN_LOGFILE = + #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = stasis \ - src \ - test -# libdfa \ -# pbl \ -# + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = doc/modules \ + stasis \ + src +# test/stasis + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + FILE_PATTERNS = *.c \ *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + EXCLUDE = src/2pc \ - src/libdfa \ - src/pbl \ - test/2pc \ - test/cht \ - test/dfa \ - test/lladd-old \ - test/messages \ - test/monotree \ - src/apps/cht + src/libdfa \ + src/pbl \ + src/pobj \ + test/2pc \ + test/cht \ + test/dfa \ + test/lladd-old \ + test/messages \ + test/monotree \ + src/apps \ + src/timing + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + EXAMPLE_PATH = . + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = doc/figures + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = "perl -pe 's/^START_TEST\(([^\)]+)\)/test_$1()/;s/^END_TEST//;' " + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + FILTER_SOURCE_FILES = NO + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + SOURCE_BROWSER = YES -INLINE_SOURCES = NO # YES -STRIP_CODE_COMMENTS = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + VERBATIM_HEADERS = YES + #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + IGNORE_PREFIX = + #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + GENERATE_HTMLHELP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + TREEVIEW_WIDTH = 250 + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + LATEX_HIDE_INDICES = NO + #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + RTF_EXTENSIONS_FILE = + #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + MAN_LINKS = NO + #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + XML_PROGRAMLISTING = YES + #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + GENERATE_AUTOGEN_DEF = NO + #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + PERLMOD_MAKEVAR_PREFIX = + #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -## Needed for doxygen to make sane documentation from check tests. -# or, I'll just write a perl script since it's easier. -#PREDEFINED = START_TEST END_TEST -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = NO -#YES -QUIET=YES -WARNINGS=NO -# Muh-ha-ha-ha_ha -INPUT_FILTER="perl -pe 's/^START_TEST\(([^\)]+)\)/test_$1()/;s/^END_TEST//;'" +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = NO + #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + PERL_PATH = /usr/bin/perl + #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = NO # YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + CALL_GRAPH = YES + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + DOT_CLEANUP = YES + #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + SEARCHENGINE = YES diff --git a/doc/figures/StasisDBMS.png b/doc/figures/StasisDBMS.png new file mode 100644 index 0000000000000000000000000000000000000000..bb173732fe3b4d73db9f9b165b67ea2655b99137 GIT binary patch literal 88512 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 + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + Query Processor + RelationalStorage API + Tuple Store + Indices / Ref.Integrity + Allocation andspace mgmt + Recovery + Page formats/ metadata + BufferManager + Logger + Page evictionLRU/DBMIN/? + OS Wrappers: I/O, Memory mgmtThreading, etc... + StasisCoreLibrary + Operations API + Record API + TransactionalPage API + StasisExtensions + + + + Lock Manager + + + + + diff --git a/doc/modules b/doc/modules new file mode 100644 index 0000000..d11bced --- /dev/null +++ b/doc/modules @@ -0,0 +1,50 @@ +/** + @defgroup LLADD_CORE +*//** + @defgroup BUFFER_MANAGER + @ingroup LLADD_CORE +*//** @defgroup BUFFER_MANAGER_IMPLEMENTATIONS + @ingroup BUFFER_MANAGER +*//** + @defgroup PAGE_EVICTION + @ingroup BUFFER_MANAGER +*//** + @defgroup LOGGER + @ingroup LLADD_CORE +*//** + @defgroup LOGGING_DISCIPLINES + @ingroup LOGGER +*//** + @defgroup RECOVERY + @ingroup LLADD_CORE +*//** + @defgroup PAGE_FORMATS +*//** + @defgroup PAGE_HOWTO + @ingroup PAGE_FORMATS +*//** + @defgroup PAGE_HEADER + @ingroup PAGE_FORMATS +*//** + @defgroup PAGE_UTIL + @ingroup PAGE_FORMATS +*//** + @defgroup PAGE_RECORD_INTERFACE + @ingroup PAGE_FORMATS +*//** + @defgroup PAGE_IMPLEMENTATIONS + @ingroup PAGE_FORMATS +*//** + @defgroup ALLOCATION +*//** + @defgroup OPERATIONS +*//** + @defgroup COLLECTIONS + @ingroup OPERATIONS +*//** + @defgroup ARRAY_LIST + @ingroup COLLECTIONS +*//** + @defgroup ROSE + @ingroup OPERATIONS +*/ \ No newline at end of file diff --git a/src/stasis/bufferPool.c b/src/stasis/bufferPool.c index d11f8e9..a0ac7dd 100644 --- a/src/stasis/bufferPool.c +++ b/src/stasis/bufferPool.c @@ -41,7 +41,9 @@ terms specified in this license. ---*/ /** - * @file Implementation of in memory buffer pool + * @file + * + * Implementation of in memory buffer pool * * $Id$ * diff --git a/src/stasis/io/non_blocking.c b/src/stasis/io/non_blocking.c index 6670cac..fdc46a9 100644 --- a/src/stasis/io/non_blocking.c +++ b/src/stasis/io/non_blocking.c @@ -180,7 +180,7 @@ typedef struct nbw_impl { static inline void freeFastHandle(nbw_impl * impl, const tree_node * n); /** Obtain a slow handle from the pool of existing ones, or obtain a new one - by calling impl->slow_factory.. */ + by calling impl.slow_factory. */ static stasis_handle_t * getSlowHandle(nbw_impl * impl) { pthread_mutex_lock(&impl->mut); stasis_handle_t * slow diff --git a/src/stasis/logger/logger2.c b/src/stasis/logger/logger2.c index 5b278d0..714f362 100644 --- a/src/stasis/logger/logger2.c +++ b/src/stasis/logger/logger2.c @@ -41,7 +41,9 @@ terms specified in this license. ---*/ /** - @file Abstract log implementation. Provides access to methods that + @file + + Abstract log implementation. Provides access to methods that directly read and write log entries, force the log to disk, etc. @todo Switch logger2 to use function pointers diff --git a/src/stasis/operations/arrayList.c b/src/stasis/operations/arrayList.c index 8e6ce3d..f025d8b 100644 --- a/src/stasis/operations/arrayList.c +++ b/src/stasis/operations/arrayList.c @@ -12,19 +12,6 @@ #define _XOPEN_SOURCE 600 #include - - -/** - Implement resizable arrays, just like java's ArrayList class. - - Essentially, the base page contains a fixed size array of rids - pointing at contiguous blocks of pages. Each block is twice as - big as the previous block. - - The base block is of type FIXED_PAGE, of int's. The first few slots are reserved: - -*/ - typedef struct { int firstPage; int initialSize; @@ -166,7 +153,6 @@ static compensated_function int TarrayListExtendInternal(int xid, recordid rid, int blockSize = tlp.initialSize * pow(tlp.multiplier, i); int newFirstPage = TpageAllocMany(xid, blockSize); DEBUG("block %d\n", i); - /* We used to call OPERATION_INITIALIZE_FIXED_PAGE on each page in current indirection block. */ tmp.slot = i + FIRST_DATA_PAGE_OFFSET; /* Iterate over the (large number) of new blocks, clearing their contents */ /* @todo XXX arraylist generates N log entries initing pages. diff --git a/src/stasis/recovery2.c b/src/stasis/recovery2.c index 7df7da0..28ae124 100644 --- a/src/stasis/recovery2.c +++ b/src/stasis/recovery2.c @@ -1,6 +1,8 @@ /** - @file Implements three phase recovery + @file + + Implements three phase recovery */ @@ -20,7 +22,7 @@ #include #include -/** @todo Get rid of linkedlist.[ch] */ +/** @todo Get rid of linkedlist */ #include #include // Needed for pageReadLSN. @@ -28,7 +30,7 @@ static pblHashTable_t * transactionLSN; static LinkedList * rollbackLSNs = NULL; /** @todo There is no real reason to have this mutex (which prevents - concurrent aborts, except that we need to protect rollbackLSNs's + concurrent aborts), except that we need to protect rollbackLSNs's from concurrent modifications. */ static pthread_mutex_t rollback_mutex = PTHREAD_MUTEX_INITIALIZER; diff --git a/src/stasis/transactional2.c b/src/stasis/transactional2.c index 1103a97..00b247f 100644 --- a/src/stasis/transactional2.c +++ b/src/stasis/transactional2.c @@ -68,9 +68,7 @@ void setupOperationsTable() { operationsTable[OPERATION_NOOP] = getNoop(); operationsTable[OPERATION_INSTANT_SET] = getInstantSet(); operationsTable[OPERATION_ARRAY_LIST_ALLOC] = getArrayListAlloc(); - // operationsTable[OPERATION_INITIALIZE_FIXED_PAGE] = getInitFixed(); operationsTable[OPERATION_INITIALIZE_PAGE] = getInitializePage(); - // operationsTable[OPERATION_UNINITIALIZE_PAGE] = getUnInitPage(); operationsTable[OPERATION_LINEAR_INSERT] = getLinearInsert(); operationsTable[OPERATION_UNDO_LINEAR_INSERT] = getUndoLinearInsert(); diff --git a/stasis/bufferManager.h b/stasis/bufferManager.h index 530ab0f..e5dc5c3 100644 --- a/stasis/bufferManager.h +++ b/stasis/bufferManager.h @@ -73,7 +73,7 @@ terms specified in this license. When such a value is returned, the transaction aborts, and an error is passed up to the application. - * @ingroup LLADD_CORE + @ingroup BUFFER_MANAGER * $Id$ */ diff --git a/stasis/logger/logger2.h b/stasis/logger/logger2.h index eb8a5df..2616a7c 100644 --- a/stasis/logger/logger2.h +++ b/stasis/logger/logger2.h @@ -43,7 +43,9 @@ terms specified in this license. /** * @file * - * New version of logger. Based on logger.h + * Interface to Stasis' log file. + * + * @ingroup LOGGING_DISCIPLINE * * $Id$ * diff --git a/stasis/operations.h b/stasis/operations.h index 8cb04a7..5148334 100644 --- a/stasis/operations.h +++ b/stasis/operations.h @@ -45,10 +45,21 @@ terms specified in this license. * * Interface for defining new logical operations. * - * @ingroup LLADD_CORE OPERATIONS + * @ingroup OPERATIONS * @todo The functions in operations.h don't belong in the API, but it defines some constants and typedefs that should be there. * $Id$ */ +/** + @defgroup COLLECTIONS Collections + + Stasis provides a number of general-purpose data structures for use + by applications. + + Stasis provides a number of general-purpose data structures for use + by applications. This section documents these data structures and + associated interfaces, such as iterators. +*/ + #ifndef __OPERATIONS_H__ #define __OPERATIONS_H__ diff --git a/stasis/operations/arrayList.h b/stasis/operations/arrayList.h index 858bf85..c6e76f6 100644 --- a/stasis/operations/arrayList.h +++ b/stasis/operations/arrayList.h @@ -40,34 +40,86 @@ permission to use and distribute the software in accordance with the terms specified in this license. ---*/ /** - @file + @file - Implements an extendible array of fixed length records with O(1) - complexity for all operations. + @ingroup ARRAY_LIST - @ingroup OPERATIONS + @defgroup ARRAY_LIST ArrayList + + O(1) growable array. + + ArrayList provides an growable array of fixed length records with + O(1) complexity for all operations. The list grows by doubling the + amount of space it reserves each time the list is extended. + Therefore, this data structure can use up to twice as much storage + as is strictly necessary. + + These arrays are similar to those in Java's ArrayList class. + Essentially, the base page contains a fixed size array of recordid's + pointing at contiguous blocks of pages. Each block is twice as big + as the previous block. + + The base block is of type FIXED_PAGE, of int values. The first few slots + are reserved and store information about the arrayList (size of + array entries, number/size of allocated regions, etc.) + + @todo arrayList's base block should store pageid_t values, not ints. + + @ingroup COLLECTIONS $Id$ */ + +/** @ingroup ARRAY_LIST */ +/** @{ */ #ifndef __ARRAY_LIST_H #define __ARRAY_LIST_H +/** Allocate a new array list. + + @param xid The transaction allocating the new arrayList. + + @param numPages The number of pages to be allocated as part of the + first region. (The arraylist starts with zero capacity + regardless of this parameter's value.) + + @param multiplier Each time the array list runs out of space, the + allocate multipler times more space than last time. + + @param recordSize The size of the things stored in this arrayList. + Must fit on a single page (arrayList cannot store blobs.) + +*/ + compensated_function recordid TarrayListAlloc(int xid, int numPages, int multiplier, int recordSize); +/** + Extend the ArrayList in place. + + @param xid the transaction performing the expansion + @param rid the recordid pointing to the ArrayList. + @param slots the number of slots to end to the end of the ArrayList. + */ +compensated_function int TarrayListExtend(int xid, recordid rid, int slots); +/** + Do not call this function. + + @deprecated This function is known to be broken, and is only + called by a deprecated hash implementation. + */ +compensated_function int TarrayListInstantExtend(int xid, recordid rid, int slots); +/** + Get the length of an ArrayList. + + @param xid the transaction performing the expansion + @param rid the recordid pointing to the ArrayList. + @return The number of items stored in the ArrayList. + */ +compensated_function int TarrayListLength(int xid, recordid rid); + +/** Used by Tread() and Tset() to map from arrayList index to recordid. */ +recordid dereferenceArrayListRid(int xid, Page * p, int offset); Operation getArrayListAlloc(); -Operation getInitFixed(); -Operation getUnInitPage(); - -/** Initialized a fixed page with the maximum possible number of slots - allocated. The rid.size field is used to determine the size of - record that the slots can hold. */ -#define TinitFixed(xid, rid) Tupdate(xid, rid, NULL, OPERATION_INITIALIZE_FIXED_PAGE) -/** Un-initializes a page. */ -#define TunInitPage(xid, rid) Tupdate(xid, rid, NULL, OPERATION_UNINITIALIZE_PAGE) - -recordid dereferenceArrayListRid(int xid, Page * p, int offset); -compensated_function int TarrayListExtend(int xid, recordid rid, int slots); -compensated_function int TarrayListInstantExtend(int xid, recordid rid, int slots); -compensated_function int TarrayListLength(int xid, recordid rid); +/** @} */ #endif diff --git a/stasis/operations/lsmTree.h b/stasis/operations/lsmTree.h index a0fc7e9..6a5fea0 100644 --- a/stasis/operations/lsmTree.h +++ b/stasis/operations/lsmTree.h @@ -87,12 +87,14 @@ void TlsmFree(int xid, recordid tree, lsm_page_deallocator_t dealloc, /** Lookup a leaf page. + @param xid The transaction that is looking up this page + + @param tree The tree to be queried. + @param key The value you're looking for. The first page that may contain this value will be returned. (lsmTree supports - duplicate keys...) - - @param keySize Must match the keySize passed to TlsmCreate. - Currently unused. + duplicate keys...) LSM trees currently store fixed + length keys, so there is no keySize parameter. */ pageid_t TlsmFindPage(int xid, recordid tree, const byte *key); diff --git a/stasis/page.h b/stasis/page.h index c7adb15..ed40c95 100644 --- a/stasis/page.h +++ b/stasis/page.h @@ -48,13 +48,13 @@ terms specified in this license. * This file provides a re-entrant interface for pages that are labeled * with an LSN and a page type. * - * @ingroup LLADD_CORE pageFormats + * @ingroup PAGE_FORMATS * * $Id$ */ /** - @defgroup pageFormats Page format implementations + @defgroup PAGE_FORMATS Page layouts Stasis allows developers to define their own on-disk page formats. Currently, each page format must end with a hard-coded header @@ -90,7 +90,7 @@ terms specified in this license. and APIs. However, Stasis's record oriented page interface provides a default set of methods for page access. - @see pageRecordInterface + @see PAGE_RECORD_INTERFACE @todo Page deallocators should call stasis_page_cleanup() @todo Create variant of loadPage() that takes a page type @@ -196,8 +196,7 @@ struct Page_s { /*@}*/ /** - @defgroup pageLSNHeaderGeneric LSN and Page Types - @ingroup pageFormats + @defgroup PAGE_HEADER Default page header Most Stasis pages contain an LSN and a page type. These are used by recovery to determine whether or not to perform redo. At @@ -279,8 +278,7 @@ lsn_t stasis_page_lsn_read(const Page * page); /*@}*/ /** - @defgroup pageUtils Utility methods for page manipulation - @ingroup pageFormats + @defgroup PAGE_UTIL Byte-level page manipulation These methods make it easy to manipulate pages that use a standard Stasis header (one with an LSN and page type). @@ -291,6 +289,60 @@ lsn_t stasis_page_lsn_read(const Page * page); Methods with "_ptr_" in their names take non-const pages, and return non-const pointers. + @par Implementing new pointer arithmetic macros + + Stasis page type implementations typically do little more than + pointer arithmetic. However, implementing page types cleanly and + portably is a bit tricky. Stasis has settled upon a compromise in + this matter. Its page file formats are compatible within a single + architecture, but not across systems with varying lengths of + primitive types, or that vary in endianness. + + Over time, types that vary in length such as "int", "long", etc + will be removed from Stasis, but their usage still exists in a few + places. Once they have been removed, file compatibility problems + should be limited to endianness (though application code will still + be free to serialize objects in a non-portable manner). + + Most page implementations leverage C's pointer manipulation + semantics to lay out pages. Rather than casting pointers to + char*'s and then manually calculating byte offsets using sizeof(), + the existing page types prefer to cast pointers to appropriate + types, and then add or subtract the appropriate number of values. + + For example, instead of doing this: + + @code + // p points to an int, followed by a two bars, then the foo whose address + // we want to calculate + + int * p; + foo* f = (foo*)( ((char*)p) + sizeof(int) + 2 * sizeof(bar)) + @endcode + + the implementations would do this: + + @code + int * p; + foo * f = (foo*)( ((bar*)(p+1)) + 2 ) + @endcode + + The main disadvantage of this approach is the large number of ()'s + involved. However, it lets the compiler deal with the underlying + multiplications, and often reduces the number of casts, leading to + slightly more readable code. Take this implementation of + stasis_page_type_ptr(), for example: + + @code + int * stasis_page_type_ptr(Page *p) { + return ( (int*)stasis_page_lsn_ptr(Page *p) ) - 1; + } + @endcode + + Here, the page type is stored as an integer immediately before the + LSN pointer. Using arithmetic over char*'s would require an extra + cast to char*, and a multiplication by sizeof(int). + */ /*@{*/ static inline byte* @@ -365,14 +417,37 @@ void stasis_page_init(); void stasis_page_deinit(); /** - @defgroup pageRecordInterface Record-oriented page interface - @ingroup pageFormats + @defgroup PAGE_RECORD_INTERFACE Record interface + @ingroup PAGE_FORMATS + + Page formats define the layout of data on pages. Currently, all + pages contain a header with an LSN and a page type in it. This + information is used by recovery and the buffer manager to invoke + callbacks at appropriate times. (LSN-free pages are currently not + supported.) + + Stasis' record-oriented page interface uses the page type to determine + which page implementation should be used to access or modify + records. This API's functions begin with "stasis_record". Two + commonly used examples are stasis_read_record() and + stasis_write_record(). + + This interface is not re-entrant. Rather, page implementations + assume that their callers will latch pages using + readLock(p->rwlatch) and writeLock(p-rwlatch) before attempting to + access the page. A second latch, p->loadlatch, should not be + acquired by page manipulation code. Instead, it is used by the + buffer manager to protect against races during page eviction. + + @par Registering new page type implementations + + Page implementations are registered with Stasis by passing a + page_impl struct into registerPageType(). page_impl.page_type + should contain an integer that is unique across all page types, + while the rest of the fields contain function pointers to the page + type's implementation. + - Stasis provides a default record-oriented interface to page - implementations. By defining these methods, and registering - appropriate callbacks, page implementations allow callers to - access their data through standard Stasis methods such as Tread() - and Tset(). */ /*@{*/ static const size_t USABLE_SIZE_OF_PAGE = (PAGE_SIZE - sizeof(lsn_t) - sizeof(int)); diff --git a/stasis/transactional.h b/stasis/transactional.h index 8854fd2..cf41d2a 100644 --- a/stasis/transactional.h +++ b/stasis/transactional.h @@ -56,13 +56,59 @@ terms specified in this license. /** @mainpage Introduction to Stasis - This is the main section. -
    -
  • @ref gettingStarted
  • -
  • @ref pageFormats
  • -
  • @ref LLADD_CORE
  • -
  • @ref OPERATIONS
  • -
+ Stasis is a flexible transactional storage library. Unlike + existing systems, it provides application and server developers + with much freedom, but little guidance regarding page file layouts, + data models, and concurrency schemes. This often means that Stasis + can outperform general purpose storage solutions by orders of + magnitude, but it does require more effort on the part of its end + users. We are in the process of implementing a library of commonly + used, general-purpose transactional data structures on top of + Stasis. + + @section The Stasis data model + + Stasis does not really have a data model. While designing and + implementing Stasis, we focused on providing end users with + mechanisms, not policy. As much as possible, we have + avoiding hardcoding application-specific implmentation details such + as data formats and concurrency models. Instead, Stasis provides a + number of reusable lower-level mechanisms that make it easy for + applications to implement custom transactional storage systems. + + At the lowest level, Stasis provides transactional pages; + the buffer manager manages a set of pages and regions on disk, and + coordinates with the log and other Stasis mechanisms to provide + recovery and concurrent transactions. On top of this low level + API, we have developed record oriented interfaces that facilitate + development and interchangability of new page formats. Conformance + to these APIs is recommended, but not required. Stasis records are + simply arrays of bytes (not tuples). A Stasis recordid is simply a + record that contains a pointer to another record. + + Stasis's @ref OPERATIONS provide a set of methods that manipulate + records in a transactional, durable fashion. They are implemented + on top of the record (and sometimes page) API's, and range from low + level access methods like record reads and writes to higher level + data structure implementations, such as hash tables and log-oriented + tree indexes. Stasis' library of operations makes use of a number of + different @ref LOGGING_DISCIPLINES. Most new operations will want to + choose one of these disciplines, as many subtlties arise during the + development of new concurrent, high-performance recovery + algorithms. + + @image html "StasisDBMS.png" "Stasis' place in a conventional DBMS architecture" + + @section Tutorial + + @ref gettingStarted explains how to download and compile Stasis, + and includes a number of sample programs. + + The "Modules" section in the navigation pane contains detailed + documentation of Stasis' major components. + + @see Modules + */ /** @@ -109,11 +155,11 @@ terms specified in this license. This will fail if your system defaults to an old (pre-1.7) version of autotools. Fortunately, multiple versions of autotools may exist on the same system. Execute the following commands to - compile with version 1.8 of autotools: + compile with version 1.8 (or 1.9) of autotools: @code - $ ./reconf-1.8 + $ ./reconf-1.8 # or ./reconf-1.9 $ ./configure --quiet $ make -j4 > /dev/null $ cd test/stasis @@ -133,7 +179,7 @@ terms specified in this license. @section usage Using Stasis in your software - Synopsis: + Synopsis (examples/ex1.c): @include examples/ex1.c @@ -153,25 +199,27 @@ terms specified in this license. or naming of objects within the page file. This means that the application must maintain such information manually. - In order to facilitate this, Stasis provides the function TgetRecordType() and - guarantees that the first recordid returned by any allocation will point to - the same page and slot as the constant ROOT_RECORD. TgetRecordType - will return NULLRID if the record passed to it does not exist. + In order to facilitate this, Stasis provides the function + TrecordType() and guarantees that the first recordid returned by + any allocation will point to the same page and slot as the constant + ROOT_RECORD. TrecordType() will return UNINITIALIZED_RECORD if the + record passed to it does not exist. A second function, + TrecordSize() returns the size of a record in bytes, or -1 if the + record does not exist. - Therefore, the following code will safely initialize or reopen a data - store: + Therefore, the following code (found in examples/ex2.c) will safely + initialize or reopen a data store: @include examples/ex2.c - @see test.c for a complete, executable example of reopening an existing store. - @todo Explain how to determine the correct value of rootEntry.size in the case of a hashtable. - @see OPERATIONS for more operations that may be useful for your software. + @see OPERATIONS for other transactional primitives that may be + useful for your software. - @subsection consistency Using Stasis in multithreaded applications. + @subsection consistency Using Stasis in multithreaded applications Unless otherwise noted, Stasis' operations are re-entrant. This means that an application may call them concurrently without @@ -229,7 +277,7 @@ terms specified in this license. Stasis components can be classified as follows: - I/O utilities (file handles, OS compatibility wrappers) - - Write ahead logging component interfaces (logger.h, XXX) + - Write ahead logging component interfaces (logger.h, logger/inMemoryLog.h logger/logEntry.h logger/logger2.h logger/logHandle.h logger/logMemory.h logger/logWriter.h) - Write ahead logging component implementations (hash based buffer manager, in memory log, etc...) - Page formats and associated operations (page/slotted.c page/fixed.c) - Application visible methods (Talloc, Tset, ThashInsert, etc) @@ -353,106 +401,50 @@ terms specified in this license. Interesting files in this part of Stasis include logger2.c, bufferManager.c, and recovery2.c. - @subsection page Page types + @subsection page Custom page formats - Page types define the layout of data on pages. Currently, all - pages contain a header with an LSN and a page type in it. This - information is used by recovery and the buffer manager to invoke - callbacks at appropriate times. (LSN-free pages are currently not - supported.) + Stasis provides a default @ref PAGE_RECORD_INTERFACE to custom page + implementations. Methods that define their own log disciplines, or + otherwise need to bypass Stasis' default recovery mechanisms should + call into this API. - XXX: This section is not complete. - - @todo Discuss readRecord, writeRecord (high level page access - methods) - - @todo Explain the latching convention. (Also, explain which - latches are not to be used by page implementations, and which - latches may not be used by higher level code.) - - @par Registering new page type implementations - - Page implementations are registered with Stasis by passing a - page_impl struct into registerPageType(). page_impl.page_type - should contain an integer that is unique across all page types, - while the rest of the fields contain function pointers to the page - type's implementation. - - @par Pointer arithmetic - - Stasis page type implementations typically do little more than - pointer arithmetic. However, implementing page types cleanly and - portably is a bit tricky. Stasis has settled upon a compromise in - this matter. Its page file formats are compatible within a single - architecture, but not across systems with varying lengths of - primitive types, or that vary in endianness. - - Over time, types that vary in length such as "int", "long", etc - will be removed from Stasis, but their usage still exists in a few - places. Once they have been removed, file compatibility problems - should be limited to endianness (though application code will still - be free to serialize objects in a non-portable manner). - - Most page implementations leverage C's pointer manipulation - semantics to lay out pages. Rather than casting pointers to - char*'s and then manually calculating byte offsets using sizeof(), - the existing page types prefer to cast pointers to appropriate - types, and then add or subtract the appropriate number of values. - - For example, instead of doing this: - - @code - // p points to an int, followed by a two bars, then the foo whose address - // we want to calculate - - int * p; - foo* f = (foo*)( ((char*)p) + sizeof(int) + 2 * sizeof(bar)) - @endcode - - the implementations would do this: - - @code - int * p; - foo * f = (foo*)( ((bar*)(p+1)) + 2 ) - @endcode - - The main disadvantage of this approach is the large number of ()'s - involved. However, it lets the compiler deal with the underlying - multiplications, and often reduces the number of casts, leading to - slightly more readable code. Take this implementation of - stasis_page_type_ptr(), for example: - - @code - int * stasis_page_type_ptr(Page *p) { - return ( (int*)stasis_page_lsn_ptr(Page *p) ) - 1; - } - @endcode - - Here, the page type is stored as an integer immediately before the - LSN pointer. Using arithmetic over char*'s would require an extra - cast to char*, and a multiplication by sizeof(int). + By defining these methods and registering appropriate callbacks, + page implementations allow callers to access their data through + standard Stasis methods such as Tread() and Tset(). This module + also includes a set of utility methods to simplify the pointer + arithmetic associated with manipulating the buffer manager's copy + of pages. @par A note on storage allocation - Finally, while Stasis will correctly call appropriate functions - when it encounters a properly registered third party page type, it - currently provides few mechanisms to allocate such pages in the - first place. There are examples of three approaches in the current - code base: + Stasis currently provides a few different mechanisms that allocate + entire pages and page ranges at once. There are examples of three + approaches in the current code base: - # Implement a full-featured, general purpose allocator, like the + - Implement a full-featured, general purpose allocator, like the one in alloc.h. This is more difficult than it sounds. - # Allocate entire regions at a time, and manually initialize pages - within them. arrayList.h attempts to do this, but gets it wrong - by relying upon lazy initialization to eventually set page types - correctly. Doing so is problematic if the page was deallocated, - then reused without being reset. + - Allocate entire regions at a time, and manually initialize pages + within them. arrayList.h does this. This is the most flexible + and efficient approach, but requires extra management code if + region allocation is not a natural approach. - # Allocate a single page at a time using TallocPage(), and - TsetPage(). This is currently the most attractive route, though - TsetPage() does not call pageLoaded() when it resets page types, - which can lead to trouble. + - Allocate a single page at a time using TallocPage(), then call + page initialization methods on each page. Currently, + TallocPage() is poorly implemented and wastes one page for every + page it allocates. + + Note that before you initialize a new page you need to call + stasis_page_cleanup() to notify the page's old format that it should + free resources associated with the old version of the page. + Stasis' allocation routines guarantee that the pages they return + were freed by committed transactions (and therefore, that their + contents can be discarded). Therefore, you do not need to log the + preimage of pages returned by the allocator. + + @todo Should we change the API so that allocation routines (TpageAlloc(), TregionAlloc()) call stasis_page_cleanup() on behalf of their callers? + + @todo Optimize page, region allocation to call page initializers automatically during forward operation and redo? @see page.h, fixed.h, and slotted.h for more information on the page API's, and the implementations of two common page formats. @@ -461,8 +453,7 @@ terms specified in this license. These methods start with "T". Look at the examples above. These are the "wrapper functions" from the OSDI paper. They are - supported by operation implementations, which can be found in the - operations/ directory. + supported by @ref OPERATIONS. @section extending Implementing you own operations @@ -472,9 +463,6 @@ terms specified in this license. @see linearHashNTA.h for a more sophisticated example that makes use of Nested Top Actions. */ -/** - * @defgroup pageFormats Page format implementations - */ /** * @defgroup OPERATIONS Logical Operations * @@ -483,6 +471,53 @@ terms specified in this license. * @todo Write a brief howto to explain the implementation of new operations. * */ +/** + * @defgroup LOGGING_DISCIPLINES Logging Disciplines + * + * Stasis' log API provides a number of methods that directly + * manipulate the log. + * + * @section SNF STEAL/NO-FORCE recovery + * Stasis includes a function, Tupdate(), that + * provides traditional STEAL/NO-FORCE logging for recovery. The + * STEAL/NO-FORCE strategy allows dirty, uncommitted pages to be + * written back to disk (STEAL), which prevents long running + * transactions from exhausting RAM. It does not force write pages to + * disk at commit (NO-FORCE), and instead only forces the log. This + * prevents the hard drive head from performing unnecessary seeks + * during commit. Recovery works by "repeating history"; all actions + * are redone up to some point in time after the last successful + * transaction committed, but before the crash. Conceptually, any + * partially commited transactions are then rolled back using + * Tabort(), as they would be during normal operation. For more + * information about STEAL/NO-FORCE recovery strategies, see the ARIES + * paper (XXX cite aries properly) + * + * + * @section SF STEAL/FORCE and bulk-logged recovery + * + * Stasis supports other logging disciplines as well. In particular, + * the buffer manager allows REGIONS (XXX document region allocator) + * to be synchronously written to disk, allowing operations to make + * use of a STEAL/FORCE recovery strategy. This is attractive when a + * transaction is writing a large, contiguous region of disk, as + * STEAL/FORCE operations do not write redo information to the log. + * If the STEAL/FORCE transaction is overwriting newly allocated + * pages, it can also avoid writing undo information to the log, as + * the newly allocated pages do not contain useful data. This allows + * large objects to be written with no tangible logging overhead, and + * has been implemented by a number of commercial systems. It is used + * by the Stasis' Rose indexes. (XXX cite LSM trees, etc.) + * + * @section LSNFREE LSN-Free pages + * + * Stasis' third (and most exotic) logging strategy makes use of + * LSN-free pages. By constraining the behavior of redo and undo log + * entries, we can entirely avoid storing Stasis metadata on pages. + * This logging discipline is under development. + * + */ + /** * @file