+++ /dev/null
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-\f
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-\f
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-\f
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-\f
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-\f
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-\f
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-\f
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-\f
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-\f
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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 library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
+++ /dev/null
-2008-04-22 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tcbdbcmpdecimal, tcbdbcmpint32, tcbdbcmpint64): bugs of overflow were fixed.
-
- - Release: 1.2.5
-
-2008-04-13 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tcbdbopenimpl): comparison function checking was added.
-
- * tcadb.c (tcadbopen): "capnum" option is now supported for B+ tree.
-
- - Release: 1.2.4
-
-2008-04-07 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcregexmatch, tcregexreplace, tcglobpat): new functions.
-
- * tcbdb.c (tcbdbcmpfunc, tcbdbcmpop): new functions.
-
- * tcbdb.c (tcbdboptimizeimpl): leaf size limitation is now implemented.
-
- * tcbdb.c (tcbdbsetcapnum): new function.
-
- - Release: 1.2.3
-
-2008-03-19 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcmapnew2): "calloc" is now used.
-
- * tcbdb.c (tcbdbputimpl): algorithm to divide large leaves was modified.
-
- - Release: 1.2.2
-
-2008-03-13 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tclistelemcmp, tclistelemcmpci): bugs about multibyte ordering were fixed.
-
- * tcutil.c (tclistsortex): new function.
-
- * tcbdb.c (tcbdbsetecode): new function.
-
- * tcadb.c (tcadbopen): "c", "t", "e", and "w" options were added.
-
- - Release: 1.2.1
-
-2008-02-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcmdb.c (tcmdbfwmkeys, tcmdbfwmkeys2): new functions.
-
- * tchdb.c (tchdbfwmkeys, tchdbfwmkeys2): new functions.
-
- * tcbdb.c (tcbdbfwmkeys, tcbdbfwmkeys2): new functions instead of "tcbdbrange3".
-
- * tcadb.c (tcadbfwmkeys, tcadbfwmkeys2): new functions.
-
- * tcbdb.c (tcbdbrangeimpl): a bug related to mutex operation was fixed.
-
- - The library version was bumped up for some binary packages.
-
- - Release: 1.2.0
-
-2008-02-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcbwtsortchrcount): time efficiency was improved.
-
- - The library version was bumped up for some binary packages.
-
- - Release: 1.1.15
-
-2008-02-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcatest.c (runwicked, procwicked): new functions.
-
- - Release: 1.1.14
-
-2008-01-30 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tctime): measure unit was changed to in seconds.
-
- * tchdb.c (tchdbcopy): shared lock is now used.
-
- * tcadb.c (tcadbsync, tcadbcopy): new functions.
-
- - Release: 1.1.13
-
-2008-01-23 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tcbdbleafkill, tcbdbnodesubidx): new functions.
-
- * tcbtest.c (runqueue, procqueue): new functions.
-
- - Release: 1.1.12
-
-2008-01-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcmapmsiz, tcmdbmsiz, tcadbsize): new functions.
-
- * tcutil.c (tcglobalmutexshared): new function.
-
- * tcutil.c (tcglobalmutexinit, tcglobalmutexdestroy): new functions.
-
- * tcutil.c (tcreadfile): a bug related to the size assignment was fixed.
-
- * tcadb.c (tcadbopen): "capsiz" parameter was added.
-
- - Release: 1.1.11
-
-2008-01-17 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tclistshift, tclistshift2): memory alignment was improved.
-
- * tcutil.c (tcvxstrprintf): a bug related to format of long long integer was fixed.
-
- - Release: 1.1.10
-
-2008-01-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcmdbvsiz, tcmdbvsiz2): new functions.
-
- * tcutil.c (tcmdbiternext): a bug related to handling sparse map was fixed.
-
- * tcadb.h, tcadb.c: new files.
-
- * tcatest.c, tcadb.c: new files.
-
- - Release: 1.1.9
-
-2008-01-03 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcstrutftoucs, tcstrucstoutf, tcstrjoin): new function.
-
- * tcutil.c (tcstrdist, tcstrdistutf): new function.
-
- - Release: 1.1.8
-
-2007-12-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * myconf.h: some header includings were removed for environments not conforming to C99.
-
- * tcutil.c (tctccalendar, tcdatestrwww, tcdatestrhttp): new functions.
-
- * tcutil.c (tcmapaddint): new function.
-
- * tcucodec.c (rundate, procdate): new functions.
-
- - Release: 1.1.7
-
-2007-12-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tcseekread, tcseekwrite): pread and pwrite were to be used.
-
- - Release: 1.1.6
-
-2007-12-21 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcmdbnew, tcmdbput, tcmdbget): concurrency was improved.
-
- * tcutil.c (tcmapcutfront, tcmdbcutfront): new functions.
-
- * tchdb.c (tchdbasyncimpl): large deferred buffer was to be flushed.
-
- * tcumttest.c: new file.
-
- - Release: 1.1.5
-
-2007-12-19 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tclrand, tcdrand, tcdrandnd): new functions.
-
- * tchdb.c (tchdbcacheadjust): count checking was removed.
-
- * tchmttest.c (myrandnd): new function.
-
- * tcbmttest.c (myrandnd): new function.
-
- - Release: 1.1.4
-
-2007-12-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcglobalmutexlock): the type of the global mutex was changed to rwlock.
-
- * tchdb.c (tchdbsetmutex, tchdbopenimpl): multiple reading file descriptors were added.
-
- * tchmttest.c (runtypical, proctypical): reading ratio assignment was added.
-
- * tcbmttest.c (runtypical, proctypical): reading ratio assignment was added.
-
- - Release: 1.1.3
-
-2007-12-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcmpoolput): mutex for operations was added.
-
- - Release: 1.1.2
-
-2007-12-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcberencode, tcberdecode): new functions.
-
- * tcbdb.c (tcbdbleafload): speed was improved.
-
- - Release: 1.1.1
-
-2007-12-07 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdbsetcache): new function.
-
- * tchmttest.c (procwrite, procread): random mode was added.
-
- * tcbmttest.c (procwrite, procread): random mode was added.
-
- - Release: 1.1.0
-
-2007-12-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchmgr.c (procget): a bug related to the open omode was fixed.
-
- * tchdb.c (tchdbreadrec): a bug related to overflow on 32-bit environment was fixed.
-
- * tchdb.c (tchdbgetbucket): the type of the return value was changed.
-
- * tcbdb.c (tcbdbcurfirst, tcbdbcurnext): cache adjustment was to be performed.
-
- * tcbdb.c (tcbdbrange, tcbdbrange2, tcbdbrange3): new functions.
-
- * tchmgr.c (proclist): "-m" option was added.
-
- * tchmgr.c (procimporttsv): new function.
-
- * tcbmgr.c (proclist): "-m", "-rb", and "-rp" options were added.
-
- * tcbmgr.c (procimporttsv): new function.
-
- - Release: 1.0.9
-
-2007-11-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchmttest.c (threadtypical): a test case was added.
-
- * tchdb.c (tchdbfbpmerge): a bug related to iterator was fixed.
-
- * tcbdb.c (tcbdbgetimpl): a bug related to concurrent cache cleaning was fixed.
-
- - Release: 1.0.8
-
-2007-11-20 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdblockmethod): a bug related to R/W lock was fixed.
-
- * tcbdb.c (tcbdblockmethod): a bug related to R/W lock was fixed.
-
- * tchdb.c, tcbdb.c: locking functions were re-imlemented as macros.
-
- * tchmttest.c, tcbmttest.c: test cases of typical operations were added.
-
- * tokyocabinet.idl: methods handling list parameters were added.
-
- - Release: 1.0.7
-
-2007-11-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tcbdboptimize): the default behaviour of bnum was changed.
-
- - Release: 1.0.6
-
-2007-11-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcutil.c (tcrealpath, tccopyfile): new functions.
-
- * tchdb.c (tchdbcopy): new function.
-
- * tcbdb.c (tcbdbcopy): new function.
-
- - Release: 1.0.5
-
-2007-11-10 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tcbdbtune): comparing functions were optimized with macros.
-
- * tcbdb.c (tcbdbsetlsmax): new function.
-
- * myconf.c, tcutil.c, tchdb.c, tcbdb.c: code cleanup and optimization.
-
- - Release: 1.0.4
-
-2007-11-08 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tcbdbleafsave, tcbdbleafload): warnings on 64-bit system were cleared.
-
- * configure.in: 64-bit offset mode for 32-bit system was added.
-
- * Makefile.in: Mac OS X is now supported.
-
- - Release: 1.0.3
-
-2007-11-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tcbdbdel): a bug that opened database was not closed was fixed.
-
- * tcbdb.c (tcbdbcurout): a bug of deleting always the first value was fixed.
-
- * tcbdb.c (tcbdbopenimpl): a potential bug of not initializing meta data was fixed.
-
- * tcutil.h, tchdb.h, tcbdb.h: wrapped in C linkage block for C++.
-
- * tokyocabinet.idl: definition of constants were added.
-
- - commands for performance test were added.
-
- - Release: 1.0.2
-
-2007-10-28 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tchdboptimize): a bug related to custom comparison function was fixed.
-
- * tcbdb.c (tcbdbleafsave): empty pages was to be removed for time space efficiency.
-
- * tcbdb.c (tcbdbputdup3): new function.
-
- * tchdb.c (tchdbvanish): new function.
-
- * tcbdb.c (tcbdbvanish): new function.
-
- * tokyocabinet.idl: new file.
-
- - Release: 1.0.1
-
-2007-10-24 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tokyocabinet.pc.in: new file.
-
- - document files were fulfilled.
-
- - Release: 1.0.0
-
-2007-10-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tcbdb.c (tchdbtranbegin): locking mode was aolished.
-
- * tcbdb.c (tcbdbsetcmpfunc): new function.
-
- - Release: 0.4.1
-
-2007-10-11 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdbopenimpl): database corruption was to be handled automatically.
-
- * tcbdb.c, tcbtest.c, tcbmttest.c, tcbmgr.c: new files.
-
- - Release: 0.4.0
-
-2007-09-09 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdbsetmutex, tchdblockobj, tchdbunlockobj): new functions.
-
- * tchmttest.c: new file.
-
- - Release: 0.3.4
-
-2007-09-05 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdbopen): TCBS compression mode is now supported.
-
- - Release: 0.3.3
-
-2007-09-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tcbsencode, tcbsdecode): new functions.
-
- - Release: 0.3.2
-
-2007-08-25 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tcpackencode, tcpackdecode): new functions.
-
- * tchdb.c (tcbwtencode, tcbwtdecode): new functions.
-
- - Release: 0.3.1
-
-2007-08-22 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdbputasync, tchdbputasync2): new functions.
-
- - Release: 0.3.0
-
-2007-08-18 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdboptimize): a bug causing data corruption was fixed.
-
- - Release: 0.2.8
-
-2007-08-15 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdboptimize): new function.
-
- - Release: 0.2.7
-
-2007-08-14 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdbsavefbp, tchdbloadfbp): a bug related to 64-bit support was fixed.
-
- * tchdb.c (tchdbreadrec, tchdbwriterec): a bug related to 64-bit support was fixed.
-
- - Release: 0.2.6
-
-2007-08-13 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- * tchdb.c (tchdbsavefbp, tchdbloadfbp): new functions.
-
- - Release: 0.2.5
-
-2007-08-12 Mikio Hirabayashi <mikio@users.sourceforge.net>
-
- - The initial version.
-
- - Release: 0.2.4
-
+++ /dev/null
-# Makefile for Tokyo Cabinet
-
-
-
-#================================================================
-# Setting Variables
-#================================================================
-
-
-# Generic settings
-SHELL = @SHELL@
-
-# Package information
-PACKAGE = @PACKAGE_NAME@
-VERSION = @PACKAGE_VERSION@
-PACKAGEDIR = $(PACKAGE)-$(VERSION)
-PACKAGETGZ = $(PACKAGE)-$(VERSION).tar.gz
-LIBVER = @MYLIBVER@
-LIBREV = @MYLIBREV@
-FORMATVER = @MYFORMATVER@
-
-# Targets
-HEADERFILES = @MYHEADERFILES@
-LIBRARYFILES = @MYLIBRARYFILES@
-LIBOBJFILES = @MYLIBOBJFILES@
-COMMANDFILES = @MYCOMMANDFILES@
-MAN1FILES = @MYMAN1FILES@
-MAN3FILES = @MYMAN3FILES@
-DOCUMENTFILES = @MYDOCUMENTFILES@
-PCFILES = @MYPCFILES@
-
-# Install destinations
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-datarootdir = @datarootdir@
-INCLUDEDIR = @includedir@
-LIBDIR = @libdir@
-BINDIR = @bindir@
-LIBEXECDIR = @libexecdir@
-DATADIR = @datadir@/$(PACKAGE)
-MAN1DIR = @mandir@/man1
-MAN3DIR = @mandir@/man3
-PCDIR = @libdir@/pkgconfig
-DESTDIR =
-
-# Building configuration
-CC = @CC@
-CPPFLAGS = @MYCPPFLAGS@ \
- -D_TC_PREFIX="\"$(prefix)\"" -D_TC_INCLUDEDIR="\"$(INCLUDEDIR)\"" \
- -D_TC_LIBDIR="\"$(LIBDIR)\"" -D_TC_BINDIR="\"$(BINDIR)\"" -D_TC_LIBEXECDIR="\"$(LIBEXECDIR)\"" \
- -D_TC_APPINC="\"-I$(INCLUDEDIR)\"" -D_TC_APPLIBS="\"-L$(LIBDIR) -ltokyocabinet @LIBS@\""
-CFLAGS = @MYCFLAGS@
-LDFLAGS = @MYLDFLAGS@
-LIBS = @LIBS@
-LDENV = LD_RUN_PATH=/lib:/usr/lib:$(LIBDIR):$(HOME)/lib:/usr/local/lib:@MYRUNPATH@:.
-RUNENV = @MYLDLIBPATHENV@=.:/lib:/usr/lib:$(LIBDIR):$(HOME)/lib:/usr/local/lib:@MYRUNPATH@
-POSTCMD = @MYPOSTCMD@
-NO_ECHO = @
-
-
-#================================================================
-# Suffix rules
-#================================================================
-
-
-.SUFFIXES :
-.SUFFIXES : .c .o
-
-.c.o :
- @echo "Compiling $<"
- $(NO_ECHO)$(CC) -c $(CPPFLAGS) $(CFLAGS) $<
-
-
-
-#================================================================
-# Actions
-#================================================================
-
-all: $(LIBRARYFILES)
-
-not-all : $(LIBRARYFILES) $(COMMANDFILES)
- @$(POSTCMD)
- @printf '\n'
- @printf '#================================================================\n'
- @printf '# Ready to install.\n'
- @printf '#================================================================\n'
-
-
-clean :
- rm -rf $(LIBRARYFILES) $(LIBOBJFILES) $(COMMANDFILES) \
- *.o a.out check.in check.out gmon.out leak.log casket casket-* casket.* *~ hoge moge
-
-
-version :
- vernum=`expr $(LIBVER)00 + $(LIBREV)` ; \
- sed -e 's/_TC_VERSION.*/_TC_VERSION "$(VERSION)"/' \
- -e "s/_TC_LIBVER.*/_TC_LIBVER $$vernum/" \
- -e 's/_TC_FORMATVER.*/_TC_FORMATVER "$(FORMATVER)"/' tcutil.h > tcutil.h~
- [ -f tcutil.h~ ] && mv -f tcutil.h~ tcutil.h
-
-untabify :
- ls *.c *.h *.idl | while read name ; \
- do \
- sed -e 's/\t/ /g' -e 's/ *$$//' $$name > $$name~; \
- [ -f $$name~ ] && mv -f $$name~ $$name ; \
- done
-
-install:
-
-install-strip:
-
-uninstall:
-
-do-notinstall :
- mkdir -p $(DESTDIR)$(INCLUDEDIR)
- cp -Rf $(HEADERFILES) $(DESTDIR)$(INCLUDEDIR)
- mkdir -p $(DESTDIR)$(LIBDIR)
- cp -Rf $(LIBRARYFILES) $(DESTDIR)$(LIBDIR)
- mkdir -p $(DESTDIR)$(BINDIR)
- cp -Rf $(COMMANDFILES) $(DESTDIR)$(BINDIR)
- mkdir -p $(DESTDIR)$(DATADIR)
- cp -Rf $(DOCUMENTFILES) $(DESTDIR)$(DATADIR)
- mkdir -p $(DESTDIR)$(MAN1DIR)
- cd man && cp -Rf $(MAN1FILES) $(DESTDIR)$(MAN1DIR)
- mkdir -p $(DESTDIR)$(MAN3DIR)
- cd man && cp -Rf $(MAN3FILES) $(DESTDIR)$(MAN3DIR)
- mkdir -p $(DESTDIR)$(PCDIR)
- cp -Rf $(PCFILES) $(DESTDIR)$(PCDIR)
- @printf '\n'
- @printf '#================================================================\n'
- @printf '# Thanks for using Tokyo Cabinet.\n'
- @printf '#================================================================\n'
-
-
-do-notinstall-strip :
- make DESTDIR=$(DESTDIR) install
- cd $(DESTDIR)$(BINDIR) && strip $(MYCOMMANDS)
-
-
-do-notuninstall :
- cd $(DESTDIR)$(INCLUDEDIR) && rm -f $(HEADERFILES)
- cd $(DESTDIR)$(LIBDIR) && rm -f $(LIBRARYFILES)
- cd $(DESTDIR)$(BINDIR) && rm -f $(COMMANDFILES)
- cd $(DESTDIR)$(MAN1DIR) && rm -f $(MAN1FILES)
- cd $(DESTDIR)$(MAN3DIR) && rm -f $(MAN3FILES)
- rm -rf $(DESTDIR)$(DATADIR)
- cd $(DESTDIR)$(PCDIR) && rm -f $(PCFILES)
-
-
-dist :
- make version
- make untabify
- make distclean
- cd .. && tar cvf - $(PACKAGEDIR) | gzip -c > $(PACKAGETGZ)
- sync ; sync
-
-
-distclean : clean
- rm -rf Makefile tokyocabinet.pc config.cache config.log config.status autom4te.cache
-
-
-check :
- rm -rf casket*
- $(RUNENV) $(RUNCMD) ./tcamgr version
- $(RUNENV) $(RUNCMD) ./tcutest xstr 50000
- $(RUNENV) $(RUNCMD) ./tcutest list 50000
- $(RUNENV) $(RUNCMD) ./tcutest map 50000
- $(RUNENV) $(RUNCMD) ./tcutest mdb 50000
- $(RUNENV) $(RUNCMD) ./tcutest misc 500
- $(RUNENV) $(RUNCMD) ./tcutest wicked 50000
- $(RUNENV) $(RUNCMD) ./tcumttest combo 5 50000 500
- $(RUNENV) $(RUNCMD) ./tcumttest combo -rnd 5 50000 500
- $(RUNENV) $(RUNCMD) ./tchmttest typical casket 5 50000 5000
- $(RUNENV) $(RUNCMD) ./tchmttest typical -rr 1000 casket 5 50000 5000
- $(RUNENV) $(RUNCMD) ./tchmttest typical -rc 50000 -nc casket 5 50000 5000
- $(RUNENV) $(RUNCMD) ./tcucodec url Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec url -d check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec base Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec base -d check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec quote Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec quote -d check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec mime Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec mime -d check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec pack -bwt Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec pack -d -bwt check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec tcbs Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec tcbs -d check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec zlib Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec zlib -d check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec xml Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec xml -d check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec ucs Makefile > check.in
- $(RUNENV) $(RUNCMD) ./tcucodec ucs -d check.in > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec date -ds '1978-02-11T18:05:30+09:00' -rf > check.out
- $(RUNENV) $(RUNCMD) ./tcucodec conf
- $(RUNENV) $(RUNCMD) ./tchtest write casket 50000 5000 5 5
- $(RUNENV) $(RUNCMD) ./tchtest read casket
- $(RUNENV) $(RUNCMD) ./tchtest remove casket
- $(RUNENV) $(RUNCMD) ./tchtest write -mt -tl -td -rc 50 casket 50000 5000 5 5
- $(RUNENV) $(RUNCMD) ./tchtest read -mt -nb -rc 50 casket
- $(RUNENV) $(RUNCMD) ./tchtest remove -mt -rc 50 casket
- $(RUNENV) $(RUNCMD) ./tchtest write -as -tb -rc 50 casket 50000 50000 5 5
- $(RUNENV) $(RUNCMD) ./tchtest read -nl -rc 50 casket
- $(RUNENV) $(RUNCMD) ./tchtest remove -rc 50 casket
- $(RUNENV) $(RUNCMD) ./tchtest rcat -pn 500 casket 50000 5000 5 5
- $(RUNENV) $(RUNCMD) ./tchtest rcat -tl -td -pn 5000 casket 50000 500 5 15
- $(RUNENV) $(RUNCMD) ./tchtest rcat -nl -pn 500 -rl casket 5000 500 5 5
- $(RUNENV) $(RUNCMD) ./tchtest rcat -tb -pn 500 casket 5000 500 5 5
- $(RUNENV) $(RUNCMD) ./tchmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tchmgr list -pv -fm 1 -px casket > check.out
- $(RUNENV) $(RUNCMD) ./tchtest misc casket 5000
- $(RUNENV) $(RUNCMD) ./tchtest misc -tl -td casket 5000
- $(RUNENV) $(RUNCMD) ./tchtest misc -mt -tb casket 500
- $(RUNENV) $(RUNCMD) ./tchtest wicked casket 50000
- $(RUNENV) $(RUNCMD) ./tchtest wicked -tl -td casket 50000
- $(RUNENV) $(RUNCMD) ./tchtest wicked -mt -tb casket 5000
- $(RUNENV) $(RUNCMD) ./tchmttest write -tl casket 5 5000 500 5
- $(RUNENV) $(RUNCMD) ./tchmttest read casket 5
- $(RUNENV) $(RUNCMD) ./tchmttest read -rnd casket 5
- $(RUNENV) $(RUNCMD) ./tchmttest remove casket 5
- $(RUNENV) $(RUNCMD) ./tchmttest wicked -nc casket 5 5000
- $(RUNENV) $(RUNCMD) ./tchmttest wicked -tl -td casket 5 5000
- $(RUNENV) $(RUNCMD) ./tchmttest wicked -tb casket 5 5000
- $(RUNENV) $(RUNCMD) ./tchmttest typical casket 5 50000 5000
- $(RUNENV) $(RUNCMD) ./tchmttest typical -rr 1000 casket 5 50000 5000
- $(RUNENV) $(RUNCMD) ./tchmttest typical -tl -rc 50000 -nc casket 5 50000 5000
- $(RUNENV) $(RUNCMD) ./tchmgr create casket 3 1 1
- $(RUNENV) $(RUNCMD) ./tchmgr inform casket
- $(RUNENV) $(RUNCMD) ./tchmgr put casket one first
- $(RUNENV) $(RUNCMD) ./tchmgr put casket two second
- $(RUNENV) $(RUNCMD) ./tchmgr put -dk casket three third
- $(RUNENV) $(RUNCMD) ./tchmgr put -dc casket three third
- $(RUNENV) $(RUNCMD) ./tchmgr put -dc casket three third
- $(RUNENV) $(RUNCMD) ./tchmgr put -dc casket three third
- $(RUNENV) $(RUNCMD) ./tchmgr put casket four fourth
- $(RUNENV) $(RUNCMD) ./tchmgr put -dk casket five fifth
- $(RUNENV) $(RUNCMD) ./tchmgr out casket one
- $(RUNENV) $(RUNCMD) ./tchmgr out casket two
- $(RUNENV) $(RUNCMD) ./tchmgr get casket three > check.out
- $(RUNENV) $(RUNCMD) ./tchmgr get casket four > check.out
- $(RUNENV) $(RUNCMD) ./tchmgr get casket five > check.out
- $(RUNENV) $(RUNCMD) ./tchmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tchmgr optimize casket
- $(RUNENV) $(RUNCMD) ./tchmgr put -dc casket three third
- $(RUNENV) $(RUNCMD) ./tchmgr get casket three > check.out
- $(RUNENV) $(RUNCMD) ./tchmgr get casket four > check.out
- $(RUNENV) $(RUNCMD) ./tchmgr get casket five > check.out
- $(RUNENV) $(RUNCMD) ./tchmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbtest write casket 50000 5 5 5000 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest read casket
- $(RUNENV) $(RUNCMD) ./tcbtest remove casket
- $(RUNENV) $(RUNCMD) ./tcbmgr list -rb 00001000 00002000 casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr list -fm 000001 casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbtest write -mt -tl -td -ls 1024 casket 50000 5000 5000 5000 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest read -mt -nb casket
- $(RUNENV) $(RUNCMD) ./tcbtest remove -mt casket
- $(RUNENV) $(RUNCMD) ./tcbtest write -tb casket 50000 5 5 50000 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest read -nl casket
- $(RUNENV) $(RUNCMD) ./tcbtest remove casket
- $(RUNENV) $(RUNCMD) ./tcbtest rcat -lc 5 -nc 5 -pn 500 casket 50000 5 5 5000 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest rcat -tl -td -pn 5000 casket 50000 5 5 500 5 15
- $(RUNENV) $(RUNCMD) ./tcbtest rcat -nl -pn 5000 -rl casket 15000 5 5 500 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest rcat -ca 1000 -tb -pn 5000 casket 15000 5 5 500 5 5
- $(RUNENV) $(RUNCMD) ./tcbmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbtest queue casket 15000 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest misc casket 5000
- $(RUNENV) $(RUNCMD) ./tcbtest misc -tl -td casket 5000
- $(RUNENV) $(RUNCMD) ./tcbtest misc -mt -tb casket 500
- $(RUNENV) $(RUNCMD) ./tcbtest wicked casket 50000
- $(RUNENV) $(RUNCMD) ./tcbtest wicked -tl -td casket 50000
- $(RUNENV) $(RUNCMD) ./tcbtest wicked -mt -tb casket 5000
- $(RUNENV) $(RUNCMD) ./tcbtest write -cd -lc 5 -nc 5 casket 5000 5 5 5 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest read -cd -lc 5 -nc 5 casket
- $(RUNENV) $(RUNCMD) ./tcbtest remove -cd -lc 5 -nc 5 casket
- $(RUNENV) $(RUNCMD) ./tcbmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbtest write -ci -td -lc 5 -nc 5 casket 5000 5 5 5 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest read -ci -lc 5 -nc 5 casket
- $(RUNENV) $(RUNCMD) ./tcbtest remove -ci -lc 5 -nc 5 casket
- $(RUNENV) $(RUNCMD) ./tcbmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbtest write -cj -tb -lc 5 -nc 5 casket 5000 5 5 5 5 5
- $(RUNENV) $(RUNCMD) ./tcbtest read -cj -lc 5 -nc 5 casket
- $(RUNENV) $(RUNCMD) ./tcbtest remove -cj -lc 5 -nc 5 casket
- $(RUNENV) $(RUNCMD) ./tcbmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbmttest write -tl casket 5 5000 5 5 500 5
- $(RUNENV) $(RUNCMD) ./tcbmttest read casket 5
- $(RUNENV) $(RUNCMD) ./tcbmttest read -rnd casket 5
- $(RUNENV) $(RUNCMD) ./tcbmttest remove casket 5
- $(RUNENV) $(RUNCMD) ./tcbmttest wicked -nc casket 5 5000
- $(RUNENV) $(RUNCMD) ./tcbmttest wicked -tl -td casket 5 5000
- $(RUNENV) $(RUNCMD) ./tchmttest wicked -tb casket 5 5000
- $(RUNENV) $(RUNCMD) ./tcbmttest typical casket 5 50000 5 5
- $(RUNENV) $(RUNCMD) ./tcbmttest typical -rr 1000 casket 5 50000 5 5
- $(RUNENV) $(RUNCMD) ./tcbmttest typical -tl -nc casket 5 50000 5 5
- $(RUNENV) $(RUNCMD) ./tcbmgr create casket 4 4 3 1 1
- $(RUNENV) $(RUNCMD) ./tcbmgr inform casket
- $(RUNENV) $(RUNCMD) ./tcbmgr put casket one first
- $(RUNENV) $(RUNCMD) ./tcbmgr put casket two second
- $(RUNENV) $(RUNCMD) ./tcbmgr put -dk casket three third
- $(RUNENV) $(RUNCMD) ./tcbmgr put -dc casket three third
- $(RUNENV) $(RUNCMD) ./tcbmgr put -dc casket three third
- $(RUNENV) $(RUNCMD) ./tcbmgr put -dd casket three third
- $(RUNENV) $(RUNCMD) ./tcbmgr put -dd casket three third
- $(RUNENV) $(RUNCMD) ./tcbmgr put casket four fourth
- $(RUNENV) $(RUNCMD) ./tcbmgr put -dk casket five fifth
- $(RUNENV) $(RUNCMD) ./tcbmgr out casket one
- $(RUNENV) $(RUNCMD) ./tcbmgr out casket two
- $(RUNENV) $(RUNCMD) ./tcbmgr get casket three > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr get casket four > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr get casket five > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr list -j three -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr optimize casket
- $(RUNENV) $(RUNCMD) ./tcbmgr put -dc casket three third
- $(RUNENV) $(RUNCMD) ./tcbmgr get casket three > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr get casket four > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr get casket five > check.out
- $(RUNENV) $(RUNCMD) ./tcbmgr list -pv casket > check.out
- $(RUNENV) $(RUNCMD) ./tcatest write 'casket.tch#mode=wct#bnum=5000' 50000
- $(RUNENV) $(RUNCMD) ./tcatest read 'casket.tch#mode=r'
- $(RUNENV) $(RUNCMD) ./tcatest remove 'casket.tch#mode=w'
- $(RUNENV) $(RUNCMD) ./tcatest misc 'casket.tch#mode=wct#bnum=500#opts=ld' 5000
- $(RUNENV) $(RUNCMD) ./tcatest wicked 'casket.tch#mode=wct' 5000
- $(RUNENV) $(RUNCMD) ./tcatest write 'casket.tcb#mode=wct#lmemb=5#nmemb=5' 50000
- $(RUNENV) $(RUNCMD) ./tcatest read 'casket.tcb#mode=r'
- $(RUNENV) $(RUNCMD) ./tcatest remove 'casket.tcb#mode=w'
- $(RUNENV) $(RUNCMD) ./tcatest misc 'casket.tcb#mode=wct#lmemb=5#nmemb=5#opts=ld' 5000
- $(RUNENV) $(RUNCMD) ./tcatest wicked 'casket.tcb#mode=wct' 5000
- $(RUNENV) $(RUNCMD) ./tcatest write '*#bnum=5000#cap=100' 50000
- $(RUNENV) $(RUNCMD) ./tcatest misc '*' 5000
- $(RUNENV) $(RUNCMD) ./tcatest wicked '*' 5000
- $(RUNENV) $(RUNCMD) ./tcamgr create 'casket.tch#mode=wct#bnum=3'
- $(RUNENV) $(RUNCMD) ./tcamgr inform 'casket.tch'
- $(RUNENV) $(RUNCMD) ./tcamgr put casket.tch one first
- $(RUNENV) $(RUNCMD) ./tcamgr put casket.tch two second
- $(RUNENV) $(RUNCMD) ./tcamgr put -dk casket.tch three third
- $(RUNENV) $(RUNCMD) ./tcamgr put -dc casket.tch three third
- $(RUNENV) $(RUNCMD) ./tcamgr put -dc casket.tch three third
- $(RUNENV) $(RUNCMD) ./tcamgr put -dc casket.tch three third
- $(RUNENV) $(RUNCMD) ./tcamgr put casket.tch four fourth
- $(RUNENV) $(RUNCMD) ./tcamgr put -dk casket.tch five fifth
- $(RUNENV) $(RUNCMD) ./tcamgr out casket.tch one
- $(RUNENV) $(RUNCMD) ./tcamgr out casket.tch two
- $(RUNENV) $(RUNCMD) ./tcamgr get casket.tch three > check.out
- $(RUNENV) $(RUNCMD) ./tcamgr get casket.tch four > check.out
- $(RUNENV) $(RUNCMD) ./tcamgr get casket.tch five > check.out
- $(RUNENV) $(RUNCMD) ./tcamgr list -pv -fm f casket.tch > check.out
- $(RUNENV) $(RUNCMD) ./tcamgr put -dc casket.tch three third
- $(RUNENV) $(RUNCMD) ./tcamgr get casket.tch three > check.out
- $(RUNENV) $(RUNCMD) ./tcamgr get casket.tch four > check.out
- $(RUNENV) $(RUNCMD) ./tcamgr get casket.tch five > check.out
- $(RUNENV) $(RUNCMD) ./tcamgr list -pv casket.tch > check.out
- rm -rf casket*
- @printf '\n'
- @printf '#================================================================\n'
- @printf '# Checking completed.\n'
- @printf '#================================================================\n'
-
-
-check-valgrind :
- make RUNCMD="valgrind --tool=memcheck --log-fd=1" check | tee leak.log
- grep ERROR leak.log
- grep 'at exit' leak.log
-
-
-check-large :
- rm -rf casket*
- $(RUNENV) $(RUNCMD) ./tchmttest typical casket 3 1000000 5000000 13 8
- $(RUNENV) $(RUNCMD) ./tchmttest typical -nc casket 3 1000000 5000000 13 8
- $(RUNENV) $(RUNCMD) ./tcbmttest typical casket 3 500000 8 8 500000 16 8
- $(RUNENV) $(RUNCMD) ./tcbmttest typical -nc casket 3 500000 8 8 500000 16 8
- rm -rf casket*
-
-
-check-thread :
- rm -rf casket*
- $(RUNENV) $(RUNCMD) ./tcumttest typical 5 500000 500000
- $(RUNENV) $(RUNCMD) ./tcumttest typical -nc -rr 1000 5 500000 500000
- $(RUNENV) $(RUNCMD) ./tchmttest typical casket 5 500000 500000
- $(RUNENV) $(RUNCMD) ./tchmttest typical -rc 500000 -nc -rr 1000 casket 5 500000 500000
- $(RUNENV) $(RUNCMD) ./tcbmttest typical casket 5 100000 5 5
- $(RUNENV) $(RUNCMD) ./tcbmttest typical -nc -rr 1000 casket 5 100000 5 5
- rm -rf casket*
-
-
-check-forever :
- while true ; \
- do \
- make check || break ; \
- make check || break ; \
- make check || break ; \
- make check || break ; \
- make check || break ; \
- make check-thread || break ; \
- done
-
-
-dicthdb :
- rm -f casket
- sed -e 's/.*$$/&\t&/' /usr/share/dict/words | \
- ./tchmgr importtsv -sc casket
-
-
-dictbdb :
- rm -f casket
- sed -e 's/.*$$/&\t&/' /usr/share/dict/words | \
- ./tcbmgr importtsv -sc casket
-
-
-.PHONY : all clean install check
-
-
-
-#================================================================
-# Building binaries
-#================================================================
-
-
-libtokyocabinet.a : $(LIBOBJFILES)
- $(AR) $(ARFLAGS) $@ $(LIBOBJFILES)
-
-
-libtokyocabinet.so.$(LIBVER).$(LIBREV).0 : $(LIBOBJFILES)
- $(CC) -shared -Wl,-soname,libtokyocabinet.so.$(LIBVER) -o $@ $(LIBOBJFILES) \
- $(LDFLAGS) $(LIBS)
-
-
-libtokyocabinet.so.$(LIBVER) : libtokyocabinet.so.$(LIBVER).$(LIBREV).0
- ln -f -s libtokyocabinet.so.$(LIBVER).$(LIBREV).0 $@
-
-
-libtokyocabinet.so : libtokyocabinet.so.$(LIBVER).$(LIBREV).0
- ln -f -s libtokyocabinet.so.$(LIBVER).$(LIBREV).0 $@
-
-
-libtokyocabinet.$(LIBVER).$(LIBREV).0.dylib : $(LIBOBJFILES)
- $(CC) -dynamiclib -o $@ \
- -install_name $(LIBDIR)/libtokyocabinet.$(LIBVER).dylib \
- -current_version $(LIBVER).$(LIBREV).0 -compatibility_version $(LIBVER) \
- $(LIBOBJFILES) $(LDFLAGS) $(LIBS)
-
-
-libtokyocabinet.$(LIBVER).dylib : libtokyocabinet.$(LIBVER).$(LIBREV).0.dylib
- ln -f -s libtokyocabinet.$(LIBVER).$(LIBREV).0.dylib $@
-
-
-libtokyocabinet.dylib : libtokyocabinet.$(LIBVER).$(LIBREV).0.dylib
- ln -f -s libtokyocabinet.$(LIBVER).$(LIBREV).0.dylib $@
-
-
-tcutest : tcutest.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tcumttest : tcumttest.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tcucodec : tcucodec.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tchtest : tchtest.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tchmttest : tchmttest.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tchmgr : tchmgr.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tcbtest : tcbtest.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tcbmttest : tcbmttest.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tcbmgr : tcbmgr.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tcatest : tcatest.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-tcamgr : tcamgr.o $(LIBRARYFILES)
- $(LDENV) $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -ltokyocabinet $(LIBS)
-
-
-myconf.o : myconf.h
-
-tcutil.o : tcutil.h myconf.h
-
-tchdb.o : tchdb.h tcutil.h myconf.h
-
-tcbdb.o : tcbdb.h tchdb.h tcutil.h myconf.h
-
-tcutest.o tcucodec.o : tcutil.h myconf.h
-
-tchtest.o tchmttest.o tchmgr.o : tcutil.h tchdb.h myconf.h
-
-tcbtest.o tcbmttest.o tcbmgr.o : tcutil.h tchdb.h tcbdb.h myconf.h
-
-tcatest.o : tcutil.h tchdb.h tcbdb.h tcadb.h myconf.h
-
-
-
-# END OF FILE
+++ /dev/null
-================================================================
- Tokyo Cabinet: a modern implementation of DBM
- Copyright (C) 2006-2008 Mikio Hirabayashi
-================================================================
-
-
-Please read the following documents with a WWW browser.
-How to install Tokyo Cabinet is explained in the specification.
-
- README - this file
- COPYING - license
- ChangeLog - history of enhancement
- THANKS - list of contributors
- doc/index.html - index of documents
-
-
-Contents of the directory tree is below.
-
- ./ - sources of Tokyo Cabinet
- ./doc/ - manuals and specifications
- ./man/ - manuals for nroff
- ./example/ - sample code of tutorial
- ./lab/ - for test and experiment
- ./bros/ - for comparison with other database managers
-
-
-Tokyo Cabinet is released under the terms of the GNU Lesser General
-Public License. See the file `COPYING' for details.
-
-Tokyo Cabinet was written by Mikio Hirabayashi. You can contact the
-author by e-mail to `mikio@users.sourceforge.net'.
-
-
-Thanks.
-
-
-
-== END OF FILE ==
+++ /dev/null
-================================================================
- Thanks to all of the following for their valuable suggestions
- or contributions.
-================================================================
-
-
-mixi Inc. and and its developers
- - allowing me to develop and publish Tokyo Cabinet as business work
-
-
-
-== END OF FILE ==
+++ /dev/null
-
-tcmdbfwmkeysを貝偏
-
-adbも実装
\ No newline at end of file
+++ /dev/null
-/*************************************************************************************************
- * The compat WIN32 API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-#ifdef HAVE_WIN32
-
-#include "tcutil.h"
-#include "myconf.h"
-#include <windef.h>
-#include <winbase.h>
-
-int msync(void *start, size_t length, int flags)
-{
- return 0;
-}
-int fsync(int fd)
-{
- return 0;
-}
-
-/*
- * Keep track of HANDLE for CreateView
- */
-
-struct mmap_priv
-{
- HANDLE h;
- HANDLE mv;
-};
-
-static TCLIST *mmap_list=NULL;
-
-static void mmap_register(HANDLE h, HANDLE mv)
-{
- struct mmap_priv *priv;
-/*
- if (!tcglobalmutexlock()) {
- return;
- }
-*/
- if (!mmap_list) {
- mmap_list = tclistnew();
- }
-
- priv = tcmalloc(sizeof(struct mmap_priv));
- priv->h = h;
- priv->mv = mv;
- tclistpush(mmap_list, priv, sizeof(priv));
-/*
- tcglobalmutexunlock();
-*/
-}
-
-static HANDLE mmap_unregister(HANDLE mv)
-{
- HANDLE h=NULL;
- struct mmap_priv *priv;
- int i, max, size;
- int nok=1;
-/*
- if (!tcglobalmutexlock()) {
- return NULL;
- }
-*/
- max = tclistnum(mmap_list);
- for(i=0; nok && i<max; i++) {
- priv = (struct mmap_priv *)tclistval(mmap_list, i, &size);
- if (priv && (priv->mv == mv)) {
- tclistremove(mmap_list, i, &size);
- h = priv->h;
- tcfree(mmap_list);
- nok=0;
- }
- }
-/*
- tcglobalmutexunlock();
-*/
- return h;
-}
-
-
-/*
- * Emulation of mmap and unmmap for tokyo dbm
- */
-void *mmap(void *start, size_t length, int prot, int flags,
- int fd, off_t offset)
-{
- DWORD fm_access = 0;
- DWORD mv_access = 0;
- HANDLE h;
- HANDLE mv;
-
- if (length == 0) {
- return MAP_FAILED;
- }
- if (!fd) {
- return MAP_FAILED;
- }
-
- if (flags & PROT_WRITE) {
- fm_access |= PAGE_READWRITE;
- } else if (flags & PROT_READ) {
- fm_access |= PAGE_READONLY;
- }
-
- if (flags & PROT_READ) {
- mv_access |= FILE_MAP_READ;
- }
- if (flags & PROT_WRITE) {
- mv_access |= FILE_MAP_WRITE;
- }
-
- h = CreateFileMapping((HANDLE)_get_osfhandle (fd),
- NULL /* security */,
- fm_access,
- 0 /* MaximumSizeHigh */,
- 0 /* MaximumSizeLow */,
- NULL /* name of the file mapping object */);
-
- if (!h || h == INVALID_HANDLE_VALUE) {
- return MAP_FAILED;
- }
-
- mv = MapViewOfFile(h, mv_access,
- 0 /* offset hi */,
- 0 /* offset lo */,
- length);
- if (!mv || mv == INVALID_HANDLE_VALUE) {
- CloseHandle(h);
- return MAP_FAILED;
- }
-
- mmap_register(h, mv);
- return (void *) mv;
-}
-
-int munmap(void *start, size_t length)
-{
- HANDLE h;
- if (!start) {
- return -1;
- }
- h = mmap_unregister(start);
- UnmapViewOfFile(start);
- CloseHandle(h);
- return 0;
-}
-
-int regcomp(regex_t *preg, const char *regex, int cflags)
-{
- return 0;
-}
-
-int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
-{
- return 0;
-}
-
-size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
-{
- *errbuf = 0;
- return 0;
-}
-/*
-int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- return -1;
-}
-*/
-void regfree(regex_t *preg)
-{
-}
-
-int glob(const char *pattern, int flags,
- int (*errfunc) (const char *epath, int eerrno),
- glob_t *pglob)
-{
- return GLOB_NOMATCH;
-}
-void globfree(glob_t *pglob)
-{
-}
-
-char *realpath(const char *path, char *resolved_path)
-{
- strcpy(resolved_path, path);
- return resolved_path;
-}
-
-/*
-int rand_r(unsigned int *seedp)
-{
- *seedp = *seedp * 1103515245 + 12345;
- return((unsigned)(*seedp/65536) % 32768);
-}
-*/
-
-/* read from a file descriptor at a given offset */
-ssize_t pread(int fd, void *buf, size_t count, off_t offset)
-{
- __int64 cur_pos;
- ssize_t num_read;
-
- if ((cur_pos = _lseeki64(fd, 0, SEEK_CUR)) == (off_t)-1)
- return -1;
-
- if (_lseeki64(fd, offset, SEEK_SET) == (off_t)-1)
- return -1;
-
- num_read = read(fd, buf, count);
-
- if (_lseeki64(fd, cur_pos, SEEK_SET) == (off_t)-1)
- return -1;
-
- return num_read;
-}
-
-/* write to a file descriptor at a given offset */
-ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
-{
- __int64 cur_pos;
- ssize_t num_write;
-
- if ((cur_pos = _lseeki64(fd, 0, SEEK_CUR)) == (off_t)-1)
- return -1;
-
- if (_lseeki64(fd, offset, SEEK_SET) == (off_t)-1)
- return -1;
-
- num_write = write(fd, buf, count);
-
- if (_lseeki64(fd, cur_pos, SEEK_SET) == (off_t)-1)
- return -1;
-
- return num_write;
-}
-
-#endif
+++ /dev/null
-/*************************************************************************************************
- * The win32 compat API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- *
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-#ifndef COMPAT_H
-#define COMPAT_H
-
-#ifdef HAVE_WIN32
-#include <sys/types.h>
-
-typedef int regoff_t;
-
-typedef struct {
- regoff_t rm_so;
- regoff_t rm_eo;
-} regmatch_t;
-
-typedef struct {
-
-} regex_t;
-
-#define REG_EXTENDED 0
-#define REG_NOSUB 0
-#define REG_ICASE 0
-#define REG_NOTBOL 0
-int regcomp(regex_t *preg, const char *regex, int cflags);
-int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
-size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
-void regfree(regex_t *preg);
-
-
-/* mmap implementation for tokyodbm */
-#define PROT_WRITE 0x2 /* Page can be written. */
-#define PROT_READ 0x1 /* page can be read */
-#define MAP_SHARED 0x01 /* Share changes. */
-#define MAP_FAILED ((void *) -1)
-#define MS_SYNC 0
-
-void *mmap(void *start, size_t length, int prot, int flags,
- int fd, off_t offset);
-int munmap(void *start, size_t length);
-int msync(void *start, size_t length, int flags);
-int fsync(int fd);
-ssize_t pread(int fd, void *buf, size_t count, off_t offset);
-ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
-int rand_r(int *seedp);
-
-/*
-struct timezone {
- int tz_minuteswest;
- int tz_dsttime;
-};
-
-int gettimeofday(struct timeval *tv, struct timezone *tz);
-*/
-
-typedef struct {
- size_t gl_pathc; /* Count of paths matched so far */
- char **gl_pathv; /* List of matched pathnames. */
- size_t gl_offs; /* Slots to reserve in ‘gl_pathv’. */
-} glob_t;
-
-int glob(const char *pattern, int flags,
- int (*errfunc) (const char *epath, int eerrno),
- glob_t *pglob);
-
-void globfree(glob_t *pglob);
-
-#define GLOB_ERR 0
-#define GLOB_NOSORT 0
-#define GLOB_NOMATCH 0
-
-char *realpath(const char *path, char *resolved_path);
-
-#define lstat stat
-
-#endif /* HAVE_WIN32 */
-#endif /* !COMPAT_H */
+++ /dev/null
-#! /bin/sh
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for tokyocabinet 1.2.5.
-#
-# Copyright (C) 2003 Free Software Foundation, Inc.
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
- set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- $as_unset $as_var
- fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)$' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
- /^X\/\(\/\/\)$/{ s//\1/; q; }
- /^X\/\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" || {
- # Find who we are. Look in the path if we contain no path at all
- # relative or not.
- case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
- ;;
- esac
- # We did not find ourselves, most probably we were run as `sh COMMAND'
- # in which case we are not to be found in the path.
- if test "x$as_myself" = x; then
- as_myself=$0
- fi
- if test ! -f "$as_myself"; then
- { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
- { (exit 1); exit 1; }; }
- fi
- case $CONFIG_SHELL in
- '')
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for as_base in sh bash ksh sh5; do
- case $as_dir in
- /*)
- if ("$as_dir/$as_base" -c '
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
- $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
- $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
- CONFIG_SHELL=$as_dir/$as_base
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$0" ${1+"$@"}
- fi;;
- esac
- done
-done
-;;
- esac
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line before each line; the second 'sed' does the real
- # work. The second script uses 'N' to pair each line-number line
- # with the numbered line, and appends trailing '-' during
- # substitution so that $LINENO is not a special case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
- sed '=' <$as_myself |
- sed '
- N
- s,$,-,
- : loop
- s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
- t loop
- s,-$,,
- s,^['$as_cr_digits']*\n,,
- ' >$as_me.lineno &&
- chmod +x $as_me.lineno ||
- { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensible to this).
- . ./$as_me.lineno
- # Exit status is that of the last command.
- exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
- *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T=' ' ;;
- *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
- *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- # We could just check for DJGPP; but this test a) works b) is more generic
- # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
- if test -f conf$$.exe; then
- # Don't use ln at all; we don't have any links
- as_ln_s='cp -p'
- else
- as_ln_s='ln -s'
- fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS=" $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-
-# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-exec 6>&1
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_config_libobj_dir=.
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Maximum number of lines to put in a shell here document.
-# This variable seems obsolete. It should probably be removed, and
-# only ac_max_sed_lines should be used.
-: ${ac_max_here_lines=38}
-
-# Identity of this package.
-PACKAGE_NAME='tokyocabinet'
-PACKAGE_TARNAME='tokyocabinet'
-PACKAGE_VERSION='1.2.5'
-PACKAGE_STRING='tokyocabinet 1.2.5'
-PACKAGE_BUGREPORT=''
-
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT MYLIBVER MYLIBREV MYFORMATVER MYHEADERFILES MYLIBRARYFILES MYLIBOBJFILES MYCOMMANDFILES MYMAN1FILES MYMAN3FILES MYDOCUMENTFILES MYPCFILES MYCFLAGS MYCPPFLAGS MYLDFLAGS MYRUNPATH MYLDLIBPATHENV MYPOSTCMD LIBOBJS LTLIBOBJS'
-ac_subst_files=''
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-ac_prev=
-for ac_option
-do
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
- ac_prev=
- continue
- fi
-
- ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case $ac_option in
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir=$ac_optarg ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build_alias ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build_alias=$ac_optarg ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file=$ac_optarg ;;
-
- --config-cache | -C)
- cache_file=config.cache ;;
-
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
- datadir=$ac_optarg ;;
-
- -disable-* | --disable-*)
- ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid feature name: $ac_feature" >&2
- { (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
- eval "enable_$ac_feature=no" ;;
-
- -enable-* | --enable-*)
- ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid feature name: $ac_feature" >&2
- { (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
- case $ac_option in
- *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
- *) ac_optarg=yes ;;
- esac
- eval "enable_$ac_feature='$ac_optarg'" ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix=$ac_optarg ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he | -h)
- ac_init_help=long ;;
- -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
- ac_init_help=recursive ;;
- -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
- ac_init_help=short ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host_alias ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host_alias=$ac_optarg ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir=$ac_optarg ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir=$ac_optarg ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir=$ac_optarg ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir=$ac_optarg ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir=$ac_optarg ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir=$ac_optarg ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c | -n)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir=$ac_optarg ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix=$ac_optarg ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix=$ac_optarg ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix=$ac_optarg ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name=$ac_optarg ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir=$ac_optarg ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir=$ac_optarg ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site=$ac_optarg ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir=$ac_optarg ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir=$ac_optarg ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target_alias ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target_alias=$ac_optarg ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers | -V)
- ac_init_version=: ;;
-
- -with-* | --with-*)
- ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid package name: $ac_package" >&2
- { (exit 1); exit 1; }; }
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- case $ac_option in
- *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
- *) ac_optarg=yes ;;
- esac
- eval "with_$ac_package='$ac_optarg'" ;;
-
- -without-* | --without-*)
- ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
- # Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid package name: $ac_package" >&2
- { (exit 1); exit 1; }; }
- ac_package=`echo $ac_package | sed 's/-/_/g'`
- eval "with_$ac_package=no" ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes=$ac_optarg ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries=$ac_optarg ;;
-
- -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; }
- ;;
-
- *=*)
- ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
- # Reject names that are not valid shell variable names.
- expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
- { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
- { (exit 1); exit 1; }; }
- ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
- eval "$ac_envvar='$ac_optarg'"
- export $ac_envvar ;;
-
- *)
- # FIXME: should be removed in autoconf 3.0.
- echo "$as_me: WARNING: you should use --build, --host, --target" >&2
- expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- echo "$as_me: WARNING: invalid host type: $ac_option" >&2
- : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- ac_option=--`echo $ac_prev | sed 's/_/-/g'`
- { echo "$as_me: error: missing argument to $ac_option" >&2
- { (exit 1); exit 1; }; }
-fi
-
-# Be sure to have absolute paths.
-for ac_var in exec_prefix prefix
-do
- eval ac_val=$`echo $ac_var`
- case $ac_val in
- [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
- *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
- { (exit 1); exit 1; }; };;
- esac
-done
-
-# Be sure to have absolute paths.
-for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
- localstatedir libdir includedir oldincludedir infodir mandir
-do
- eval ac_val=$`echo $ac_var`
- case $ac_val in
- [\\/$]* | ?:[\\/]* ) ;;
- *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
- { (exit 1); exit 1; }; };;
- esac
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
- if test "x$build_alias" = x; then
- cross_compiling=maybe
- echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used." >&2
- elif test "x$build_alias" != "x$host_alias"; then
- cross_compiling=yes
- fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then its parent.
- ac_confdir=`(dirname "$0") 2>/dev/null ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$0" : 'X\(//\)[^/]' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$0" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
- if test "$ac_srcdir_defaulted" = yes; then
- { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
- { (exit 1); exit 1; }; }
- else
- { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
- { (exit 1); exit 1; }; }
- fi
-fi
-(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
- { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
- { (exit 1); exit 1; }; }
-srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
-ac_env_build_alias_set=${build_alias+set}
-ac_env_build_alias_value=$build_alias
-ac_cv_env_build_alias_set=${build_alias+set}
-ac_cv_env_build_alias_value=$build_alias
-ac_env_host_alias_set=${host_alias+set}
-ac_env_host_alias_value=$host_alias
-ac_cv_env_host_alias_set=${host_alias+set}
-ac_cv_env_host_alias_value=$host_alias
-ac_env_target_alias_set=${target_alias+set}
-ac_env_target_alias_value=$target_alias
-ac_cv_env_target_alias_set=${target_alias+set}
-ac_cv_env_target_alias_value=$target_alias
-ac_env_CC_set=${CC+set}
-ac_env_CC_value=$CC
-ac_cv_env_CC_set=${CC+set}
-ac_cv_env_CC_value=$CC
-ac_env_CFLAGS_set=${CFLAGS+set}
-ac_env_CFLAGS_value=$CFLAGS
-ac_cv_env_CFLAGS_set=${CFLAGS+set}
-ac_cv_env_CFLAGS_value=$CFLAGS
-ac_env_LDFLAGS_set=${LDFLAGS+set}
-ac_env_LDFLAGS_value=$LDFLAGS
-ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
-ac_cv_env_LDFLAGS_value=$LDFLAGS
-ac_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_env_CPPFLAGS_value=$CPPFLAGS
-ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_cv_env_CPPFLAGS_value=$CPPFLAGS
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat <<_ACEOF
-\`configure' configures tokyocabinet 1.2.5 to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE. See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
- -h, --help display this help and exit
- --help=short display options specific to this package
- --help=recursive display the short help of all the included packages
- -V, --version display version information and exit
- -q, --quiet, --silent do not print \`checking...' messages
- --cache-file=FILE cache test results in FILE [disabled]
- -C, --config-cache alias for \`--cache-file=config.cache'
- -n, --no-create do not create output files
- --srcdir=DIR find the sources in DIR [configure dir or \`..']
-
-_ACEOF
-
- cat <<_ACEOF
-Installation directories:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
- --bindir=DIR user executables [EPREFIX/bin]
- --sbindir=DIR system admin executables [EPREFIX/sbin]
- --libexecdir=DIR program executables [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --libdir=DIR object code libraries [EPREFIX/lib]
- --includedir=DIR C header files [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc [/usr/include]
- --infodir=DIR info documentation [PREFIX/info]
- --mandir=DIR man documentation [PREFIX/man]
-_ACEOF
-
- cat <<\_ACEOF
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
- case $ac_init_help in
- short | recursive ) echo "Configuration of tokyocabinet 1.2.5:";;
- esac
- cat <<\_ACEOF
-
-Optional Features:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --enable-debug build for debugging
- --enable-devel build for development
- --enable-profile build for profiling
- --enable-off64 build with 64-bit file offset on 32-bit system
- --enable-fastest build for fastest run
- --enable-swab build for swapping byte-orders
- --enable-uyield build for detecting race conditions
- --disable-zlib build without ZLIB compression
- --disable-pthread build without POSIX thread support
- --disable-shared avoid to build shared libraries
-
-Some influential environment variables:
- CC C compiler command
- CFLAGS C compiler flags
- LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
- nonstandard directory <lib dir>
- CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
- headers in a nonstandard directory <include dir>
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-_ACEOF
-fi
-
-if test "$ac_init_help" = "recursive"; then
- # If there are subdirs, report their specific --help.
- ac_popdir=`pwd`
- for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
- test -d $ac_dir || continue
- ac_builddir=.
-
-if test "$ac_dir" != .; then
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A "../" for each directory in $ac_dir_suffix.
- ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
- ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
- .) # No --srcdir option. We are building in place.
- ac_srcdir=.
- if test -z "$ac_top_builddir"; then
- ac_top_srcdir=.
- else
- ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
- fi ;;
- [\\/]* | ?:[\\/]* ) # Absolute path.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir ;;
- *) # Relative path.
- ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
- case "$ac_dir" in
- .) ac_abs_builddir=`pwd`;;
- [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
- *) ac_abs_builddir=`pwd`/"$ac_dir";;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
- case ${ac_top_builddir}. in
- .) ac_abs_top_builddir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
- *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
- case $ac_srcdir in
- .) ac_abs_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
- *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
- case $ac_top_srcdir in
- .) ac_abs_top_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
- *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
- esac;;
-esac
-
- cd $ac_dir
- # Check for guested configure; otherwise get Cygnus style configure.
- if test -f $ac_srcdir/configure.gnu; then
- echo
- $SHELL $ac_srcdir/configure.gnu --help=recursive
- elif test -f $ac_srcdir/configure; then
- echo
- $SHELL $ac_srcdir/configure --help=recursive
- elif test -f $ac_srcdir/configure.ac ||
- test -f $ac_srcdir/configure.in; then
- echo
- $ac_configure --help
- else
- echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
- fi
- cd $ac_popdir
- done
-fi
-
-test -n "$ac_init_help" && exit 0
-if $ac_init_version; then
- cat <<\_ACEOF
-tokyocabinet configure 1.2.5
-generated by GNU Autoconf 2.59
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
- exit 0
-fi
-exec 5>config.log
-cat >&5 <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by tokyocabinet $as_me 1.2.5, which was
-generated by GNU Autoconf 2.59. Invocation command line was
-
- $ $0 $@
-
-_ACEOF
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
-
-/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
-/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
-/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- echo "PATH: $as_dir"
-done
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_sep=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
- for ac_arg
- do
- case $ac_arg in
- -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- continue ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
- ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
- esac
- case $ac_pass in
- 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
- 2)
- ac_configure_args1="$ac_configure_args1 '$ac_arg'"
- if test $ac_must_keep_next = true; then
- ac_must_keep_next=false # Got value, back to normal.
- else
- case $ac_arg in
- *=* | --config-cache | -C | -disable-* | --disable-* \
- | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
- | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
- | -with-* | --with-* | -without-* | --without-* | --x)
- case "$ac_configure_args0 " in
- "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
- esac
- ;;
- -* ) ac_must_keep_next=true ;;
- esac
- fi
- ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
- # Get rid of the leading space.
- ac_sep=" "
- ;;
- esac
- done
-done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log. We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Be sure not to use single quotes in there, as some shells,
-# such as our DU 5.0 friend, will then `close' the trap.
-trap 'exit_status=$?
- # Save into config.log some information that might help in debugging.
- {
- echo
-
- cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
- echo
- # The following way of writing the cache mishandles newlines in values,
-{
- (set) 2>&1 |
- case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- sed -n \
- "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
- ;;
- *)
- sed -n \
- "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
- ;;
- esac;
-}
- echo
-
- cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
- echo
- for ac_var in $ac_subst_vars
- do
- eval ac_val=$`echo $ac_var`
- echo "$ac_var='"'"'$ac_val'"'"'"
- done | sort
- echo
-
- if test -n "$ac_subst_files"; then
- cat <<\_ASBOX
-## ------------- ##
-## Output files. ##
-## ------------- ##
-_ASBOX
- echo
- for ac_var in $ac_subst_files
- do
- eval ac_val=$`echo $ac_var`
- echo "$ac_var='"'"'$ac_val'"'"'"
- done | sort
- echo
- fi
-
- if test -s confdefs.h; then
- cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
- echo
- sed "/^$/d" confdefs.h | sort
- echo
- fi
- test "$ac_signal" != 0 &&
- echo "$as_me: caught signal $ac_signal"
- echo "$as_me: exit $exit_status"
- } >&5
- rm -f core *.core &&
- rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
- exit $exit_status
- ' 0
-for ac_signal in 1 2 13 15; do
- trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo >confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
-fi
-for ac_site_file in $CONFIG_SITE; do
- if test -r "$ac_site_file"; then
- { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
- sed 's/^/| /' "$ac_site_file" >&5
- . "$ac_site_file"
- fi
-done
-
-if test -r "$cache_file"; then
- # Some versions of bash will fail to source /dev/null (special
- # files actually), so we avoid doing that.
- if test -f "$cache_file"; then
- { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
- case $cache_file in
- [\\/]* | ?:[\\/]* ) . $cache_file;;
- *) . ./$cache_file;;
- esac
- fi
-else
- { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
- >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in `(set) 2>&1 |
- sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
- eval ac_old_set=\$ac_cv_env_${ac_var}_set
- eval ac_new_set=\$ac_env_${ac_var}_set
- eval ac_old_val="\$ac_cv_env_${ac_var}_value"
- eval ac_new_val="\$ac_env_${ac_var}_value"
- case $ac_old_set,$ac_new_set in
- set,)
- { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,set)
- { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,);;
- *)
- if test "x$ac_old_val" != "x$ac_new_val"; then
- { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
- { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
-echo "$as_me: former value: $ac_old_val" >&2;}
- { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
-echo "$as_me: current value: $ac_new_val" >&2;}
- ac_cache_corrupted=:
- fi;;
- esac
- # Pass precious variables to config.status.
- if test "$ac_new_set" = set; then
- case $ac_new_val in
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
- ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
- *) ac_arg=$ac_var=$ac_new_val ;;
- esac
- case " $ac_configure_args " in
- *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
- *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- esac
- fi
-done
-if $ac_cache_corrupted; then
- { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Package information
-MYLIBVER=3
-MYLIBREV=6
-MYFORMATVER="1.0"
-
-# Targets
-MYHEADERFILES="tcutil.h tchdb.h tcbdb.h tcadb.h"
-MYLIBRARYFILES="libtokyocabinet.a"
-MYLIBOBJFILES="tcutil.o tchdb.o tcbdb.o tcadb.o myconf.o"
-MYCOMMANDFILES="tcutest tcumttest tcucodec tchtest tchmttest tchmgr"
-MYCOMMANDFILES="$MYCOMMANDFILES tcbtest tcbmttest tcbmgr tcatest tcamgr"
-MYMAN1FILES="tcutest.1 tcumttest.1 tcucodec.1 tchtest.1 tchmttest.1 tchmgr.1"
-MYMAN1FILES="$MYMAN1FILES tcbtest.1 tcbmttest.1 tcbmgr.1 tcatest.1 tcamgr.1"
-MYMAN3FILES="tokyocabinet.3 tcutil.3 tcxstr.3 tclist.3 tcmap.3 tcmdb.3 tcmpool.3"
-MYMAN3FILES="$MYMAN3FILES tchdb.3 tcbdb.3 tcadb.3"
-MYDOCUMENTFILES="COPYING ChangeLog THANKS doc"
-MYPCFILES="tokyocabinet.pc"
-
-# Building flags
-MYCFLAGS="-std=c99 -Wall -fPIC -fsigned-char -O2"
-MYCPPFLAGS="-I. -I\$(INCLUDEDIR) -L$HOME/include -L/usr/local/include -DNDEBUG -D_GNU_SOURCE=1"
-MYLDFLAGS="-L. -L\$(LIBDIR) -L$HOME/lib -L/usr/local/lib"
-MYRUNPATH="\$(LIBDIR)"
-MYLDLIBPATHENV="LD_LIBRARY_PATH"
-MYPOSTCMD="true"
-
-# Building paths
-pathtmp="$PATH"
-PATH="$HOME/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin"
-PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp"
-LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH"
-LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH"
-CPATH="$HOME/include:/usr/local/include:$CPATH"
-PKG_CONFIG_PATH="$HOME/lib/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH"
-export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH PKG_CONFIG_PATH
-
-
-
-#================================================================
-# Options
-#================================================================
-
-
-# Internal variables
-enables=""
-
-# Debug mode
-# Check whether --enable-debug or --disable-debug was given.
-if test "${enable_debug+set}" = set; then
- enableval="$enable_debug"
-
-fi;
-if test "$enable_debug" = "yes"
-then
- MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g"
- MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG"
- MYLDFLAGS="$MYLDFLAGS -static"
- enables="$enables (debug)"
-fi
-
-# Developping mode
-# Check whether --enable-devel or --disable-devel was given.
-if test "${enable_devel+set}" = set; then
- enableval="$enable_devel"
-
-fi;
-if test "$enable_devel" = "yes"
-then
- MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -O2 -pipe"
- MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG"
- enables="$enables (devel)"
-fi
-
-# Profiling mode
-# Check whether --enable-profile or --disable-profile was given.
-if test "${enable_profile+set}" = set; then
- enableval="$enable_profile"
-
-fi;
-if test "$enable_profile" = "yes"
-then
- MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -pg -O2 -pipe"
- enables="$enables (profile)"
-fi
-
-# 64-bit offset mode
-# Check whether --enable-off64 or --disable-off64 was given.
-if test "${enable_off64+set}" = set; then
- enableval="$enable_off64"
-
-fi;
-if test "$enable_off64" = "yes"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_FILE_OFFSET_BITS=64"
- enables="$enables (off64)"
-fi
-
-# Fastest mode
-# Check whether --enable-fastest or --disable-fastest was given.
-if test "${enable_fastest+set}" = set; then
- enableval="$enable_fastest"
-
-fi;
-if test "$enable_fastest" = "yes"
-then
- MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -O3"
- MYCFLAGS="$MYCFLAGS -fomit-frame-pointer -fforce-addr -minline-all-stringops"
- MYCPPFLAGS="$MYCPPFLAGS -D_MYFASTEST"
- enables="$enables (fastest)"
-fi
-
-# Swapping byte-orders mode
-# Check whether --enable-swab or --disable-swab was given.
-if test "${enable_swab+set}" = set; then
- enableval="$enable_swab"
-
-fi;
-if test "$enable_swab" = "yes"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_MYSWAB"
- enables="$enables (swab)"
-fi
-
-# Micro yield mode
-# Check whether --enable-uyield or --disable-uyield was given.
-if test "${enable_uyield+set}" = set; then
- enableval="$enable_uyield"
-
-fi;
-if test "$enable_uyield" = "yes"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_MYMICROYIELD"
- enables="$enables (uyield)"
-fi
-
-# Disable ZLIB compression
-# Check whether --enable-zlib or --disable-zlib was given.
-if test "${enable_zlib+set}" = set; then
- enableval="$enable_zlib"
-
-fi;
-if test "$enable_zlib" = "no"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_MYNOZLIB"
- enables="$enables (no-zlib)"
-fi
-
-# Disable POSIX thread
-# Check whether --enable-pthread or --disable-pthread was given.
-if test "${enable_pthread+set}" = set; then
- enableval="$enable_pthread"
-
-fi;
-if test "$enable_pthread" = "no"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_MYNOPTHREAD"
- enables="$enables (no-pthread)"
-fi
-
-# Disable shared object
-# Check whether --enable-shared or --disable-shared was given.
-if test "${enable_shared+set}" = set; then
- enableval="$enable_shared"
-
-fi;
-if test "$enable_shared" = "no"
-then
- enables="$enables (no-shared)"
-fi
-
-# Messages
-printf '#================================================================\n'
-printf '# Configuring Tokyo Cabinet version %s%s.\n' "$PACKAGE_VERSION" "$enables"
-printf '#================================================================\n'
-
-
-
-#================================================================
-# Checking Commands and Libraries
-#================================================================
-
-# C compiler
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="gcc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- CC=$ac_ct_CC
-else
- CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- CC=$ac_ct_CC
-else
- CC="$ac_cv_prog_CC"
-fi
-
-fi
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# != 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
- fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- for ac_prog in cl
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$CC" && break
- done
-fi
-if test -z "$CC"; then
- ac_ct_CC=$CC
- for ac_prog in cl
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="$ac_prog"
- echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
- echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
- test -n "$ac_ct_CC" && break
-done
-
- CC=$ac_ct_CC
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
- "checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
- (eval $ac_compiler --version </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
- (eval $ac_compiler -v </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
- (eval $ac_compiler -V </dev/null >&5) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
- (eval $ac_link_default) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # Find the output, starting from the most likely. This scheme is
-# not robust to junk in `.', hence go to wildcards (a.*) only as a last
-# resort.
-
-# Be careful to initialize this variable, since it used to be cached.
-# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
-ac_cv_exeext=
-# b.out is created by i960 compilers.
-for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
-do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
- ;;
- conftest.$ac_ext )
- # This is the source file.
- ;;
- [ab].out )
- # We found the default executable, but exeext='' is most
- # certainly right.
- break;;
- *.* )
- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- # FIXME: I believe we export ac_cv_exeext for Libtool,
- # but it would be cool to find out if it's true. Does anybody
- # maintain Libtool? --akim.
- export ac_cv_exeext
- break;;
- * )
- break;;
- esac
-done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
- { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6
-
-# Check the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
- if { ac_try='./$ac_file'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- cross_compiling=no
- else
- if test "$cross_compiling" = maybe; then
- cross_compiling=yes
- else
- { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
- fi
- fi
-fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-# Check the compiler produces executables we can run. If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6
-
-echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
- test -f "$ac_file" || continue
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
- export ac_cv_exeext
- break;;
- * ) break;;
- esac
-done
-else
- { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
-if test "${ac_cv_objext+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
- case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
- *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
- break;;
- esac
-done
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_compiler_gnu=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-CFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_g+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_g=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cc_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_prog_cc_stdc=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std1 is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std1. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
-_ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX -qlanglvl=ansi
-# Ultrix and OSF/1 -std1
-# HP-UX 10.20 and later -Ae
-# HP-UX older versions -Aa -D_HPUX_SOURCE
-# SVR4 -Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
- CC="$ac_save_CC $ac_arg"
- rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_stdc=$ac_arg
-break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext
-done
-rm -f conftest.$ac_ext conftest.$ac_objext
-CC=$ac_save_CC
-
-fi
-
-case "x$ac_cv_prog_cc_stdc" in
- x|xno)
- echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
- *)
- echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
- CC="$CC $ac_cv_prog_cc_stdc" ;;
-esac
-
-# Some people use a C++ compiler to compile C. Since we use `exit',
-# in C++ we need to declare it. In case someone uses the same compiler
-# for both compiling C and C++ we need to have the C++ compiler decide
-# the declaration of exit, since it's the most demanding environment.
-cat >conftest.$ac_ext <<_ACEOF
-#ifndef __cplusplus
- choke me
-#endif
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- for ac_declaration in \
- '' \
- 'extern "C" void std::exit (int) throw (); using std::exit;' \
- 'extern "C" void std::exit (int); using std::exit;' \
- 'extern "C" void exit (int) throw ();' \
- 'extern "C" void exit (int);' \
- 'void exit (int);'
-do
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- :
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-$ac_declaration
-int
-main ()
-{
-exit (42);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- break
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
- echo '#ifdef __cplusplus' >>confdefs.h
- echo $ac_declaration >>confdefs.h
- echo '#endif' >>confdefs.h
-fi
-
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-# Byte order
-
-echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
-echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
-if test "${ac_cv_c_bigendian+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- # See if sys/param.h defines the BYTE_ORDER macro.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/param.h>
-
-int
-main ()
-{
-#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
- bogus endian macros
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- # It does; now see whether it defined to BIG_ENDIAN or not.
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/param.h>
-
-int
-main ()
-{
-#if BYTE_ORDER != BIG_ENDIAN
- not big endian
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_c_bigendian=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_c_bigendian=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-# It does not; compile a test program.
-if test "$cross_compiling" = yes; then
- # try to guess the endianness by grepping values into an object file
- ac_cv_c_bigendian=unknown
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
-short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
-void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
-short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
-short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
-void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
-int
-main ()
-{
- _ascii (); _ebcdic ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
- ac_cv_c_bigendian=yes
-fi
-if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
- if test "$ac_cv_c_bigendian" = unknown; then
- ac_cv_c_bigendian=no
- else
- # finding both strings is unlikely to happen, but who knows?
- ac_cv_c_bigendian=unknown
- fi
-fi
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-int
-main ()
-{
- /* Are we little or big endian? From Harbison&Steele. */
- union
- {
- long l;
- char c[sizeof (long)];
- } u;
- u.l = 1;
- exit (u.c[sizeof (long) - 1] == 1);
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_c_bigendian=no
-else
- echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_c_bigendian=yes
-fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
-echo "${ECHO_T}$ac_cv_c_bigendian" >&6
-case $ac_cv_c_bigendian in
- yes)
- MYCPPFLAGS="$MYCPPFLAGS -D_MYBIGEND" ;;
- no)
- ;;
- *)
- { { echo "$as_me:$LINENO: error: unknown endianness
-presetting ac_cv_c_bigendian=no (or yes) will help" >&5
-echo "$as_me: error: unknown endianness
-presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
- { (exit 1); exit 1; }; } ;;
-esac
-
-
-# Underlying libraries
-
-echo "$as_me:$LINENO: checking for main in -lc" >&5
-echo $ECHO_N "checking for main in -lc... $ECHO_C" >&6
-if test "${ac_cv_lib_c_main+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-main ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_c_main=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_c_main=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_c_main" >&5
-echo "${ECHO_T}$ac_cv_lib_c_main" >&6
-if test $ac_cv_lib_c_main = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBC 1
-_ACEOF
-
- LIBS="-lc $LIBS"
-
-fi
-
-
-echo "$as_me:$LINENO: checking for main in -lm" >&5
-echo $ECHO_N "checking for main in -lm... $ECHO_C" >&6
-if test "${ac_cv_lib_m_main+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lm $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-main ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_m_main=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_m_main=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_m_main" >&5
-echo "${ECHO_T}$ac_cv_lib_m_main" >&6
-if test $ac_cv_lib_m_main = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBM 1
-_ACEOF
-
- LIBS="-lm $LIBS"
-
-fi
-
-if test "$enable_pthread" != "no"
-then
-
-echo "$as_me:$LINENO: checking for main in -lpthread" >&5
-echo $ECHO_N "checking for main in -lpthread... $ECHO_C" >&6
-if test "${ac_cv_lib_pthread_main+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpthread $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-main ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_pthread_main=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_pthread_main=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_main" >&5
-echo "${ECHO_T}$ac_cv_lib_pthread_main" >&6
-if test $ac_cv_lib_pthread_main = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBPTHREAD 1
-_ACEOF
-
- LIBS="-lpthread $LIBS"
-
-fi
-
-fi
-if test "$enable_zlib" != "no"
-then
-
-echo "$as_me:$LINENO: checking for main in -lz" >&5
-echo $ECHO_N "checking for main in -lz... $ECHO_C" >&6
-if test "${ac_cv_lib_z_main+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lz $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-main ();
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
- (eval $ac_link) 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag"
- || test ! -s conftest.err'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_lib_z_main=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_z_main=no
-fi
-rm -f conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_z_main" >&5
-echo "${ECHO_T}$ac_cv_lib_z_main" >&6
-if test $ac_cv_lib_z_main = yes; then
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBZ 1
-_ACEOF
-
- LIBS="-lz $LIBS"
-
-fi
-
-fi
-
-# Shared libraries
-if test "$enable_shared" != "no" && test "$enable_profile" != "yes"
-then
- if uname | grep Darwin >/dev/null
- then
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.$MYLIBVER.$MYLIBREV.0.dylib"
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.$MYLIBVER.dylib"
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.dylib"
- MYLDLIBPATHENV="DYLD_LIBRARY_PATH"
- else
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.so.$MYLIBVER.$MYLIBREV.0"
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.so.$MYLIBVER"
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.so"
- fi
-fi
-
-
-
-#================================================================
-# Generic Settings
-#================================================================
-
-# Export variables
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Targets
- ac_config_files="$ac_config_files Makefile tokyocabinet.pc"
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems. If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-{
- (set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote
- # substitution turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- "s/'/'\\\\''/g;
- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n \
- "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
- ;;
- esac;
-} |
- sed '
- t clear
- : clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
- t end
- /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
- : end' >>confcache
-if diff $cache_file confcache >/dev/null 2>&1; then :; else
- if test -w $cache_file; then
- test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
- cat confcache >$cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=/{
-s/:*\$(srcdir):*/:/;
-s/:*\${srcdir}:*/:/;
-s/:*@srcdir@:*/:/;
-s/^\([^=]*=[ ]*\):*/\1/;
-s/:*$//;
-s/^[^=]*=[ ]*$//;
-}'
-fi
-
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-#
-# If the first sed substitution is executed (which looks for macros that
-# take arguments), then we branch to the quote section. Otherwise,
-# look for a macro that doesn't take arguments.
-cat >confdef2opt.sed <<\_ACEOF
-t clear
-: clear
-s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g
-t quote
-s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g
-t quote
-d
-: quote
-s,[ `~#$^&*(){}\\|;'"<>?],\\&,g
-s,\[,\\&,g
-s,\],\\&,g
-s,\$,$$,g
-p
-_ACEOF
-# We use echo to avoid assuming a particular line-breaking character.
-# The extra dot is to prevent the shell from consuming trailing
-# line-breaks from the sub-command output. A line-break within
-# single-quotes doesn't work because, if this script is created in a
-# platform that uses two characters for line-breaks (e.g., DOS), tr
-# would break.
-ac_LF_and_DOT=`echo; echo .`
-DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
-rm -f confdef2opt.sed
-
-
-ac_libobjs=
-ac_ltlibobjs=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
- # 1. Remove the extension, and $U if already installed.
- ac_i=`echo "$ac_i" |
- sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
- # 2. Add them.
- ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
- ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: ${CONFIG_STATUS=./config.status}
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
- set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- $as_unset $as_var
- fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)$' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
- /^X\/\(\/\/\)$/{ s//\1/; q; }
- /^X\/\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" || {
- # Find who we are. Look in the path if we contain no path at all
- # relative or not.
- case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
- ;;
- esac
- # We did not find ourselves, most probably we were run as `sh COMMAND'
- # in which case we are not to be found in the path.
- if test "x$as_myself" = x; then
- as_myself=$0
- fi
- if test ! -f "$as_myself"; then
- { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
-echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
- { (exit 1); exit 1; }; }
- fi
- case $CONFIG_SHELL in
- '')
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for as_base in sh bash ksh sh5; do
- case $as_dir in
- /*)
- if ("$as_dir/$as_base" -c '
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
- $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
- $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
- CONFIG_SHELL=$as_dir/$as_base
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$0" ${1+"$@"}
- fi;;
- esac
- done
-done
-;;
- esac
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line before each line; the second 'sed' does the real
- # work. The second script uses 'N' to pair each line-number line
- # with the numbered line, and appends trailing '-' during
- # substitution so that $LINENO is not a special case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
- sed '=' <$as_myself |
- sed '
- N
- s,$,-,
- : loop
- s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
- t loop
- s,-$,,
- s,^['$as_cr_digits']*\n,,
- ' >$as_me.lineno &&
- chmod +x $as_me.lineno ||
- { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
-echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensible to this).
- . ./$as_me.lineno
- # Exit status is that of the last command.
- exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
- *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T=' ' ;;
- *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
- *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- # We could just check for DJGPP; but this test a) works b) is more generic
- # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
- if test -f conf$$.exe; then
- # Don't use ln at all; we don't have any links
- as_ln_s='cp -p'
- else
- as_ln_s='ln -s'
- fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS=" $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-exec 6>&1
-
-# Open the log real soon, to keep \$[0] and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling. Logging --version etc. is OK.
-exec 5>>config.log
-{
- echo
- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-} >&5
-cat >&5 <<_CSEOF
-
-This file was extended by tokyocabinet $as_me 1.2.5, which was
-generated by GNU Autoconf 2.59. Invocation command line was
-
- CONFIG_FILES = $CONFIG_FILES
- CONFIG_HEADERS = $CONFIG_HEADERS
- CONFIG_LINKS = $CONFIG_LINKS
- CONFIG_COMMANDS = $CONFIG_COMMANDS
- $ $0 $@
-
-_CSEOF
-echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
-echo >&5
-_ACEOF
-
-# Files that config.status was made for.
-if test -n "$ac_config_files"; then
- echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_headers"; then
- echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_links"; then
- echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_commands"; then
- echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
- -h, --help print this help, then exit
- -V, --version print version number, then exit
- -q, --quiet do not print progress messages
- -d, --debug don't remove temporary files
- --recheck update $as_me by reconfiguring in the same conditions
- --file=FILE[:TEMPLATE]
- instantiate the configuration file FILE
-
-Configuration files:
-$config_files
-
-Report bugs to <bug-autoconf@gnu.org>."
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-ac_cs_version="\\
-tokyocabinet config.status 1.2.5
-configured by $0, generated by GNU Autoconf 2.59,
- with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-srcdir=$srcdir
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value. By we need to know if files were specified by the user.
-ac_need_defaults=:
-while test $# != 0
-do
- case $1 in
- --*=*)
- ac_option=`expr "x$1" : 'x\([^=]*\)='`
- ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
- ac_shift=:
- ;;
- -*)
- ac_option=$1
- ac_optarg=$2
- ac_shift=shift
- ;;
- *) # This is not an option, so the user has probably given explicit
- # arguments.
- ac_option=$1
- ac_need_defaults=false;;
- esac
-
- case $ac_option in
- # Handling of the options.
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- ac_cs_recheck=: ;;
- --version | --vers* | -V )
- echo "$ac_cs_version"; exit 0 ;;
- --he | --h)
- # Conflict between --help and --header
- { { echo "$as_me:$LINENO: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2;}
- { (exit 1); exit 1; }; };;
- --help | --hel | -h )
- echo "$ac_cs_usage"; exit 0 ;;
- --debug | --d* | -d )
- debug=: ;;
- --file | --fil | --fi | --f )
- $ac_shift
- CONFIG_FILES="$CONFIG_FILES $ac_optarg"
- ac_need_defaults=false;;
- --header | --heade | --head | --hea )
- $ac_shift
- CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
- ac_need_defaults=false;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil | --si | --s)
- ac_cs_silent=: ;;
-
- # This is an error.
- -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2;}
- { (exit 1); exit 1; }; } ;;
-
- *) ac_config_targets="$ac_config_targets $1" ;;
-
- esac
- shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
- exec 6>/dev/null
- ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-if \$ac_cs_recheck; then
- echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
- exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-fi
-
-_ACEOF
-
-
-
-
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_config_target in $ac_config_targets
-do
- case "$ac_config_target" in
- # Handling of arguments.
- "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- "tokyocabinet.pc" ) CONFIG_FILES="$CONFIG_FILES tokyocabinet.pc" ;;
- *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
- { (exit 1); exit 1; }; };;
- esac
-done
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used. Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
-fi
-
-# Have a temporary directory for convenience. Make it in the build tree
-# simply because there is no reason to put it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Create a temporary directory, and hook for its removal unless debugging.
-$debug ||
-{
- trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
- trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-
-# Create a (secure) tmp directory for tmp files.
-
-{
- tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
- test -n "$tmp" && test -d "$tmp"
-} ||
-{
- tmp=./confstat$$-$RANDOM
- (umask 077 && mkdir $tmp)
-} ||
-{
- echo "$me: cannot create a temporary directory in ." >&2
- { (exit 1); exit 1; }
-}
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-
-#
-# CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
- # Protect against being on the right side of a sed subst in config.status.
- sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
- s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
-s,@SHELL@,$SHELL,;t t
-s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
-s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
-s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
-s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
-s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
-s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
-s,@exec_prefix@,$exec_prefix,;t t
-s,@prefix@,$prefix,;t t
-s,@program_transform_name@,$program_transform_name,;t t
-s,@bindir@,$bindir,;t t
-s,@sbindir@,$sbindir,;t t
-s,@libexecdir@,$libexecdir,;t t
-s,@datadir@,$datadir,;t t
-s,@sysconfdir@,$sysconfdir,;t t
-s,@sharedstatedir@,$sharedstatedir,;t t
-s,@localstatedir@,$localstatedir,;t t
-s,@libdir@,$libdir,;t t
-s,@includedir@,$includedir,;t t
-s,@oldincludedir@,$oldincludedir,;t t
-s,@infodir@,$infodir,;t t
-s,@mandir@,$mandir,;t t
-s,@build_alias@,$build_alias,;t t
-s,@host_alias@,$host_alias,;t t
-s,@target_alias@,$target_alias,;t t
-s,@DEFS@,$DEFS,;t t
-s,@ECHO_C@,$ECHO_C,;t t
-s,@ECHO_N@,$ECHO_N,;t t
-s,@ECHO_T@,$ECHO_T,;t t
-s,@LIBS@,$LIBS,;t t
-s,@CC@,$CC,;t t
-s,@CFLAGS@,$CFLAGS,;t t
-s,@LDFLAGS@,$LDFLAGS,;t t
-s,@CPPFLAGS@,$CPPFLAGS,;t t
-s,@ac_ct_CC@,$ac_ct_CC,;t t
-s,@EXEEXT@,$EXEEXT,;t t
-s,@OBJEXT@,$OBJEXT,;t t
-s,@MYLIBVER@,$MYLIBVER,;t t
-s,@MYLIBREV@,$MYLIBREV,;t t
-s,@MYFORMATVER@,$MYFORMATVER,;t t
-s,@MYHEADERFILES@,$MYHEADERFILES,;t t
-s,@MYLIBRARYFILES@,$MYLIBRARYFILES,;t t
-s,@MYLIBOBJFILES@,$MYLIBOBJFILES,;t t
-s,@MYCOMMANDFILES@,$MYCOMMANDFILES,;t t
-s,@MYMAN1FILES@,$MYMAN1FILES,;t t
-s,@MYMAN3FILES@,$MYMAN3FILES,;t t
-s,@MYDOCUMENTFILES@,$MYDOCUMENTFILES,;t t
-s,@MYPCFILES@,$MYPCFILES,;t t
-s,@MYCFLAGS@,$MYCFLAGS,;t t
-s,@MYCPPFLAGS@,$MYCPPFLAGS,;t t
-s,@MYLDFLAGS@,$MYLDFLAGS,;t t
-s,@MYRUNPATH@,$MYRUNPATH,;t t
-s,@MYLDLIBPATHENV@,$MYLDLIBPATHENV,;t t
-s,@MYPOSTCMD@,$MYPOSTCMD,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
-s,@LTLIBOBJS@,$LTLIBOBJS,;t t
-CEOF
-
-_ACEOF
-
- cat >>$CONFIG_STATUS <<\_ACEOF
- # Split the substitutions into bite-sized pieces for seds with
- # small command number limits, like on Digital OSF/1 and HP-UX.
- ac_max_sed_lines=48
- ac_sed_frag=1 # Number of current file.
- ac_beg=1 # First line for current file.
- ac_end=$ac_max_sed_lines # Line after last line for current file.
- ac_more_lines=:
- ac_sed_cmds=
- while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
- else
- sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
- fi
- if test ! -s $tmp/subs.frag; then
- ac_more_lines=false
- else
- # The purpose of the label and of the branching condition is to
- # speed up the sed processing (if there are no `@' at all, there
- # is no need to browse any of the substitutions).
- # These are the two extra sed commands mentioned above.
- (echo ':t
- /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
- fi
- ac_sed_frag=`expr $ac_sed_frag + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_lines`
- fi
- done
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
- fi
-fi # test -n "$CONFIG_FILES"
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case $ac_file in
- - | *:- | *:-:* ) # input from stdin
- cat >$tmp/stdin
- ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
- ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
- * ) ac_file_in=$ac_file.in ;;
- esac
-
- # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
- ac_dir=`(dirname "$ac_file") 2>/dev/null ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_file" : 'X\(//\)[^/]' \| \
- X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- { if $as_mkdir_p; then
- mkdir -p "$ac_dir"
- else
- as_dir="$ac_dir"
- as_dirs=
- while test ! -d "$as_dir"; do
- as_dirs="$as_dir $as_dirs"
- as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| \
- . : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
- /^X\(\/\/\)[^/].*/{ s//\1/; q; }
- /^X\(\/\/\)$/{ s//\1/; q; }
- /^X\(\/\).*/{ s//\1/; q; }
- s/.*/./; q'`
- done
- test ! -n "$as_dirs" || mkdir $as_dirs
- fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
- { (exit 1); exit 1; }; }; }
-
- ac_builddir=.
-
-if test "$ac_dir" != .; then
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A "../" for each directory in $ac_dir_suffix.
- ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
- ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
- .) # No --srcdir option. We are building in place.
- ac_srcdir=.
- if test -z "$ac_top_builddir"; then
- ac_top_srcdir=.
- else
- ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
- fi ;;
- [\\/]* | ?:[\\/]* ) # Absolute path.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir ;;
- *) # Relative path.
- ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
- case "$ac_dir" in
- .) ac_abs_builddir=`pwd`;;
- [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
- *) ac_abs_builddir=`pwd`/"$ac_dir";;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
- case ${ac_top_builddir}. in
- .) ac_abs_top_builddir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
- *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
- case $ac_srcdir in
- .) ac_abs_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
- *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
- esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
- case $ac_top_srcdir in
- .) ac_abs_top_srcdir=$ac_abs_builddir;;
- [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
- *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
- esac;;
-esac
-
-
-
- if test x"$ac_file" != x-; then
- { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
- rm -f "$ac_file"
- fi
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- if test x"$ac_file" = x-; then
- configure_input=
- else
- configure_input="$ac_file. "
- fi
- configure_input=$configure_input"Generated from `echo $ac_file_in |
- sed 's,.*/,,'` by configure."
-
- # First look for the input files in the build tree, otherwise in the
- # src tree.
- ac_file_inputs=`IFS=:
- for f in $ac_file_in; do
- case $f in
- -) echo $tmp/stdin ;;
- [\\/$]*)
- # Absolute (can't be DOS-style, as IFS=:)
- test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- echo "$f";;
- *) # Relative
- if test -f "$f"; then
- # Build tree
- echo "$f"
- elif test -f "$srcdir/$f"; then
- # Source tree
- echo "$srcdir/$f"
- else
- # /dev/null tree
- { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
- { (exit 1); exit 1; }; }
- fi;;
- esac
- done` || { (exit 1); exit 1; }
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
- sed "$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@configure_input@,$configure_input,;t t
-s,@srcdir@,$ac_srcdir,;t t
-s,@abs_srcdir@,$ac_abs_srcdir,;t t
-s,@top_srcdir@,$ac_top_srcdir,;t t
-s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
-s,@builddir@,$ac_builddir,;t t
-s,@abs_builddir@,$ac_abs_builddir,;t t
-s,@top_builddir@,$ac_top_builddir,;t t
-s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
-" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
- rm -f $tmp/stdin
- if test x"$ac_file" != x-; then
- mv $tmp/out $ac_file
- else
- cat $tmp/out
- rm -f $tmp/out
- fi
-
-done
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-{ (exit 0); exit 0; }
-_ACEOF
-chmod +x $CONFIG_STATUS
-ac_clean_files=$ac_clean_files_save
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded. So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status. When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
- ac_cs_success=:
- ac_config_status_args=
- test "$silent" = yes &&
- ac_config_status_args="$ac_config_status_args --quiet"
- exec 5>/dev/null
- $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
- exec 5>>config.log
- # Use ||, not &&, to avoid exiting from the if with $? = 1, which
- # would make configure fail if this is the last instruction.
- $ac_cs_success || { (exit 1); exit 1; }
-fi
-
-
-# Messages
-printf '#================================================================\n'
-printf '# Ready to make.\n'
-printf '#================================================================\n'
-
-
-
-# END OF FILE
+++ /dev/null
-# Source of configuration for Tokyo Cabinet
-
-
-
-#================================================================
-# Generic Settings
-#================================================================
-
-# Package name
-AC_INIT(tokyocabinet, 1.2.5)
-
-# Package information
-MYLIBVER=3
-MYLIBREV=6
-MYFORMATVER="1.0"
-
-# Targets
-MYHEADERFILES="tcutil.h tchdb.h tcbdb.h tcadb.h"
-MYLIBRARYFILES="libtokyocabinet.a"
-MYLIBOBJFILES="tcutil.o tchdb.o tcbdb.o tcadb.o myconf.o"
-MYCOMMANDFILES="tcutest tcumttest tcucodec tchtest tchmttest tchmgr"
-MYCOMMANDFILES="$MYCOMMANDFILES tcbtest tcbmttest tcbmgr tcatest tcamgr"
-MYMAN1FILES="tcutest.1 tcumttest.1 tcucodec.1 tchtest.1 tchmttest.1 tchmgr.1"
-MYMAN1FILES="$MYMAN1FILES tcbtest.1 tcbmttest.1 tcbmgr.1 tcatest.1 tcamgr.1"
-MYMAN3FILES="tokyocabinet.3 tcutil.3 tcxstr.3 tclist.3 tcmap.3 tcmdb.3 tcmpool.3"
-MYMAN3FILES="$MYMAN3FILES tchdb.3 tcbdb.3 tcadb.3"
-MYDOCUMENTFILES="COPYING ChangeLog THANKS doc"
-MYPCFILES="tokyocabinet.pc"
-
-# Building flags
-MYCFLAGS="-std=c99 -Wall -fPIC -fsigned-char -O2"
-MYCPPFLAGS="-I. -I\$(INCLUDEDIR) -L$HOME/include -L/usr/local/include -DNDEBUG -D_GNU_SOURCE=1"
-MYLDFLAGS="-L. -L\$(LIBDIR) -L$HOME/lib -L/usr/local/lib"
-MYRUNPATH="\$(LIBDIR)"
-MYLDLIBPATHENV="LD_LIBRARY_PATH"
-MYPOSTCMD="true"
-
-# Building paths
-pathtmp="$PATH"
-PATH="$HOME/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin"
-PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp"
-LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH"
-LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH"
-CPATH="$HOME/include:/usr/local/include:$CPATH"
-PKG_CONFIG_PATH="$HOME/lib/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH"
-export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH PKG_CONFIG_PATH
-
-
-
-#================================================================
-# Options
-#================================================================
-
-
-# Internal variables
-enables=""
-
-# Debug mode
-AC_ARG_ENABLE(debug,
- AC_HELP_STRING([--enable-debug], [build for debugging]))
-if test "$enable_debug" = "yes"
-then
- MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g"
- MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG"
- MYLDFLAGS="$MYLDFLAGS -static"
- enables="$enables (debug)"
-fi
-
-# Developping mode
-AC_ARG_ENABLE(devel,
- AC_HELP_STRING([--enable-devel], [build for development]))
-if test "$enable_devel" = "yes"
-then
- MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -O2 -pipe"
- MYCPPFLAGS="$MYCPPFLAGS -UNDEBUG"
- enables="$enables (devel)"
-fi
-
-# Profiling mode
-AC_ARG_ENABLE(profile,
- AC_HELP_STRING([--enable-profile], [build for profiling]))
-if test "$enable_profile" = "yes"
-then
- MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -g -pg -O2 -pipe"
- enables="$enables (profile)"
-fi
-
-# 64-bit offset mode
-AC_ARG_ENABLE(off64,
- AC_HELP_STRING([--enable-off64], [build with 64-bit file offset on 32-bit system]))
-if test "$enable_off64" = "yes"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_FILE_OFFSET_BITS=64"
- enables="$enables (off64)"
-fi
-
-# Fastest mode
-AC_ARG_ENABLE(fastest,
- AC_HELP_STRING([--enable-fastest], [build for fastest run]))
-if test "$enable_fastest" = "yes"
-then
- MYCFLAGS="-std=c99 -Wall -fPIC -pedantic -fsigned-char -O3"
- MYCFLAGS="$MYCFLAGS -fomit-frame-pointer -fforce-addr -minline-all-stringops"
- MYCPPFLAGS="$MYCPPFLAGS -D_MYFASTEST"
- enables="$enables (fastest)"
-fi
-
-# Swapping byte-orders mode
-AC_ARG_ENABLE(swab,
- AC_HELP_STRING([--enable-swab], [build for swapping byte-orders]))
-if test "$enable_swab" = "yes"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_MYSWAB"
- enables="$enables (swab)"
-fi
-
-# Micro yield mode
-AC_ARG_ENABLE(uyield,
- AC_HELP_STRING([--enable-uyield], [build for detecting race conditions]))
-if test "$enable_uyield" = "yes"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_MYMICROYIELD"
- enables="$enables (uyield)"
-fi
-
-# Disable ZLIB compression
-AC_ARG_ENABLE(zlib,
- AC_HELP_STRING([--disable-zlib], [build without ZLIB compression]))
-if test "$enable_zlib" = "no"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_MYNOZLIB"
- enables="$enables (no-zlib)"
-fi
-
-# Disable POSIX thread
-AC_ARG_ENABLE(pthread,
- AC_HELP_STRING([--disable-pthread], [build without POSIX thread support]))
-if test "$enable_pthread" = "no"
-then
- MYCPPFLAGS="$MYCPPFLAGS -D_MYNOPTHREAD"
- enables="$enables (no-pthread)"
-fi
-
-# Disable shared object
-AC_ARG_ENABLE(shared,
- AC_HELP_STRING([--disable-shared], [avoid to build shared libraries]))
-if test "$enable_shared" = "no"
-then
- enables="$enables (no-shared)"
-fi
-
-# Messages
-printf '#================================================================\n'
-printf '# Configuring Tokyo Cabinet version %s%s.\n' "$PACKAGE_VERSION" "$enables"
-printf '#================================================================\n'
-
-
-
-#================================================================
-# Checking Commands and Libraries
-#================================================================
-
-# C compiler
-AC_PROG_CC
-
-# Byte order
-AC_C_BIGENDIAN(MYCPPFLAGS="$MYCPPFLAGS -D_MYBIGEND")
-
-# Underlying libraries
-AC_CHECK_LIB(c, main)
-AC_CHECK_LIB(m, main)
-if test "$enable_pthread" != "no"
-then
-AC_CHECK_LIB(pthread, main)
-fi
-if test "$enable_zlib" != "no"
-then
- AC_CHECK_LIB(z, main)
-fi
-
-# Shared libraries
-if test "$enable_shared" != "no" && test "$enable_profile" != "yes"
-then
- if uname | grep Darwin >/dev/null
- then
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.$MYLIBVER.$MYLIBREV.0.dylib"
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.$MYLIBVER.dylib"
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.dylib"
- MYLDLIBPATHENV="DYLD_LIBRARY_PATH"
- else
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.so.$MYLIBVER.$MYLIBREV.0"
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.so.$MYLIBVER"
- MYLIBRARYFILES="$MYLIBRARYFILES libtokyocabinet.so"
- fi
-fi
-
-
-
-#================================================================
-# Generic Settings
-#================================================================
-
-# Export variables
-AC_SUBST(MYLIBVER)
-AC_SUBST(MYLIBREV)
-AC_SUBST(MYFORMATVER)
-AC_SUBST(MYHEADERFILES)
-AC_SUBST(MYLIBRARYFILES)
-AC_SUBST(MYLIBOBJFILES)
-AC_SUBST(MYCOMMANDFILES)
-AC_SUBST(MYMAN1FILES)
-AC_SUBST(MYMAN3FILES)
-AC_SUBST(MYDOCUMENTFILES)
-AC_SUBST(MYPCFILES)
-AC_SUBST(MYCFLAGS)
-AC_SUBST(MYCPPFLAGS)
-AC_SUBST(MYLDFLAGS)
-AC_SUBST(MYRUNPATH)
-AC_SUBST(MYLDLIBPATHENV)
-AC_SUBST(MYPOSTCMD)
-
-# Targets
-AC_OUTPUT(Makefile tokyocabinet.pc)
-
-# Messages
-printf '#================================================================\n'
-printf '# Ready to make.\n'
-printf '#================================================================\n'
-
-
-
-# END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * System-dependent configurations of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include "myconf.h"
-
-
-
-/*************************************************************************************************
- * common settings
- *************************************************************************************************/
-
-
-int _tc_dummyfunc(void){
- return 0;
-}
-
-
-int _tc_dummyfuncv(int a, ...){
- return 0;
-}
-
-
-
-/*************************************************************************************************
- * for ZLIB
- *************************************************************************************************/
-
-
-#if TCUSEZLIB
-
-
-#include <zlib.h>
-
-#define ZLIBBUFSIZ 8192
-
-
-static char *_tc_deflate_impl(const char *ptr, int size, int *sp, int mode);
-static char *_tc_inflate_impl(const char *ptr, int size, int *sp, int mode);
-static unsigned int _tc_getcrc_impl(const char *ptr, int size);
-
-
-char *(*_tc_deflate)(const char *, int, int *, int) = _tc_deflate_impl;
-char *(*_tc_inflate)(const char *, int, int *, int) = _tc_inflate_impl;
-unsigned int (*_tc_getcrc)(const char *, int) = _tc_getcrc_impl;
-
-
-static char *_tc_deflate_impl(const char *ptr, int size, int *sp, int mode){
- assert(ptr && size >= 0 && sp);
- z_stream zs;
- char *buf, *swap;
- unsigned char obuf[ZLIBBUFSIZ];
- int rv, asiz, bsiz, osiz;
- zs.zalloc = Z_NULL;
- zs.zfree = Z_NULL;
- zs.opaque = Z_NULL;
- switch(mode){
- case _TCZMRAW:
- if(deflateInit2(&zs, 5, Z_DEFLATED, -15, 7, Z_DEFAULT_STRATEGY) != Z_OK)
- return NULL;
- break;
- case _TCZMGZIP:
- if(deflateInit2(&zs, 6, Z_DEFLATED, 15 + 16, 9, Z_DEFAULT_STRATEGY) != Z_OK)
- return NULL;
- break;
- default:
- if(deflateInit2(&zs, 6, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY) != Z_OK)
- return NULL;
- break;
- }
- asiz = size + 16;
- if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ;
- if(!(buf = malloc(asiz))){
- deflateEnd(&zs);
- return NULL;
- }
- bsiz = 0;
- zs.next_in = (unsigned char *)ptr;
- zs.avail_in = size;
- zs.next_out = obuf;
- zs.avail_out = ZLIBBUFSIZ;
- while((rv = deflate(&zs, Z_FINISH)) == Z_OK){
- osiz = ZLIBBUFSIZ - zs.avail_out;
- if(bsiz + osiz > asiz){
- asiz = asiz * 2 + osiz;
- if(!(swap = realloc(buf, asiz))){
- free(buf);
- deflateEnd(&zs);
- return NULL;
- }
- buf = swap;
- }
- memcpy(buf + bsiz, obuf, osiz);
- bsiz += osiz;
- zs.next_out = obuf;
- zs.avail_out = ZLIBBUFSIZ;
- }
- if(rv != Z_STREAM_END){
- free(buf);
- deflateEnd(&zs);
- return NULL;
- }
- osiz = ZLIBBUFSIZ - zs.avail_out;
- if(bsiz + osiz + 1 > asiz){
- asiz = asiz * 2 + osiz;
- if(!(swap = realloc(buf, asiz))){
- free(buf);
- deflateEnd(&zs);
- return NULL;
- }
- buf = swap;
- }
- memcpy(buf + bsiz, obuf, osiz);
- bsiz += osiz;
- buf[bsiz] = '\0';
- if(mode == _TCZMRAW) bsiz++;
- *sp = bsiz;
- deflateEnd(&zs);
- return buf;
-}
-
-
-static char *_tc_inflate_impl(const char *ptr, int size, int *sp, int mode){
- assert(ptr && size >= 0 && sp);
- z_stream zs;
- char *buf, *swap;
- unsigned char obuf[ZLIBBUFSIZ];
- int rv, asiz, bsiz, osiz;
- zs.zalloc = Z_NULL;
- zs.zfree = Z_NULL;
- zs.opaque = Z_NULL;
- switch(mode){
- case _TCZMRAW:
- if(inflateInit2(&zs, -15) != Z_OK) return NULL;
- break;
- case _TCZMGZIP:
- if(inflateInit2(&zs, 15 + 16) != Z_OK) return NULL;
- break;
- default:
- if(inflateInit2(&zs, 15) != Z_OK) return NULL;
- break;
- }
- asiz = size * 2 + 16;
- if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ;
- if(!(buf = malloc(asiz))){
- inflateEnd(&zs);
- return NULL;
- }
- bsiz = 0;
- zs.next_in = (unsigned char *)ptr;
- zs.avail_in = size;
- zs.next_out = obuf;
- zs.avail_out = ZLIBBUFSIZ;
- while((rv = inflate(&zs, Z_NO_FLUSH)) == Z_OK){
- osiz = ZLIBBUFSIZ - zs.avail_out;
- if(bsiz + osiz >= asiz){
- asiz = asiz * 2 + osiz;
- if(!(swap = realloc(buf, asiz))){
- free(buf);
- inflateEnd(&zs);
- return NULL;
- }
- buf = swap;
- }
- memcpy(buf + bsiz, obuf, osiz);
- bsiz += osiz;
- zs.next_out = obuf;
- zs.avail_out = ZLIBBUFSIZ;
- }
- if(rv != Z_STREAM_END){
- free(buf);
- inflateEnd(&zs);
- return NULL;
- }
- osiz = ZLIBBUFSIZ - zs.avail_out;
- if(bsiz + osiz >= asiz){
- asiz = asiz * 2 + osiz;
- if(!(swap = realloc(buf, asiz))){
- free(buf);
- inflateEnd(&zs);
- return NULL;
- }
- buf = swap;
- }
- memcpy(buf + bsiz, obuf, osiz);
- bsiz += osiz;
- buf[bsiz] = '\0';
- *sp = bsiz;
- inflateEnd(&zs);
- return buf;
-}
-
-
-static unsigned int _tc_getcrc_impl(const char *ptr, int size){
- assert(ptr && size >= 0);
- int crc = crc32(0, Z_NULL, 0);
- return crc32(crc, (unsigned char *)ptr, size);
-}
-
-
-#else
-
-
-char *(*_tc_deflate)(const char *, int, int *, int) = NULL;
-char *(*_tc_inflate)(const char *, int, int *, int) = NULL;
-unsigned int (*_tc_getcrc)(const char *, int) = NULL;
-
-
-#endif
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * System-dependent configurations of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#ifndef _MYCONF_H // duplication check
-#define _MYCONF_H
-
-
-
-/*************************************************************************************************
- * system discrimination
- *************************************************************************************************/
-
-
-#if defined(__linux__)
-
-#define _SYS_LINUX_
-#define ESTSYSNAME "Linux"
-
-#elif defined(__FreeBSD__)
-
-#define _SYS_FREEBSD_
-#define ESTSYSNAME "FreeBSD"
-
-#elif defined(__NetBSD__)
-
-#define _SYS_NETBSD_
-#define ESTSYSNAME "NetBSD"
-
-#elif defined(__OpenBSD__)
-
-#define _SYS_OPENBSD_
-#define ESTSYSNAME "OpenBSD"
-
-#elif defined(__sun__)
-
-#define _SYS_SUNOS_
-#define ESTSYSNAME "SunOS"
-
-#elif defined(__hpux)
-
-#define _SYS_HPUX_
-#define ESTSYSNAME "HP-UX"
-
-#elif defined(__osf)
-
-#define _SYS_TRU64_
-#define ESTSYSNAME "Tru64"
-
-#elif defined(_AIX)
-
-#define _SYS_AIX_
-#define ESTSYSNAME "AIX"
-
-#elif defined(__APPLE__) && defined(__MACH__)
-
-#define _SYS_MACOSX_
-#define ESTSYSNAME "Mac OS X"
-
-#elif defined(_MSC_VER)
-
-#define _SYS_MSVC_
-#define ESTSYSNAME "Windows (VC++)"
-
-#elif defined(_WIN32)
-
-#define _SYS_MINGW_
-#define ESTSYSNAME "Windows (MinGW)"
-
-#elif defined(__CYGWIN__)
-
-#define _SYS_CYGWIN_
-#define ESTSYSNAME "Windows (Cygwin)"
-
-#else
-
-#define _SYS_GENERIC_
-#define ESTSYSNAME "Generic"
-
-#endif
-
-
-
-/*************************************************************************************************
- * common settings
- *************************************************************************************************/
-
-
-#if defined(NDEBUG)
-#define TCDODEBUG(TC_expr) \
- do { \
- } while(false)
-#else
-#define TCDODEBUG(TC_expr) \
- do { \
- TC_expr; \
- } while(false)
-#endif
-
-#define TCSWAB16(TC_num) \
- ( \
- ((TC_num & 0x00ffU) << 8) | \
- ((TC_num & 0xff00U) >> 8) \
- )
-
-#define TCSWAB32(TC_num) \
- ( \
- ((TC_num & 0x000000ffUL) << 24) | \
- ((TC_num & 0x0000ff00UL) << 8) | \
- ((TC_num & 0x00ff0000UL) >> 8) | \
- ((TC_num & 0xff000000UL) >> 24) \
- )
-
-#define TCSWAB64(TC_num) \
- ( \
- ((TC_num & 0x00000000000000ffULL) << 56) | \
- ((TC_num & 0x000000000000ff00ULL) << 40) | \
- ((TC_num & 0x0000000000ff0000ULL) << 24) | \
- ((TC_num & 0x00000000ff000000ULL) << 8) | \
- ((TC_num & 0x000000ff00000000ULL) >> 8) | \
- ((TC_num & 0x0000ff0000000000ULL) >> 24) | \
- ((TC_num & 0x00ff000000000000ULL) >> 40) | \
- ((TC_num & 0xff00000000000000ULL) >> 56) \
- )
-
-#if defined(_MYBIGEND) || defined(_MYSWAB)
-#define TCBIGEND 1
-#define TCHTOIS(TC_num) TCSWAB16(TC_num)
-#define TCHTOIL(TC_num) TCSWAB32(TC_num)
-#define TCHTOILL(TC_num) TCSWAB64(TC_num)
-#define TCITOHS(TC_num) TCSWAB16(TC_num)
-#define TCITOHL(TC_num) TCSWAB32(TC_num)
-#define TCITOHLL(TC_num) TCSWAB64(TC_num)
-#else
-#define TCBIGEND 0
-#define TCHTOIS(TC_num) (TC_num)
-#define TCHTOIL(TC_num) (TC_num)
-#define TCHTOILL(TC_num) (TC_num)
-#define TCITOHS(TC_num) (TC_num)
-#define TCITOHL(TC_num) (TC_num)
-#define TCITOHLL(TC_num) (TC_num)
-#endif
-
-#if defined(_MYNOZLIB)
-#define TCUSEZLIB 0
-#else
-#define TCUSEZLIB 1
-#endif
-
-#if defined(_MYNOPTHREAD)
-#define TCUSEPTHREAD 0
-#else
-#define TCUSEPTHREAD 1
-#endif
-
-#if defined(_MYMICROYIELD)
-#define TCMICROYIELD 1
-#else
-#define TCMICROYIELD 0
-#endif
-
-#define sizeof(a) ((int)sizeof(a))
-
-int _tc_dummyfunc(void);
-int _tc_dummyfuncv(int a, ...);
-
-
-
-/*************************************************************************************************
- * general headers
- *************************************************************************************************/
-
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <float.h>
-#include <limits.h>
-#include <locale.h>
-#include <math.h>
-#include <setjmp.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/times.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <regex.h>
-#include <glob.h>
-
-#if TCUSEPTHREAD
-#include <pthread.h>
-#endif
-
-
-
-/*************************************************************************************************
- * notation of filesystems
- *************************************************************************************************/
-
-
-#define MYPATHCHR '/'
-#define MYPATHSTR "/"
-#define MYEXTCHR '.'
-#define MYEXTSTR "."
-#define MYCDIRSTR "."
-#define MYPDIRSTR ".."
-
-
-
-/*************************************************************************************************
- * for ZLIB
- *************************************************************************************************/
-
-
-enum {
- _TCZMZLIB,
- _TCZMRAW,
- _TCZMGZIP
-};
-
-
-extern char *(*_tc_deflate)(const char *, int, int *, int);
-
-extern char *(*_tc_inflate)(const char *, int, int *, int);
-
-extern unsigned int (*_tc_getcrc)(const char *, int);
-
-
-
-/*************************************************************************************************
- * for POSIX thread disability
- *************************************************************************************************/
-
-
-#if ! TCUSEPTHREAD
-
-#define pthread_once_t int
-#undef PTHREAD_ONCE_INIT
-#define PTHREAD_ONCE_INIT 0
-#define pthread_once(TC_a, TC_b) _tc_dummyfuncv((int)(TC_a), (TC_b))
-
-#define pthread_mutexattr_t int
-#undef PTHREAD_MUTEX_RECURSIVE
-#define PTHREAD_MUTEX_RECURSIVE 0
-#define pthread_mutexattr_init(TC_a) _tc_dummyfuncv((int)(TC_a))
-#define pthread_mutexattr_destroy(TC_a) _tc_dummyfuncv((int)(TC_a))
-#define pthread_mutexattr_settype(TC_a, TC_b) _tc_dummyfuncv((int)(TC_a), (TC_b))
-
-#define pthread_mutex_t int
-#undef PTHREAD_MUTEX_INITIALIZER
-#define PTHREAD_MUTEX_INITIALIZER 0
-#define pthread_mutex_init(TC_a, TC_b) _tc_dummyfuncv((int)(TC_a), (TC_b))
-#define pthread_mutex_destroy(TC_a) _tc_dummyfuncv((int)(TC_a))
-#define pthread_mutex_lock(TC_a) _tc_dummyfuncv((int)(TC_a))
-#define pthread_mutex_unlock(TC_a) _tc_dummyfuncv((int)(TC_a))
-
-#define pthread_rwlock_t int
-#undef PTHREAD_RWLOCK_INITIALIZER
-#define PTHREAD_RWLOCK_INITIALIZER 0
-#define pthread_rwlock_init(TC_a, TC_b) _tc_dummyfuncv((int)(TC_a), (TC_b))
-#define pthread_rwlock_destroy(TC_a) _tc_dummyfuncv((int)(TC_a))
-#define pthread_rwlock_rdlock(TC_a) _tc_dummyfuncv((int)(TC_a))
-#define pthread_rwlock_wrlock(TC_a) _tc_dummyfuncv((int)(TC_a))
-#define pthread_rwlock_unlock(TC_a) _tc_dummyfuncv((int)(TC_a))
-
-#define pthread_key_create(TC_a, TC_b) _tc_dummyfuncv((int)(TC_a), (TC_b))
-#define pthread_key_delete(TC_a) _tc_dummyfuncv((int)(TC_a))
-#define pthread_setspecific(TC_a, TC_b) _tc_dummyfuncv((int)(TC_a))
-#define pthread_getspecific(TC_a) _tc_dummyfuncv((int)(TC_a))
-
-#define pthread_create(TC_th, TC_attr, TC_func, TC_arg) \
- (*(TC_th) = 0, (TC_func)(TC_arg), 0)
-#define pthread_join(TC_th, TC_rv) \
- (*(TC_rv) = NULL, 0)
-#define pthread_detach(TC_th) 0
-
-#endif
-
-#if TCUSEPTHREAD && TCMICROYIELD
-#define TCTESTYIELD() \
- do { \
- static uint32_t cnt = 0; \
- if(((++cnt) & (0x20 - 1)) == 0){ \
- pthread_yield(); \
- if(cnt > 0x1000) cnt = (uint32_t)time(NULL) % 0x1000; \
- } \
- } while(false)
-#undef assert
-#define assert(TC_expr) \
- do { \
- if(!(TC_expr)){ \
- fprintf(stderr, "assertion failed: %s\n", #TC_expr); \
- abort(); \
- } \
- TCTESTYIELD(); \
- } while(false)
-#else
-#define TCTESTYIELD() \
- do { \
- } while(false);
-#endif
-
-
-
-/*************************************************************************************************
- * utilities for implementation
- *************************************************************************************************/
-
-
-#define TCNUMBUFSIZ 32 // size of a buffer for a number
-
-/* set a buffer for a variable length number */
-#define TCSETVNUMBUF(TC_len, TC_buf, TC_num) \
- do { \
- int _TC_num = (TC_num); \
- if(_TC_num == 0){ \
- ((signed char *)(TC_buf))[0] = 0; \
- (TC_len) = 1; \
- } else { \
- (TC_len) = 0; \
- while(_TC_num > 0){ \
- int _TC_rem = _TC_num & 0x7f; \
- _TC_num >>= 7; \
- if(_TC_num > 0){ \
- ((signed char *)(TC_buf))[(TC_len)] = -_TC_rem - 1; \
- } else { \
- ((signed char *)(TC_buf))[(TC_len)] = _TC_rem; \
- } \
- (TC_len)++; \
- } \
- } \
- } while(false)
-
-/* set a buffer for a variable length number of 64-bit */
-#define TCSETVNUMBUF64(TC_len, TC_buf, TC_num) \
- do { \
- long long int _TC_num = (TC_num); \
- if(_TC_num == 0){ \
- ((signed char *)(TC_buf))[0] = 0; \
- (TC_len) = 1; \
- } else { \
- (TC_len) = 0; \
- while(_TC_num > 0){ \
- int _TC_rem = _TC_num & 0x7f; \
- _TC_num >>= 7; \
- if(_TC_num > 0){ \
- ((signed char *)(TC_buf))[(TC_len)] = -_TC_rem - 1; \
- } else { \
- ((signed char *)(TC_buf))[(TC_len)] = _TC_rem; \
- } \
- (TC_len)++; \
- } \
- } \
- } while(false)
-
-/* read a variable length buffer */
-#define TCREADVNUMBUF(TC_buf, TC_num, TC_step) \
- do { \
- TC_num = 0; \
- int _TC_base = 1; \
- int _TC_i = 0; \
- while(true){ \
- if(((signed char *)(TC_buf))[_TC_i] >= 0){ \
- TC_num += ((signed char *)(TC_buf))[_TC_i] * _TC_base; \
- break; \
- } \
- TC_num += _TC_base * (((signed char *)(TC_buf))[_TC_i] + 1) * -1; \
- _TC_base <<= 7; \
- _TC_i++; \
- } \
- (TC_step) = _TC_i + 1; \
- } while(false)
-
-/* read a variable length buffer */
-#define TCREADVNUMBUF64(TC_buf, TC_num, TC_step) \
- do { \
- TC_num = 0; \
- long long int _TC_base = 1; \
- int _TC_i = 0; \
- while(true){ \
- if(((signed char *)(TC_buf))[_TC_i] >= 0){ \
- TC_num += ((signed char *)(TC_buf))[_TC_i] * _TC_base; \
- break; \
- } \
- TC_num += _TC_base * (((signed char *)(TC_buf))[_TC_i] + 1) * -1; \
- _TC_base <<= 7; \
- _TC_i++; \
- } \
- (TC_step) = _TC_i + 1; \
- } while(false)
-
-/* Compare keys of two records by lexical order. */
-#define TCCMPLEXICAL(TC_rv, TC_aptr, TC_asiz, TC_bptr, TC_bsiz) \
- do { \
- (TC_rv) = 0; \
- int _TC_min = (TC_asiz) < (TC_bsiz) ? (TC_asiz) : (TC_bsiz); \
- for(int _TC_i = 0; _TC_i < _TC_min; _TC_i++){ \
- if(((unsigned char *)(TC_aptr))[_TC_i] != ((unsigned char *)(TC_bptr))[_TC_i]){ \
- (TC_rv) = ((unsigned char *)(TC_aptr))[_TC_i] - ((unsigned char *)(TC_bptr))[_TC_i]; \
- break; \
- } \
- } \
- if((TC_rv) == 0) (TC_rv) = (TC_asiz) - (TC_bsiz); \
- } while(false)
-
-
-
-#endif // duplication check
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The abstract database API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include "tcutil.h"
-#include "tchdb.h"
-#include "tcbdb.h"
-#include "tcadb.h"
-#include "myconf.h"
-
-
-
-/*************************************************************************************************
- * API
- *************************************************************************************************/
-
-
-/* Create an abstract database object. */
-TCADB *tcadbnew(void){
- TCADB *adb;
- TCMALLOC(adb, sizeof(*adb));
- adb->name = NULL;
- adb->mdb = NULL;
- adb->hdb = NULL;
- adb->bdb = NULL;
- adb->capnum = -1;
- adb->capsiz = -1;
- adb->capcnt = 0;
- adb->cur = NULL;
- return adb;
-}
-
-
-/* Delete an abstract database object. */
-void tcadbdel(TCADB *adb){
- assert(adb);
- if(adb->name) tcadbclose(adb);
- free(adb);
-}
-
-
-/* Open an abstract database. */
-bool tcadbopen(TCADB *adb, const char *name){
- assert(adb && name);
- TCLIST *elems = tcstrsplit(name, "#");
- char *path = tclistshift2(elems);
- if(!path){
- tclistdel(elems);
- return false;
- }
- int64_t bnum = -1;
- int64_t capnum = -1;
- int64_t capsiz = -1;
- bool owmode = true;
- bool ocmode = true;
- bool otmode = false;
- bool onlmode = false;
- bool onbmode = false;
- int8_t apow = -1;
- int8_t fpow = -1;
- bool tlmode = false;
- bool tdmode = false;
- int32_t rcnum = -1;
- int32_t lmemb = -1;
- int32_t nmemb = -1;
- int32_t lcnum = -1;
- int32_t ncnum = -1;
- int ln = TCLISTNUM(elems);
- for(int i = 0; i < ln; i++){
- const char *elem = TCLISTVALPTR(elems, i);
- char *pv = strchr(elem, '=');
- if(!pv) continue;
- *(pv++) = '\0';
- if(!tcstricmp(elem, "bnum")){
- bnum = strtoll(pv, NULL, 10);
- } else if(!tcstricmp(elem, "capnum")){
- capnum = strtoll(pv, NULL, 10);
- } else if(!tcstricmp(elem, "capsiz")){
- capsiz = strtoll(pv, NULL, 10);
- } else if(!tcstricmp(elem, "mode")){
- owmode = strchr(pv, 'w') || strchr(pv, 'W');
- ocmode = strchr(pv, 'c') || strchr(pv, 'C');
- otmode = strchr(pv, 't') || strchr(pv, 'T');
- onlmode = strchr(pv, 'e') || strchr(pv, 'E');
- onbmode = strchr(pv, 'f') || strchr(pv, 'F');
- } else if(!tcstricmp(elem, "apow")){
- apow = strtol(pv, NULL, 10);
- } else if(!tcstricmp(elem, "fpow")){
- fpow = strtol(pv, NULL, 10);
- } else if(!tcstricmp(elem, "opts")){
- if(strchr(pv, 'l') || strchr(pv, 'L')) tlmode = true;
- if(strchr(pv, 'd') || strchr(pv, 'D')) tdmode = true;
- } else if(!tcstricmp(elem, "rcnum")){
- rcnum = strtol(pv, NULL, 10);
- } else if(!tcstricmp(elem, "lmemb")){
- lmemb = strtol(pv, NULL, 10);
- } else if(!tcstricmp(elem, "nmemb")){
- nmemb = strtol(pv, NULL, 10);
- } else if(!tcstricmp(elem, "lcnum")){
- lcnum = strtol(pv, NULL, 10);
- } else if(!tcstricmp(elem, "ncnum")){
- ncnum = strtol(pv, NULL, 10);
- }
- }
- tclistdel(elems);
- if(!tcstricmp(path, "*")){
- adb->mdb = bnum > 0 ? tcmdbnew2(bnum) : tcmdbnew();
- adb->capnum = capnum;
- adb->capsiz = capsiz;
- adb->capcnt = 0;
- } else if(tcstribwm(path, ".tch")){
- TCHDB *hdb = tchdbnew();
- tchdbsetmutex(hdb);
- int opts = 0;
- if(tlmode) opts |= HDBTLARGE;
- if(tdmode) opts |= HDBTDEFLATE;
- tchdbtune(hdb, bnum, apow, fpow, opts);
- tchdbsetcache(hdb, rcnum);
- int omode = owmode ? HDBOWRITER : HDBOREADER;
- if(ocmode) omode |= HDBOCREAT;
- if(otmode) omode |= HDBOTRUNC;
- if(onlmode) omode |= HDBONOLCK;
- if(onbmode) omode |= HDBOLCKNB;
- if(!tchdbopen(hdb, path, omode)){
- tchdbdel(hdb);
- free(path);
- return false;
- }
- adb->hdb = hdb;
- } else if(tcstribwm(path, ".tcb")){
- TCBDB *bdb = tcbdbnew();
- tcbdbsetmutex(bdb);
- int opts = 0;
- if(tlmode) opts |= BDBTLARGE;
- if(tdmode) opts |= BDBTDEFLATE;
- tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts);
- tcbdbsetcache(bdb, lcnum, ncnum);
- if(capnum > 0) tcbdbsetcapnum(bdb, capnum);
- int omode = owmode ? BDBOWRITER : BDBOREADER;
- if(ocmode) omode |= BDBOCREAT;
- if(otmode) omode |= BDBOTRUNC;
- if(onlmode) omode |= BDBONOLCK;
- if(onbmode) omode |= BDBOLCKNB;
- if(!tcbdbopen(bdb, path, omode)){
- tcbdbdel(bdb);
- free(path);
- return false;
- }
- adb->bdb = bdb;
- adb->cur = tcbdbcurnew(bdb);
- } else {
- free(path);
- return false;
- }
- free(path);
- adb->name = tcstrdup(name);
- return true;
-}
-
-
-/* Close an abstract database object. */
-bool tcadbclose(TCADB *adb){
- assert(adb);
- int err = false;
- if(!adb->name) return false;
- if(adb->mdb){
- tcmdbdel(adb->mdb);
- adb->mdb = NULL;
- } else if(adb->hdb){
- if(!tchdbclose(adb->hdb)) err = true;
- tchdbdel(adb->hdb);
- adb->hdb = NULL;
- } else if(adb->bdb){
- tcbdbcurdel(adb->cur);
- if(!tcbdbclose(adb->bdb)) err = true;
- tcbdbdel(adb->bdb);
- adb->bdb = NULL;
- }
- free(adb->name);
- adb->name = NULL;
- return !err;
-}
-
-
-/* Store a record into an abstract database object. */
-bool tcadbput(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(adb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- bool err = false;
- if(adb->mdb){
- tcmdbput(adb->mdb, kbuf, ksiz, vbuf, vsiz);
- if(adb->capnum > 0 || adb->capsiz > 0){
- adb->capcnt++;
- if((adb->capcnt & 0xff) == 0){
- if(adb->capnum > 0 && tcmdbrnum(adb->mdb) > adb->capnum) tcmdbcutfront(adb->mdb, 0x100);
- if(adb->capsiz > 0 && tcmdbmsiz(adb->mdb) > adb->capsiz) tcmdbcutfront(adb->mdb, 0x200);
- }
- }
- } else if(adb->hdb){
- if(!tchdbput(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
- } else if(adb->bdb){
- if(!tcbdbput(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
- } else {
- err = true;
- }
- return !err;
-}
-
-
-/* Store a string record into an abstract object. */
-bool tcadbput2(TCADB *adb, const char *kstr, const char *vstr){
- assert(adb && kstr && vstr);
- return tcadbput(adb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Store a new record into an abstract database object. */
-bool tcadbputkeep(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(adb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- bool err = false;
- if(adb->mdb){
- if(tcmdbputkeep(adb->mdb, kbuf, ksiz, vbuf, vsiz)){
- if(adb->capnum > 0 || adb->capsiz > 0){
- adb->capcnt++;
- if((adb->capcnt & 0xff) == 0){
- if(adb->capnum > 0 && tcmdbrnum(adb->mdb) > adb->capnum) tcmdbcutfront(adb->mdb, 0x100);
- if(adb->capsiz > 0 && tcmdbmsiz(adb->mdb) > adb->capsiz) tcmdbcutfront(adb->mdb, 0x200);
- }
- }
- } else {
- err = true;
- }
- } else if(adb->hdb){
- if(!tchdbputkeep(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
- } else if(adb->bdb){
- if(!tcbdbputkeep(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
- } else {
- err = true;
- }
- return !err;
-}
-
-
-/* Store a new string record into an abstract database object. */
-bool tcadbputkeep2(TCADB *adb, const char *kstr, const char *vstr){
- assert(adb && kstr && vstr);
- return tcadbputkeep(adb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Concatenate a value at the end of the existing record in an abstract database object. */
-bool tcadbputcat(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(adb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- bool err = false;
- if(adb->mdb){
- tcmdbputcat(adb->mdb, kbuf, ksiz, vbuf, vsiz);
- if(adb->capnum > 0 || adb->capsiz > 0){
- adb->capcnt++;
- if((adb->capcnt & 0xff) == 0){
- if(adb->capnum > 0 && tcmdbrnum(adb->mdb) > adb->capnum) tcmdbcutfront(adb->mdb, 0x100);
- if(adb->capsiz > 0 && tcmdbmsiz(adb->mdb) > adb->capsiz) tcmdbcutfront(adb->mdb, 0x200);
- }
- }
- } else if(adb->hdb){
- if(!tchdbputcat(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
- } else if(adb->bdb){
- if(!tcbdbputcat(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
- } else {
- err = true;
- }
- return !err;
-}
-
-
-/* Concatenate a string value at the end of the existing record in an abstract database object. */
-bool tcadbputcat2(TCADB *adb, const char *kstr, const char *vstr){
- assert(adb && kstr && vstr);
- return tcadbputcat(adb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Remove a record of an abstract database object. */
-bool tcadbout(TCADB *adb, const void *kbuf, int ksiz){
- assert(adb && kbuf && ksiz >= 0);
- bool err = false;
- if(adb->mdb){
- if(!tcmdbout(adb->mdb, kbuf, ksiz)) err = true;
- } else if(adb->hdb){
- if(!tchdbout(adb->hdb, kbuf, ksiz)) err = true;
- } else if(adb->bdb){
- if(!tcbdbout(adb->bdb, kbuf, ksiz)) err = true;
- } else {
- err = true;
- }
- return !err;
-}
-
-
-/* Remove a string record of an abstract database object. */
-bool tcadbout2(TCADB *adb, const char *kstr){
- assert(adb && kstr);
- return tcadbout(adb, kstr, strlen(kstr));
-}
-
-
-/* Retrieve a record in an abstract database object. */
-void *tcadbget(TCADB *adb, const void *kbuf, int ksiz, int *sp){
- assert(adb && kbuf && ksiz >= 0 && sp);
- char *rv;
- if(adb->mdb){
- rv = tcmdbget(adb->mdb, kbuf, ksiz, sp);
- } else if(adb->hdb){
- rv = tchdbget(adb->hdb, kbuf, ksiz, sp);
- } else if(adb->bdb){
- rv = tcbdbget(adb->bdb, kbuf, ksiz, sp);
- } else {
- rv = NULL;
- }
- return rv;
-}
-
-
-/* Retrieve a string record in an abstract database object. */
-char *tcadbget2(TCADB *adb, const char *kstr){
- assert(adb && kstr);
- int vsiz;
- return tcadbget(adb, kstr, strlen(kstr), &vsiz);
-}
-
-
-/* Get the size of the value of a record in an abstract database object. */
-int tcadbvsiz(TCADB *adb, const void *kbuf, int ksiz){
- assert(adb && kbuf && ksiz >= 0);
- int rv;
- if(adb->mdb){
- rv = tcmdbvsiz(adb->mdb, kbuf, ksiz);
- } else if(adb->hdb){
- rv = tchdbvsiz(adb->hdb, kbuf, ksiz);
- } else if(adb->bdb){
- rv = tcbdbvsiz(adb->bdb, kbuf, ksiz);
- } else {
- rv = -1;
- }
- return rv;
-}
-
-
-/* Get the size of the value of a string record in an abstract database object. */
-int tcadbvsiz2(TCADB *adb, const char *kstr){
- assert(adb && kstr);
- return tcadbvsiz(adb, kstr, strlen(kstr));
-}
-
-
-/* Initialize the iterator of an abstract database object. */
-bool tcadbiterinit(TCADB *adb){
- assert(adb);
- bool err = false;
- if(adb->mdb){
- tcmdbiterinit(adb->mdb);
- } else if(adb->hdb){
- if(!tchdbiterinit(adb->hdb)) err = true;
- } else if(adb->bdb){
- if(!tcbdbcurfirst(adb->cur)){
- int ecode = tcbdbecode(adb->bdb);
- if(ecode != TCESUCCESS && ecode != TCEINVALID && ecode != TCEKEEP && ecode != TCENOREC)
- err = true;
- }
- } else {
- err = true;
- }
- return !err;
-}
-
-
-/* Get the next key of the iterator of an abstract database object. */
-void *tcadbiternext(TCADB *adb, int *sp){
- assert(adb && sp);
- char *rv;
- if(adb->mdb){
- rv = tcmdbiternext(adb->mdb, sp);
- } else if(adb->hdb){
- rv = tchdbiternext(adb->hdb, sp);
- } else if(adb->bdb){
- rv = tcbdbcurkey(adb->cur, sp);
- tcbdbcurnext(adb->cur);
- } else {
- rv = NULL;
- }
- return rv;
-}
-
-
-/* Get the next key string of the iterator of an abstract database object. */
-char *tcadbiternext2(TCADB *adb){
- assert(adb);
- int vsiz;
- return tcadbiternext(adb, &vsiz);
-}
-
-
-/* Get forward matching keys in an abstract database object. */
-TCLIST *tcadbfwmkeys(TCADB *adb, const void *pbuf, int psiz, int max){
- assert(adb && pbuf && psiz >= 0);
- TCLIST *rv;
- if(adb->mdb){
- rv = tcmdbfwmkeys(adb->mdb, pbuf, psiz, max);
- } else if(adb->hdb){
- rv = tchdbfwmkeys(adb->hdb, pbuf, psiz, max);
- } else if(adb->bdb){
- rv = tcbdbfwmkeys(adb->bdb, pbuf, psiz, max);
- } else {
- rv = tclistnew();
- }
- return rv;
-}
-
-
-/* Get forward matching string keys in an abstract database object. */
-TCLIST *tcadbfwmkeys2(TCADB *adb, const char *pstr, int max){
- assert(adb && pstr);
- return tcadbfwmkeys(adb, pstr, strlen(pstr), max);
-}
-
-
-/* Synchronize updated contents of an abstract database object with the file and the device. */
-bool tcadbsync(TCADB *adb){
- assert(adb);
- bool err = false;
- if(adb->mdb){
- err = true;
- } else if(adb->hdb){
- if(!tchdbsync(adb->hdb)) err = true;
- } else if(adb->bdb){
- if(!tcbdbsync(adb->bdb)) err = true;
- } else {
- err = true;
- }
- return !err;
-}
-
-
-/* Remove all records of an abstract database object. */
-bool tcadbvanish(TCADB *adb){
- assert(adb);
- bool err = false;
- if(adb->mdb){
- tcmdbvanish(adb->mdb);
- } else if(adb->hdb){
- if(!tchdbvanish(adb->hdb)) err = true;
- } else if(adb->bdb){
- if(!tcbdbvanish(adb->bdb)) err = true;
- } else {
- err = true;
- }
- return !err;
-}
-
-
-/* Copy the database file of an abstract database object. */
-bool tcadbcopy(TCADB *adb, const char *path){
- assert(adb && path);
- bool err = false;
- if(adb->mdb){
- err = true;
- } else if(adb->hdb){
- if(!tchdbcopy(adb->hdb, path)) err = true;
- } else if(adb->bdb){
- if(!tcbdbcopy(adb->bdb, path)) err = true;
- } else {
- err = true;
- }
- return !err;
-}
-
-
-/* Get the number of records of an abstract database object. */
-uint64_t tcadbrnum(TCADB *adb){
- assert(adb);
- uint64_t rv;
- if(adb->mdb){
- rv = tcmdbrnum(adb->mdb);
- } else if(adb->hdb){
- rv = tchdbrnum(adb->hdb);
- } else if(adb->bdb){
- rv = tcbdbrnum(adb->bdb);
- } else {
- rv = 0;
- }
- return rv;
-}
-
-
-/* Get the size of the database of an abstract database object. */
-uint64_t tcadbsize(TCADB *adb){
- assert(adb);
- uint64_t rv;
- if(adb->mdb){
- rv = tcmdbmsiz(adb->mdb);
- } else if(adb->hdb){
- rv = tchdbfsiz(adb->hdb);
- } else if(adb->bdb){
- rv = tcbdbfsiz(adb->bdb);
- } else {
- rv = 0;
- }
- return rv;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The abstract database API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#ifndef _TCADB_H /* duplication check */
-#define _TCADB_H
-
-#if defined(__cplusplus)
-#define __TCADB_CLINKAGEBEGIN extern "C" {
-#define __TCADB_CLINKAGEEND }
-#else
-#define __TCADB_CLINKAGEBEGIN
-#define __TCADB_CLINKAGEEND
-#endif
-__TCADB_CLINKAGEBEGIN
-
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <time.h>
-#include <tcutil.h>
-#include <tchdb.h>
-#include <tcbdb.h>
-
-
-
-/*************************************************************************************************
- * API
- *************************************************************************************************/
-
-
-typedef struct { /* type of structure for an abstract database */
- char *name; /* name of the database */
- TCMDB *mdb; /* on-memory database object */
- TCHDB *hdb; /* hash database object */
- TCBDB *bdb; /* B+ tree database object */
- int64_t capnum; /* capacity number of records */
- int64_t capsiz; /* capacity size of using memory */
- uint32_t capcnt; /* count for capacity check */
- BDBCUR *cur; /* cursor of B+ tree */
-} TCADB;
-
-
-/* Create an abstract database object.
- The return value is the new abstract database object. */
-TCADB *tcadbnew(void);
-
-
-/* Delete an abstract database object.
- `adb' specifies the abstract database object. */
-void tcadbdel(TCADB *adb);
-
-
-/* Open an abstract database.
- `adb' specifies the abstract database object.
- `name' specifies the name of the database. If it is "*", the database will be an on-memory
- database. If its suffix is ".tch", the database will be a hash database. If its suffix is
- ".tcb", the database will be a B+ tree database. Otherwise, this function fails. Tuning
- parameters can trail the name, separated by "#". Each parameter is composed of the name and
- the number, separated by "=". On-memory database supports "bnum", "capnum", and "capsiz".
- Hash database supports "mode", "bnum", "apow", "fpow", "opts", and "rcnum". B+ tree database
- supports "mode", "lmemb", "nmemb", "bnum", "apow", "fpow", "opts", "lcnum", and "ncnum".
- "capnum" specifies the capacity number of records. "capsiz" specifies the capacity size of
- using memory. Records spilled the capacity are removed by the storing order. "mode" can
- contain "w" of writer, "r" of reader, "c" of creating, "t" of truncating, "e" of no locking,
- and "f" of non-blocking lock. The default mode is relevant to "wc". "opts" can contains "l"
- of large option, "d" of Deflate option, and "b" of TCBS option. For example,
- "casket.tch#bnum=1000000#opts=ld" means that the name of the database file is "casket.tch",
- and the bucket number is 1000000, and the options are large and Deflate.
- If successful, the return value is true, else, it is false. */
-bool tcadbopen(TCADB *adb, const char *name);
-
-
-/* Close an abstract database object.
- `adb' specifies the abstract database object.
- If successful, the return value is true, else, it is false.
- Update of a database is assured to be written when the database is closed. If a writer opens
- a database but does not close it appropriately, the database will be broken. */
-bool tcadbclose(TCADB *adb);
-
-
-/* Store a record into an abstract database object.
- `adb' specifies the abstract database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, it is overwritten. */
-bool tcadbput(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a string record into an abstract object.
- `adb' specifies the abstract database object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, it is overwritten. */
-bool tcadbput2(TCADB *adb, const char *kstr, const char *vstr);
-
-
-/* Store a new record into an abstract database object.
- `adb' specifies the abstract database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tcadbputkeep(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a new string record into an abstract database object.
- `adb' specifies the abstract database object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tcadbputkeep2(TCADB *adb, const char *kstr, const char *vstr);
-
-
-/* Concatenate a value at the end of the existing record in an abstract database object.
- `adb' specifies the abstract database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If there is no corresponding record, a new record is created. */
-bool tcadbputcat(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Concatenate a string value at the end of the existing record in an abstract database object.
- `adb' specifies the abstract database object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If there is no corresponding record, a new record is created. */
-bool tcadbputcat2(TCADB *adb, const char *kstr, const char *vstr);
-
-
-/* Remove a record of an abstract database object.
- `adb' specifies the abstract database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false. */
-bool tcadbout(TCADB *adb, const void *kbuf, int ksiz);
-
-
-/* Remove a string record of an abstract database object.
- `adb' specifies the abstract database object.
- `kstr' specifies the string of the key.
- If successful, the return value is true, else, it is false. */
-bool tcadbout2(TCADB *adb, const char *kstr);
-
-
-/* Retrieve a record in an abstract database object.
- `adb' specifies the abstract database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the corresponding
- record. `NULL' is returned if no record corresponds.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-void *tcadbget(TCADB *adb, const void *kbuf, int ksiz, int *sp);
-
-
-/* Retrieve a string record in an abstract database object.
- `adb' specifies the abstract database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the string of the value of the corresponding record.
- `NULL' is returned if no record corresponds.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcadbget2(TCADB *adb, const char *kstr);
-
-
-/* Get the size of the value of a record in an abstract database object.
- `adb' specifies the abstract database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1. */
-int tcadbvsiz(TCADB *adb, const void *kbuf, int ksiz);
-
-
-/* Get the size of the value of a string record in an abstract database object.
- `adb' specifies the abstract database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1. */
-int tcadbvsiz2(TCADB *adb, const char *kstr);
-
-
-/* Initialize the iterator of an abstract database object.
- `adb' specifies the abstract database object.
- If successful, the return value is true, else, it is false.
- The iterator is used in order to access the key of every record stored in a database. */
-bool tcadbiterinit(TCADB *adb);
-
-
-/* Get the next key of the iterator of an abstract database object.
- `adb' specifies the abstract database object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the next key, else, it is
- `NULL'. `NULL' is returned when no record is to be get out of the iterator.
- Because an additional zero code is appended at the end of the region of the return value, the
- return value can be treated as a character string. Because the region of the return value is
- allocated with the `malloc' call, it should be released with the `free' call when it is no
- longer in use. It is possible to access every record by iteration of calling this function.
- It is allowed to update or remove records whose keys are fetched while the iteration.
- However, it is not assured if updating the database is occurred while the iteration. Besides,
- the order of this traversal access method is arbitrary, so it is not assured that the order of
- storing matches the one of the traversal access. */
-void *tcadbiternext(TCADB *adb, int *sp);
-
-
-/* Get the next key string of the iterator of an abstract database object.
- `adb' specifies the abstract database object.
- If successful, the return value is the string of the next key, else, it is `NULL'. `NULL' is
- returned when no record is to be get out of the iterator.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. It is possible to access every
- record by iteration of calling this function. However, it is not assured if updating the
- database is occurred while the iteration. Besides, the order of this traversal access method
- is arbitrary, so it is not assured that the order of storing matches the one of the traversal
- access. */
-char *tcadbiternext2(TCADB *adb);
-
-
-/* Get forward matching keys in an abstract database object.
- `adb' specifies the abstract database object.
- `pbuf' specifies the pointer to the region of the prefix.
- `psiz' specifies the size of the region of the prefix.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the corresponding keys. This function does never fail
- and return an empty list even if no key corresponds.
- Because the object of the return value is created with the function `tclistnew', it should be
- deleted with the function `tclistdel' when it is no longer in use. Note that this function
- may be very slow because every key in the database is scanned. */
-TCLIST *tcadbfwmkeys(TCADB *adb, const void *pbuf, int psiz, int max);
-
-
-/* Get forward matching string keys in an abstract database object.
- `adb' specifies the abstract database object.
- `pstr' specifies the string of the prefix.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the corresponding keys. This function does never fail
- and return an empty list even if no key corresponds.
- Because the object of the return value is created with the function `tclistnew', it should be
- deleted with the function `tclistdel' when it is no longer in use. Note that this function
- may be very slow because every key in the database is scanned. */
-TCLIST *tcadbfwmkeys2(TCADB *adb, const char *pstr, int max);
-
-
-/* Synchronize updated contents of an abstract database object with the file and the device.
- `adb' specifies the abstract database object.
- If successful, the return value is true, else, it is false.
- This function fails and has no effect for on-memory database. */
-bool tcadbsync(TCADB *adb);
-
-
-/* Remove all records of an abstract database object.
- `adb' specifies the abstract database object.
- If successful, the return value is true, else, it is false. */
-bool tcadbvanish(TCADB *adb);
-
-
-/* Copy the database file of an abstract database object.
- `adb' specifies the abstract database object.
- `path' specifies the path of the destination file. If it begins with `@', the trailing
- substring is executed as a command line.
- If successful, the return value is true, else, it is false. False is returned if the executed
- command returns non-zero code.
- The database file is assured to be kept synchronized and not modified while the copying or
- executing operation is in progress. So, this function is useful to create a backup file of
- the database file. This function fails and has no effect for on-memory database. */
-bool tcadbcopy(TCADB *adb, const char *path);
-
-
-/* Get the number of records of an abstract database object.
- `adb' specifies the abstract database object.
- The return value is the number of records or 0 if the object does not connect to any database
- instance. */
-uint64_t tcadbrnum(TCADB *adb);
-
-
-/* Get the size of the database of an abstract database object.
- `adb' specifies the abstract database object.
- The return value is the size of the database or 0 if the object does not connect to any
- database instance. */
-uint64_t tcadbsize(TCADB *adb);
-
-
-
-__TCADB_CLINKAGEEND
-#endif /* duplication check */
-
-
-/* END OF FILE */
+++ /dev/null
-/*************************************************************************************************
- * The command line utility of the abstract database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include <tcadb.h>
-#include "myconf.h"
-
-
-/* global variables */
-const char *g_progname; // program name
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void printerr(TCADB *adb);
-static int printdata(const char *ptr, int size, bool px);
-static char *hextoobj(const char *str, int *sp);
-static int runcreate(int argc, char **argv);
-static int runinform(int argc, char **argv);
-static int runput(int argc, char **argv);
-static int runout(int argc, char **argv);
-static int runget(int argc, char **argv);
-static int runlist(int argc, char **argv);
-static int runversion(int argc, char **argv);
-static int proccreate(const char *name);
-static int procinform(const char *name);
-static int procput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- int dmode);
-static int procout(const char *name, const char *kbuf, int ksiz);
-static int procget(const char *name, const char *kbuf, int ksiz, bool px, bool pz);
-static int proclist(const char *name, int max, bool pv, bool px, const char *fmstr);
-static int procversion(void);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "create")){
- rv = runcreate(argc, argv);
- } else if(!strcmp(argv[1], "inform")){
- rv = runinform(argc, argv);
- } else if(!strcmp(argv[1], "put")){
- rv = runput(argc, argv);
- } else if(!strcmp(argv[1], "out")){
- rv = runout(argc, argv);
- } else if(!strcmp(argv[1], "get")){
- rv = runget(argc, argv);
- } else if(!strcmp(argv[1], "list")){
- rv = runlist(argc, argv);
- } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){
- rv = runversion(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: the command line utility of the abstract database API\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s create name\n", g_progname);
- fprintf(stderr, " %s inform name\n", g_progname);
- fprintf(stderr, " %s put [-sx] [-dk|-dc] name key value\n", g_progname);
- fprintf(stderr, " %s out [-sx] name key\n", g_progname);
- fprintf(stderr, " %s get [-sx] [-px] [-pz] name key\n", g_progname);
- fprintf(stderr, " %s list [-m num] [-pv] [-px] [-fm str] name\n", g_progname);
- fprintf(stderr, " %s version\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print error information */
-static void printerr(TCADB *adb){
- fprintf(stderr, "%s: error\n", g_progname);
-}
-
-
-/* print record data */
-static int printdata(const char *ptr, int size, bool px){
- int len = 0;
- while(size-- > 0){
- if(px){
- if(len > 0) putchar(' ');
- len += printf("%02X", *(unsigned char *)ptr);
- } else {
- putchar(*ptr);
- len++;
- }
- ptr++;
- }
- return len;
-}
-
-
-/* create a binary object from a hexadecimal string */
-static char *hextoobj(const char *str, int *sp){
- int len = strlen(str);
- char *buf = tcmalloc(len + 1);
- int j = 0;
- for(int i = 0; i < len; i += 2){
- while(strchr(" \n\r\t\f\v", str[i])){
- i++;
- }
- char mbuf[3];
- if((mbuf[0] = str[i]) == '\0') break;
- if((mbuf[1] = str[i+1]) == '\0') break;
- mbuf[2] = '\0';
- buf[j++] = (char)strtol(mbuf, NULL, 16);
- }
- buf[j] = '\0';
- *sp = j;
- return buf;
-}
-
-
-/* parse arguments of create command */
-static int runcreate(int argc, char **argv){
- char *name = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- usage();
- } else if(!name){
- name = argv[i];
- } else {
- usage();
- }
- }
- if(!name) usage();
- int rv = proccreate(name);
- return rv;
-}
-
-
-/* parse arguments of inform command */
-static int runinform(int argc, char **argv){
- char *name = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- usage();
- } else if(!name){
- name = argv[i];
- } else {
- usage();
- }
- }
- if(!name) usage();
- name = tcsprintf("%s#mode=r", name);
- int rv = procinform(name);
- free(name);
- return rv;
-}
-
-
-/* parse arguments of put command */
-static int runput(int argc, char **argv){
- char *name = NULL;
- char *key = NULL;
- char *value = NULL;
- int dmode = 0;
- bool sx = false;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-dk")){
- dmode = -1;
- } else if(!strcmp(argv[i], "-dc")){
- dmode = 1;
- } else if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else {
- usage();
- }
- } else if(!name){
- name = argv[i];
- } else if(!key){
- key = argv[i];
- } else if(!value){
- value = argv[i];
- } else {
- usage();
- }
- }
- if(!name || !key || !value) usage();
- int ksiz, vsiz;
- char *kbuf, *vbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- vbuf = hextoobj(value, &vsiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- vsiz = strlen(value);
- vbuf = tcmemdup(value, vsiz);
- }
- int rv = procput(name, kbuf, ksiz, vbuf, vsiz, dmode);
- free(vbuf);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of out command */
-static int runout(int argc, char **argv){
- char *name = NULL;
- char *key = NULL;
- bool sx = false;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else {
- usage();
- }
- } else if(!name){
- name = argv[i];
- } else if(!key){
- key = argv[i];
- } else {
- usage();
- }
- }
- if(!name || !key) usage();
- int ksiz;
- char *kbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- }
- int rv = procout(name, kbuf, ksiz);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of get command */
-static int runget(int argc, char **argv){
- char *name = NULL;
- char *key = NULL;
- bool sx = false;
- bool px = false;
- bool pz = false;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else if(!strcmp(argv[i], "-px")){
- px = true;
- } else if(!strcmp(argv[i], "-pz")){
- pz = true;
- } else {
- usage();
- }
- } else if(!name){
- name = argv[i];
- } else if(!key){
- key = argv[i];
- } else {
- usage();
- }
- }
- if(!name || !key) usage();
- int ksiz;
- char *kbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- }
- name = tcsprintf("%s#mode=r", name);
- int rv = procget(name, kbuf, ksiz, px, pz);
- free(name);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of list command */
-static int runlist(int argc, char **argv){
- char *name = NULL;
- int max = -1;
- bool pv = false;
- bool px = false;
- char *fmstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-m")){
- if(++i >= argc) usage();
- max = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-pv")){
- pv = true;
- } else if(!strcmp(argv[i], "-px")){
- px = true;
- } else if(!strcmp(argv[i], "-fm")){
- if(++i >= argc) usage();
- fmstr = argv[i];
- } else {
- usage();
- }
- } else if(!name){
- name = argv[i];
- } else {
- usage();
- }
- }
- if(!name) usage();
- name = tcsprintf("%s#mode=r", name);
- int rv = proclist(name, max, pv, px, fmstr);
- free(name);
- return rv;
-}
-
-
-/* parse arguments of version command */
-static int runversion(int argc, char **argv){
- int rv = procversion();
- return rv;
-}
-
-
-/* perform create command */
-static int proccreate(const char *name){
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- printerr(adb);
- tcadbdel(adb);
- return 1;
- }
- bool err = false;
- if(!tcadbclose(adb)){
- printerr(adb);
- err = true;
- }
- tcadbdel(adb);
- return err ? 1 : 0;
-}
-
-
-/* perform inform command */
-static int procinform(const char *name){
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- printerr(adb);
- tcadbdel(adb);
- return 1;
- }
- bool err = false;
- printf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
- printf("size: %llu\n", (unsigned long long)tcadbsize(adb));
- if(!tcadbclose(adb)){
- printerr(adb);
- err = true;
- }
- tcadbdel(adb);
- return err ? 1 : 0;
-}
-
-
-/* perform put command */
-static int procput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- int dmode){
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- printerr(adb);
- tcadbdel(adb);
- return 1;
- }
- bool err = false;
- switch(dmode){
- case -1:
- if(!tcadbputkeep(adb, kbuf, ksiz, vbuf, vsiz)){
- printerr(adb);
- err = true;
- }
- break;
- case 1:
- if(!tcadbputcat(adb, kbuf, ksiz, vbuf, vsiz)){
- printerr(adb);
- err = true;
- }
- break;
- default:
- if(!tcadbput(adb, kbuf, ksiz, vbuf, vsiz)){
- printerr(adb);
- err = true;
- }
- break;
- }
- if(!tcadbclose(adb)){
- if(!err) printerr(adb);
- err = true;
- }
- tcadbdel(adb);
- return err ? 1 : 0;
-}
-
-
-/* perform out command */
-static int procout(const char *name, const char *kbuf, int ksiz){
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- printerr(adb);
- tcadbdel(adb);
- return 1;
- }
- bool err = false;
- if(!tcadbout(adb, kbuf, ksiz)){
- printerr(adb);
- err = true;
- }
- if(!tcadbclose(adb)){
- if(!err) printerr(adb);
- err = true;
- }
- tcadbdel(adb);
- return err ? 1 : 0;
-}
-
-
-/* perform get command */
-static int procget(const char *name, const char *kbuf, int ksiz, bool px, bool pz){
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- printerr(adb);
- tcadbdel(adb);
- return 1;
- }
- bool err = false;
- int vsiz;
- char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
- if(vbuf){
- printdata(vbuf, vsiz, px);
- if(!pz) putchar('\n');
- free(vbuf);
- } else {
- printerr(adb);
- err = true;
- }
- if(!tcadbclose(adb)){
- if(!err) printerr(adb);
- err = true;
- }
- tcadbdel(adb);
- return err ? 1 : 0;
-}
-
-
-/* perform list command */
-static int proclist(const char *name, int max, bool pv, bool px, const char *fmstr){
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- printerr(adb);
- tcadbdel(adb);
- return 1;
- }
- bool err = false;
- if(fmstr){
- TCLIST *keys = tcadbfwmkeys2(adb, fmstr, max);
- for(int i = 0; i < tclistnum(keys); i++){
- int ksiz;
- const char *kbuf = tclistval(keys, i, &ksiz);
- printdata(kbuf, ksiz, px);
- if(pv){
- int vsiz;
- char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
- if(vbuf){
- putchar('\t');
- printdata(vbuf, vsiz, px);
- free(vbuf);
- }
- }
- putchar('\n');
- }
- tclistdel(keys);
- } else {
- if(!tcadbiterinit(adb)){
- printerr(adb);
- err = true;
- }
- int ksiz;
- char *kbuf;
- int cnt = 0;
- while((kbuf = tcadbiternext(adb, &ksiz)) != NULL){
- printdata(kbuf, ksiz, px);
- if(pv){
- int vsiz;
- char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
- if(vbuf){
- putchar('\t');
- printdata(vbuf, vsiz, px);
- free(vbuf);
- }
- }
- putchar('\n');
- free(kbuf);
- if(max >= 0 && ++cnt >= max) break;
- }
- }
- if(!tcadbclose(adb)){
- if(!err) printerr(adb);
- err = true;
- }
- tcadbdel(adb);
- return err ? 1 : 0;
-}
-
-
-/* perform version command */
-static int procversion(void){
- printf("Tokyo Cabinet version %s (%d:%s)\n", tcversion, _TC_LIBVER, _TC_FORMATVER);
- printf("Copyright (C) 2006-2008 Mikio Hirabayashi\n");
- return 0;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The test cases of the abstract database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include <tcadb.h>
-#include "myconf.h"
-
-#define RECBUFSIZ 32 // buffer for records
-
-
-/* global variables */
-const char *g_progname; // program name
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void iprintf(const char *format, ...);
-static void eprint(TCADB *adb, const char *func);
-static int myrand(int range);
-static int runwrite(int argc, char **argv);
-static int runread(int argc, char **argv);
-static int runremove(int argc, char **argv);
-static int runrcat(int argc, char **argv);
-static int runmisc(int argc, char **argv);
-static int runwicked(int argc, char **argv);
-static int procwrite(const char *name, int rnum);
-static int procread(const char *name);
-static int procremove(const char *name);
-static int procrcat(const char *name, int rnum);
-static int procmisc(const char *name, int rnum);
-static int procwicked(const char *name, int rnum);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "write")){
- rv = runwrite(argc, argv);
- } else if(!strcmp(argv[1], "read")){
- rv = runread(argc, argv);
- } else if(!strcmp(argv[1], "remove")){
- rv = runremove(argc, argv);
- } else if(!strcmp(argv[1], "rcat")){
- rv = runrcat(argc, argv);
- } else if(!strcmp(argv[1], "misc")){
- rv = runmisc(argc, argv);
- } else if(!strcmp(argv[1], "wicked")){
- rv = runwicked(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: test cases of the abstract database API of Tokyo Cabinet\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s write name rnum\n", g_progname);
- fprintf(stderr, " %s read name\n", g_progname);
- fprintf(stderr, " %s remove name\n", g_progname);
- fprintf(stderr, " %s rcat name rnum\n", g_progname);
- fprintf(stderr, " %s misc name rnum\n", g_progname);
- fprintf(stderr, " %s wicked name rnum\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print formatted information string and flush the buffer */
-static void iprintf(const char *format, ...){
- va_list ap;
- va_start(ap, format);
- vprintf(format, ap);
- fflush(stdout);
- va_end(ap);
-}
-
-
-/* print error message of abstract database */
-static void eprint(TCADB *adb, const char *func){
- fprintf(stderr, "%s: %s: error\n", g_progname, func);
-}
-
-
-/* get a random number */
-static int myrand(int range){
- return (int)((double)range * rand() / (RAND_MAX + 1.0));
-}
-
-
-/* parse arguments of write command */
-static int runwrite(int argc, char **argv){
- char *name = NULL;
- char *rstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- usage();
- } else if(!name){
- name = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!name || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procwrite(name, rnum);
- return rv;
-}
-
-
-/* parse arguments of read command */
-static int runread(int argc, char **argv){
- char *name = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- usage();
- } else if(!name){
- name = argv[i];
- } else {
- usage();
- }
- }
- if(!name) usage();
- int rv = procread(name);
- return rv;
-}
-
-
-/* parse arguments of remove command */
-static int runremove(int argc, char **argv){
- char *name = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- usage();
- } else if(!name){
- name = argv[i];
- } else {
- usage();
- }
- }
- if(!name) usage();
- int rv = procremove(name);
- return rv;
-}
-
-
-/* parse arguments of rcat command */
-static int runrcat(int argc, char **argv){
- char *name = NULL;
- char *rstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- usage();
- } else if(!name){
- name = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!name || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procrcat(name, rnum);
- return rv;
-}
-
-
-/* parse arguments of misc command */
-static int runmisc(int argc, char **argv){
- char *name = NULL;
- char *rstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- usage();
- } else if(!name){
- name = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!name || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procmisc(name, rnum);
- return rv;
-}
-
-
-/* parse arguments of wicked command */
-static int runwicked(int argc, char **argv){
- char *name = NULL;
- char *rstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!name && argv[i][0] == '-'){
- usage();
- } else if(!name){
- name = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!name || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procwicked(name, rnum);
- return rv;
-}
-
-
-/* perform write command */
-static int procwrite(const char *name, int rnum){
- iprintf("<Writing Test>\n name=%s rnum=%d\n\n", name, rnum);
- bool err = false;
- double stime = tctime();
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- eprint(adb, "tcadbopen");
- err = true;
- }
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- if(!tcadbput(adb, buf, len, buf, len)){
- eprint(adb, "tcadbput");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
- iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
- if(!tcadbclose(adb)){
- eprint(adb, "tcadbclose");
- err = true;
- }
- tcadbdel(adb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform read command */
-static int procread(const char *name){
- iprintf("<Reading Test>\n name=%s\n\n", name);
- bool err = false;
- double stime = tctime();
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- eprint(adb, "tcadbopen");
- err = true;
- }
- int rnum = tcadbrnum(adb);
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- int vsiz;
- char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(adb, "tcadbget");
- err = true;
- break;
- }
- free(vbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
- iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
- if(!tcadbclose(adb)){
- eprint(adb, "tcadbclose");
- err = true;
- }
- tcadbdel(adb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform remove command */
-static int procremove(const char *name){
- iprintf("<Removing Test>\n name=%s\n\n", name);
- bool err = false;
- double stime = tctime();
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- eprint(adb, "tcadbopen");
- err = true;
- }
- int rnum = tcadbrnum(adb);
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- if(!tcadbout(adb, kbuf, ksiz)){
- eprint(adb, "tcadbout");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
- iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
- if(!tcadbclose(adb)){
- eprint(adb, "tcadbclose");
- err = true;
- }
- tcadbdel(adb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform rcat command */
-static int procrcat(const char *name, int rnum){
- iprintf("<Random Concatenating Test>\n name=%s rnum=%d\n\n", name, rnum);
- int pnum = rnum / 5 + 1;
- bool err = false;
- double stime = tctime();
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- eprint(adb, "tcadbopen");
- err = true;
- }
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(pnum));
- if(!tcadbputcat(adb, kbuf, ksiz, kbuf, ksiz)){
- eprint(adb, "tcadbputcat");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
- iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
- if(!tcadbclose(adb)){
- eprint(adb, "tcadbclose");
- err = true;
- }
- tcadbdel(adb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform misc command */
-static int procmisc(const char *name, int rnum){
- iprintf("<Random Concatenating Test>\n name=%s rnum=%d\n\n", name, rnum);
- bool err = false;
- double stime = tctime();
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- eprint(adb, "tcadbopen");
- err = true;
- }
- iprintf("writing:\n");
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- if(!tcadbputkeep(adb, buf, len, buf, len)){
- eprint(adb, "tcadbputkeep");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("reading:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- int vsiz;
- char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(adb, "tcadbget");
- err = true;
- break;
- } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
- eprint(adb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- free(vbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(tcadbrnum(adb) != rnum){
- eprint(adb, "(validation)");
- err = true;
- }
- iprintf("random writing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '*', vsiz);
- if(!tcadbput(adb, kbuf, ksiz, vbuf, vsiz)){
- eprint(adb, "tcadbput");
- err = true;
- break;
- }
- int rsiz;
- char *rbuf = tcadbget(adb, kbuf, ksiz, &rsiz);
- if(!rbuf){
- eprint(adb, "tcadbget");
- err = true;
- break;
- }
- if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(adb, "(validation)");
- err = true;
- free(rbuf);
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- free(rbuf);
- }
- iprintf("word writing:\n");
- const char *words[] = {
- "a", "A", "bb", "BB", "ccc", "CCC", "dddd", "DDDD", "eeeee", "EEEEEE",
- "mikio", "hirabayashi", "tokyo", "cabinet", "hyper", "estraier", "19780211", "birth day",
- "one", "first", "two", "second", "three", "third", "four", "fourth", "five", "fifth",
- "_[1]_", "uno", "_[2]_", "dos", "_[3]_", "tres", "_[4]_", "cuatro", "_[5]_", "cinco",
- "[\xe5\xb9\xb3\xe6\x9e\x97\xe5\xb9\xb9\xe9\x9b\x84]", "[\xe9\xa6\xac\xe9\xb9\xbf]", NULL
- };
- for(int i = 0; words[i] != NULL; i += 2){
- const char *kbuf = words[i];
- int ksiz = strlen(kbuf);
- const char *vbuf = words[i+1];
- int vsiz = strlen(vbuf);
- if(!tcadbputkeep(adb, kbuf, ksiz, vbuf, vsiz)){
- eprint(adb, "tcadbputkeep");
- err = true;
- break;
- }
- if(rnum > 250) putchar('.');
- }
- if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
- iprintf("random erasing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- tcadbout(adb, kbuf, ksiz);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("writing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "[%d]", i);
- char vbuf[RECBUFSIZ];
- int vsiz = i % RECBUFSIZ;
- memset(vbuf, '*', vsiz);
- if(!tcadbputkeep(adb, kbuf, ksiz, vbuf, vsiz)){
- eprint(adb, "tcadbputkeep");
- err = true;
- break;
- }
- if(vsiz < 1){
- char tbuf[PATH_MAX];
- for(int j = 0; j < PATH_MAX; j++){
- tbuf[j] = myrand(0x100);
- }
- if(!tcadbput(adb, kbuf, ksiz, tbuf, PATH_MAX)){
- eprint(adb, "tcadbput");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("erasing:\n");
- for(int i = 1; i <= rnum; i++){
- if(i % 2 == 1){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "[%d]", i);
- if(!tcadbout(adb, kbuf, ksiz)){
- eprint(adb, "tcadbout");
- err = true;
- break;
- }
- tcadbout(adb, kbuf, ksiz);
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("iterator checking:\n");
- if(!tcadbiterinit(adb)){
- eprint(adb, "tcadbiterinit");
- err = true;
- }
- char *kbuf;
- int ksiz;
- int inum = 0;
- for(int i = 1; (kbuf = tcadbiternext(adb, &ksiz)) != NULL; i++, inum++){
- int vsiz;
- char *vbuf = tcadbget(adb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(adb, "tcadbget");
- err = true;
- free(kbuf);
- break;
- }
- free(vbuf);
- free(kbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(rnum > 250) iprintf(" (%08d)\n", inum);
- if(inum != tcadbrnum(adb)){
- eprint(adb, "(validation)");
- err = true;
- }
- if(*name != '*' && !tcadbsync(adb)){
- eprint(adb, "tcadbsync");
- err = true;
- }
- if(!tcadbvanish(adb)){
- eprint(adb, "tcadbsync");
- err = true;
- }
- iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
- iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
- if(!tcadbclose(adb)){
- eprint(adb, "tcadbclose");
- err = true;
- }
- tcadbdel(adb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform wicked command */
-static int procwicked(const char *name, int rnum){
- iprintf("<Wicked Writing Test>\n name=%s rnum=%d\n\n", name, rnum);
- bool err = false;
- double stime = tctime();
- TCADB *adb = tcadbnew();
- if(!tcadbopen(adb, name)){
- eprint(adb, "tcadbopen");
- err = true;
- }
- TCMAP *map = tcmapnew2(rnum / 5);
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '*', vsiz);
- vbuf[vsiz] = '\0';
- char *rbuf;
- switch(myrand(16)){
- case 0:
- putchar('0');
- if(!tcadbput(adb, kbuf, ksiz, vbuf, vsiz)){
- eprint(adb, "tcadbput");
- err = true;
- }
- tcmapput(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 1:
- putchar('1');
- if(!tcadbput2(adb, kbuf, vbuf)){
- eprint(adb, "tcadbput2");
- err = true;
- }
- tcmapput2(map, kbuf, vbuf);
- break;
- case 2:
- putchar('2');
- tcadbputkeep(adb, kbuf, ksiz, vbuf, vsiz);
- tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 3:
- putchar('3');
- tcadbputkeep2(adb, kbuf, vbuf);
- tcmapputkeep2(map, kbuf, vbuf);
- break;
- case 4:
- putchar('4');
- if(!tcadbputcat(adb, kbuf, ksiz, vbuf, vsiz)){
- eprint(adb, "tcadbputcat");
- err = true;
- }
- tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 5:
- putchar('5');
- if(!tcadbputcat2(adb, kbuf, vbuf)){
- eprint(adb, "tcadbputcat2");
- err = true;
- }
- tcmapputcat2(map, kbuf, vbuf);
- break;
- case 6:
- putchar('6');
- if(myrand(10) == 0){
- tcadbout(adb, kbuf, ksiz);
- tcmapout(map, kbuf, ksiz);
- }
- break;
- case 7:
- putchar('7');
- if(myrand(10) == 0){
- tcadbout2(adb, kbuf);
- tcmapout2(map, kbuf);
- }
- break;
- case 8:
- putchar('8');
- if((rbuf = tcadbget(adb, kbuf, ksiz, &vsiz)) != NULL) free(rbuf);
- break;
- case 9:
- putchar('9');
- if((rbuf = tcadbget2(adb, kbuf)) != NULL) free(rbuf);
- break;
- case 10:
- putchar('A');
- tcadbvsiz(adb, kbuf, ksiz);
- break;
- case 11:
- putchar('B');
- tcadbvsiz2(adb, kbuf);
- break;
- case 12:
- putchar('E');
- if(myrand(rnum / 50) == 0){
- if(!tcadbiterinit(adb)){
- eprint(adb, "tcadbiterinit");
- err = true;
- }
- }
- for(int j = myrand(rnum) / 1000 + 1; j >= 0; j--){
- int iksiz;
- char *ikbuf = tcadbiternext(adb, &iksiz);
- if(ikbuf) free(ikbuf);
- }
- break;
- default:
- putchar('@');
- if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- break;
- }
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- tcadbsync(adb);
- if(tcadbrnum(adb) != tcmaprnum(map)){
- eprint(adb, "(validation)");
- err = true;
- }
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", i - 1);
- int vsiz;
- const char *vbuf = tcmapget(map, kbuf, ksiz, &vsiz);
- int rsiz;
- char *rbuf = tcadbget(adb, kbuf, ksiz, &rsiz);
- if(vbuf){
- putchar('.');
- if(!rbuf){
- eprint(adb, "tcadbget");
- err = true;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(adb, "(validation)");
- err = true;
- }
- } else {
- putchar('*');
- if(rbuf){
- eprint(adb, "(validation)");
- err = true;
- }
- }
- free(rbuf);
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- tcmapiterinit(map);
- int ksiz;
- const char *kbuf;
- for(int i = 1; (kbuf = tcmapiternext(map, &ksiz)) != NULL; i++){
- putchar('+');
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- int rsiz;
- char *rbuf = tcadbget(adb, kbuf, ksiz, &rsiz);
- if(!rbuf){
- eprint(adb, "tcadbget");
- err = true;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(adb, "(validation)");
- err = true;
- }
- free(rbuf);
- if(!tcadbout(adb, kbuf, ksiz)){
- eprint(adb, "tcadbout");
- err = true;
- }
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- int mrnum = tcmaprnum(map);
- if(mrnum % 50 > 0) iprintf(" (%08d)\n", mrnum);
- if(tcadbrnum(adb) != 0){
- eprint(adb, "(validation)");
- err = true;
- }
- iprintf("record number: %llu\n", (unsigned long long)tcadbrnum(adb));
- iprintf("size: %llu\n", (unsigned long long)tcadbsize(adb));
- tcmapdel(map);
- if(!tcadbclose(adb)){
- eprint(adb, "tcadbclose");
- err = true;
- }
- tcadbdel(adb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The B+ tree database API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include "tcutil.h"
-#include "tchdb.h"
-#include "tcbdb.h"
-#include "myconf.h"
-
-#define BDBFILEMODE 00644 // permission of created files
-#define BDBOPAQUESIZ 64 // size of using opaque field
-#define BDBPAGEBUFSIZ 32768 // size of a buffer to read each page
-#define BDBNODEIDBASE ((1LL<<48)+1) // base number of node ID
-#define BDBLEVELMAX 64 // max level of B+ tree
-#define BDBCACHEOUT 8 // number of pages in a process of cacheout
-
-#define BDBDEFLMEMB 128 // default number of members in each leaf
-#define BDBMINLMEMB 4 // minimum number of members in each leaf
-#define BDBDEFNMEMB 256 // default number of members in each node
-#define BDBMINNMEMB 4 // minimum number of members in each node
-#define BDBDEFBNUM 16381 // default bucket number
-#define BDBDEFAPOW 8 // default alignment power
-#define BDBDEFFPOW 10 // default free block pool power
-#define BDBDEFLCNUM 1024 // default number of leaf cache
-#define BDBDEFNCNUM 512 // default number of node cache
-
-typedef struct { // type of structure for a record
- char *kbuf; // pointer to the key region
- int ksiz; // size of the key region
- char *vbuf; // pointer to the value region
- int vsiz; // size of the value region
- TCLIST *rest; // list of value objects
-} BDBREC;
-
-typedef struct { // type of structure for a leaf page
- uint64_t id; // ID number of the leaf
- TCLIST *recs; // list of records
- uint64_t prev; // ID number of the previous leaf
- uint64_t next; // ID number of the next leaf
- bool dirty; // whether to be written back
- bool dead; // whether to be removed
-} BDBLEAF;
-
-typedef struct { // type of structure for a page index
- uint64_t pid; // ID number of the referring page
- char *kbuf; // pointer to the key region
- int ksiz; // size of the key region
-} BDBIDX;
-
-typedef struct { // type of structure for a node page
- uint64_t id; // ID number of the node
- uint64_t heir; // ID of the child before the first index
- TCLIST *idxs; // list of indexes
- bool dirty; // whether to be written back
-} BDBNODE;
-
-enum { // enumeration for duplication behavior
- BDBPDOVER, // overwrite an existing value
- BDBPDKEEP, // keep the existing value
- BDBPDCAT, // concatenate values
- BDBPDDUP, // allow duplication of keys
- BDBPDDUPB, // allow backward duplication
-};
-
-
-/* private macros */
-#define BDBLOCKMETHOD(TC_bdb, TC_wr) \
- ((TC_bdb)->mmtx ? tcbdblockmethod((TC_bdb), (TC_wr)) : true)
-#define BDBUNLOCKMETHOD(TC_bdb) \
- ((TC_bdb)->mmtx ? tcbdbunlockmethod(TC_bdb) : true)
-#define BDBLOCKCACHE(TC_bdb) \
- ((TC_bdb)->mmtx ? tcbdblockcache(TC_bdb) : true)
-#define BDBUNLOCKCACHE(TC_bdb) \
- ((TC_bdb)->mmtx ? tcbdbunlockcache(TC_bdb) : true)
-#define BDBLOCKTRAN(TC_bdb) \
- ((TC_bdb)->mmtx ? tcbdblocktran(TC_bdb) : true)
-#define BDBUNLOCKTRAN(TC_bdb) \
- ((TC_bdb)->mmtx ? tcbdbunlocktran(TC_bdb) : true)
-
-
-/* private function prototypes */
-static void tcbdbclear(TCBDB *bdb);
-static void tcdumpmeta(TCBDB *bdb);
-static void tcloadmeta(TCBDB *bdb);
-static BDBLEAF *tcbdbleafnew(TCBDB *bdb, uint64_t prev, uint64_t next);
-static bool tcbdbleafcacheout(TCBDB *bdb, BDBLEAF *leaf);
-static bool tcbdbleafsave(TCBDB *bdb, BDBLEAF *leaf);
-static BDBLEAF *tcbdbleafload(TCBDB *bdb, uint64_t id);
-static BDBLEAF *tcbdbgethistleaf(TCBDB *bdb, const char *kbuf, int ksiz);
-static bool tcbdbleafaddrec(TCBDB *bdb, BDBLEAF *leaf, int dmode,
- const char *kbuf, int ksiz, const char *vbuf, int vsiz);
-static int tcbdbleafdatasize(BDBLEAF *leaf);
-static BDBLEAF *tcbdbleafdivide(TCBDB *bdb, BDBLEAF *leaf);
-static bool tcbdbleafkill(TCBDB *bdb, BDBLEAF *leaf);
-static BDBNODE *tcbdbnodenew(TCBDB *bdb, uint64_t heir);
-static bool tcbdbnodecacheout(TCBDB *bdb, BDBNODE *node);
-static bool tcbdbnodesave(TCBDB *bdb, BDBNODE *node);
-static BDBNODE *tcbdbnodeload(TCBDB *bdb, uint64_t id);
-static void tcbdbnodeaddidx(TCBDB *bdb, BDBNODE *node, bool order, uint64_t pid,
- const char *kbuf, int ksiz);
-static bool tcbdbnodesubidx(TCBDB *bdb, BDBNODE *node, uint64_t pid);
-static uint64_t tcbdbsearchleaf(TCBDB *bdb, const char *kbuf, int ksiz);
-static BDBREC *tcbdbsearchrec(TCBDB *bdb, BDBLEAF *leaf, const char *kbuf, int ksiz, int *ip);
-static bool tcbdbcacheadjust(TCBDB *bdb);
-static void tcbdbcachepurge(TCBDB *bdb);
-static bool tcbdbopenimpl(TCBDB *bdb, const char *path, int omode);
-static bool tcbdbcloseimpl(TCBDB *bdb);
-static bool tcbdbputimpl(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
- int dmode);
-static bool tcbdboutimpl(TCBDB *bdb, const char *kbuf, int ksiz);
-static bool tcbdboutlist(TCBDB *bdb, const char *kbuf, int ksiz);
-static const char *tcbdbgetimpl(TCBDB *bdb, const char *kbuf, int ksiz, int *sp);
-static int tcbdbgetnum(TCBDB *bdb, const char *kbuf, int ksiz);
-static TCLIST *tcbdbgetlist(TCBDB *bdb, const char *kbuf, int ksiz);
-static bool tcbdbrangeimpl(TCBDB *bdb, const char *bkbuf, int bksiz, bool binc,
- const char *ekbuf, int eksiz, bool einc, int max, TCLIST *keys);
-static bool tcbdbrangefwm(TCBDB *bdb, const char *pbuf, int psiz, int max, TCLIST *keys);
-static bool tcbdboptimizeimpl(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
- int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
-static bool tcbdbvanishimpl(TCBDB *bdb);
-static bool tcbdblockmethod(TCBDB *bdb, bool wr);
-static bool tcbdbunlockmethod(TCBDB *bdb);
-static bool tcbdblockcache(TCBDB *bdb);
-static bool tcbdbunlockcache(TCBDB *bdb);
-static bool tcbdblocktran(TCBDB *bdb);
-static bool tcbdbunlocktran(TCBDB *bdb);
-static bool tcbdbcurfirstimpl(BDBCUR *cur);
-static bool tcbdbcurlastimpl(BDBCUR *cur);
-static bool tcbdbcurjumpimpl(BDBCUR *cur, const char *kbuf, int ksiz, bool forward);
-static bool tcbdbcuradjust(BDBCUR *cur, bool forward);
-static bool tcbdbcurprevimpl(BDBCUR *cur);
-static bool tcbdbcurnextimpl(BDBCUR *cur);
-static bool tcbdbcurputimpl(BDBCUR *cur, const char *vbuf, int vsiz, int mode);
-static bool tcbdbcuroutimpl(BDBCUR *cur);
-static bool tcbdbcurrecimpl(BDBCUR *cur, const char **kbp, int *ksp, const char **vbp, int *vsp);
-
-
-/* debugging function prototypes */
-void tcbdbprintmeta(TCBDB *bdb);
-void tcbdbprintleaf(TCBDB *bdb, BDBLEAF *leaf);
-void tcbdbprintnode(TCBDB *bdb, BDBNODE *node);
-
-
-
-/*************************************************************************************************
- * API
- *************************************************************************************************/
-
-
-/* Get the message string corresponding to an error code. */
-const char *tcbdberrmsg(int ecode){
- return tchdberrmsg(ecode);
-}
-
-
-/* Create a B+ tree database object. */
-TCBDB *tcbdbnew(void){
- TCBDB *bdb;
- TCMALLOC(bdb, sizeof(*bdb));
- tcbdbclear(bdb);
- bdb->hdb = tchdbnew();
- TCMALLOC(bdb->hist, sizeof(*bdb->hist) * BDBLEVELMAX);
- return bdb;
-}
-
-
-/* Delete a B+ tree database object. */
-void tcbdbdel(TCBDB *bdb){
- assert(bdb);
- if(bdb->open) tcbdbclose(bdb);
- free(bdb->hist);
- tchdbdel(bdb->hdb);
- if(bdb->mmtx){
- pthread_mutex_destroy(bdb->tmtx);
- pthread_mutex_destroy(bdb->cmtx);
- pthread_rwlock_destroy(bdb->mmtx);
- free(bdb->tmtx);
- free(bdb->cmtx);
- free(bdb->mmtx);
- }
- free(bdb);
-}
-
-
-/* Get the last happened error code of a B+ tree database object. */
-int tcbdbecode(TCBDB *bdb){
- assert(bdb);
- return tchdbecode(bdb->hdb);
-}
-
-
-/* Set mutual exclusion control of a B+ tree database object for threading. */
-bool tcbdbsetmutex(TCBDB *bdb){
- assert(bdb);
- if(!TCUSEPTHREAD) return true;
- if(!tcglobalmutexlock()) return false;
- if(bdb->mmtx || bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- tcglobalmutexunlock();
- return false;
- }
- TCMALLOC(bdb->mmtx, sizeof(pthread_rwlock_t));
- TCMALLOC(bdb->cmtx, sizeof(pthread_mutex_t));
- TCMALLOC(bdb->tmtx, sizeof(pthread_mutex_t));
- if(pthread_rwlock_init(bdb->mmtx, NULL) != 0 || pthread_mutex_init(bdb->cmtx, NULL) != 0 ||
- pthread_mutex_init(bdb->tmtx, NULL) != 0){
- free(bdb->tmtx);
- free(bdb->cmtx);
- free(bdb->mmtx);
- bdb->tmtx = NULL;
- bdb->cmtx = NULL;
- bdb->mmtx = NULL;
- tcglobalmutexunlock();
- return false;
- }
- tcglobalmutexunlock();
- return tchdbsetmutex(bdb->hdb);
-}
-
-
-/* Set the custom comparison function of a B+ tree database object. */
-bool tcbdbsetcmpfunc(TCBDB *bdb, BDBCMP cmp, void *cmpop){
- assert(bdb && cmp);
- if(bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- bdb->cmp = cmp;
- bdb->cmpop = cmpop;
- return true;
-}
-
-
-/* Set the tuning parameters of a B+ tree database object. */
-bool tcbdbtune(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
- int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(bdb);
- if(bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- bdb->lmemb = (lmemb > 0) ? tclmax(lmemb, BDBMINLMEMB) : BDBDEFLMEMB;
- bdb->nmemb = (nmemb > 0) ? tclmax(nmemb, BDBMINNMEMB) : BDBDEFNMEMB;
- bdb->opts = opts;
- uint8_t hopts = 0;
- if(opts & BDBTLARGE) hopts |= HDBTLARGE;
- if(opts & BDBTDEFLATE) hopts |= HDBTDEFLATE;
- if(opts & BDBTTCBS) hopts |= HDBTTCBS;
- bnum = (bnum > 0) ? bnum : BDBDEFBNUM;
- apow = (apow >= 0) ? apow : BDBDEFAPOW;
- fpow = (fpow >= 0) ? fpow : BDBDEFFPOW;
- return tchdbtune(bdb->hdb, bnum, apow, fpow, hopts);
-}
-
-
-/* Set the caching parameters of a B+ tree database object. */
-bool tcbdbsetcache(TCBDB *bdb, int32_t lcnum, int32_t ncnum){
- assert(bdb);
- if(bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- if(lcnum > 0) bdb->lcnum = tclmax(lcnum, BDBLEVELMAX);
- if(ncnum > 0) bdb->ncnum = tclmax(ncnum, BDBLEVELMAX);
- return true;
-}
-
-
-/* Open a database file and connect a B+ tree database object. */
-bool tcbdbopen(TCBDB *bdb, const char *path, int omode){
- assert(bdb && path);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbopenimpl(bdb, path, omode);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Close a B+ tree database object. */
-bool tcbdbclose(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcloseimpl(bdb);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Store a record into a B+ tree database object. */
-bool tcbdbput(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(bdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbputimpl(bdb, kbuf, ksiz, vbuf, vsiz, BDBPDOVER);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Store a string record into a B+ tree database object. */
-bool tcbdbput2(TCBDB *bdb, const char *kstr, const char *vstr){
- assert(bdb && kstr && vstr);
- return tcbdbput(bdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Store a new record into a B+ tree database object. */
-bool tcbdbputkeep(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(bdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbputimpl(bdb, kbuf, ksiz, vbuf, vsiz, BDBPDKEEP);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Store a new string record into a B+ tree database object. */
-bool tcbdbputkeep2(TCBDB *bdb, const char *kstr, const char *vstr){
- assert(bdb && kstr && vstr);
- return tcbdbputkeep(bdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Concatenate a value at the end of the existing record in a B+ tree database object. */
-bool tcbdbputcat(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(bdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbputimpl(bdb, kbuf, ksiz, vbuf, vsiz, BDBPDCAT);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Concatenate a string value at the end of the existing record in a B+ tree database object. */
-bool tcbdbputcat2(TCBDB *bdb, const char *kstr, const char *vstr){
- assert(bdb && kstr && vstr);
- return tcbdbputcat(bdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Store a record into a B+ tree database object with allowing duplication of keys. */
-bool tcbdbputdup(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(bdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbputimpl(bdb, kbuf, ksiz, vbuf, vsiz, BDBPDDUP);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Store a string record into a B+ tree database object with allowing duplication of keys. */
-bool tcbdbputdup2(TCBDB *bdb, const char *kstr, const char *vstr){
- assert(bdb && kstr && vstr);
- return tcbdbputdup(bdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Store records into a B+ tree database object with allowing duplication of keys. */
-bool tcbdbputdup3(TCBDB *bdb, const void *kbuf, int ksiz, const TCLIST *vals){
- assert(bdb && kbuf && ksiz >= 0 && vals);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool err = false;
- int ln = TCLISTNUM(vals);
- for(int i = 0; i < ln; i++){
- int vsiz;
- const char *vbuf = tclistval(vals, i, &vsiz);
- if(!tcbdbputimpl(bdb, kbuf, ksiz, vbuf, vsiz, BDBPDDUP)) err = true;
- }
- BDBUNLOCKMETHOD(bdb);
- return !err;
-}
-
-
-/* Remove a record of a B+ tree database object. */
-bool tcbdbout(TCBDB *bdb, const void *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdboutimpl(bdb, kbuf, ksiz);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Remove a string record of a B+ tree database object. */
-bool tcbdbout2(TCBDB *bdb, const char *kstr){
- assert(bdb && kstr);
- return tcbdbout(bdb, kstr, strlen(kstr));
-}
-
-
-/* Remove records of a B+ tree database object. */
-bool tcbdbout3(TCBDB *bdb, const void *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdboutlist(bdb, kbuf, ksiz);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Retrieve a record in a B+ tree database object. */
-void *tcbdbget(TCBDB *bdb, const void *kbuf, int ksiz, int *sp){
- assert(bdb && kbuf && ksiz >= 0 && sp);
- if(!BDBLOCKMETHOD(bdb, false)) return NULL;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return NULL;
- }
- const char *vbuf = tcbdbgetimpl(bdb, kbuf, ksiz, sp);
- char *rv;
- if(vbuf){
- TCMEMDUP(rv, vbuf, *sp);
- } else {
- rv = NULL;
- }
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)){
- free(rv);
- rv = NULL;
- }
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Retrieve a string record in a B+ tree database object. */
-char *tcbdbget2(TCBDB *bdb, const char *kstr){
- assert(bdb && kstr);
- int vsiz;
- return tcbdbget(bdb, kstr, strlen(kstr), &vsiz);
-}
-
-
-/* Retrieve a record in a B+ tree database object and write the value into a buffer. */
-const void *tcbdbget3(TCBDB *bdb, const void *kbuf, int ksiz, int *sp){
- assert(bdb && kbuf && ksiz >= 0 && sp);
- if(!BDBLOCKMETHOD(bdb, false)) return NULL;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return NULL;
- }
- const char *rv = tcbdbgetimpl(bdb, kbuf, ksiz, sp);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) rv = NULL;
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Retrieve records in a B+ tree database object. */
-TCLIST *tcbdbget4(TCBDB *bdb, const void *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- if(!BDBLOCKMETHOD(bdb, false)) return NULL;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return NULL;
- }
- TCLIST *rv = tcbdbgetlist(bdb, kbuf, ksiz);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)){
- if(rv) tclistdel(rv);
- rv = NULL;
- }
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Get the number of records corresponding a key in a B+ tree database object. */
-int tcbdbvnum(TCBDB *bdb, const void *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- if(!BDBLOCKMETHOD(bdb, false)) return 0;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return 0;
- }
- int rv = tcbdbgetnum(bdb, kbuf, ksiz);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) rv = 0;
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Get the number of records corresponding a string key in a B+ tree database object. */
-int tcbdbvnum2(TCBDB *bdb, const char *kstr){
- assert(bdb && kstr);
- return tcbdbvnum(bdb, kstr, strlen(kstr));
-}
-
-
-/* Get the size of the value of a record in a B+ tree database object. */
-int tcbdbvsiz(TCBDB *bdb, const void *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- int vsiz;
- if(!tcbdbget3(bdb, kbuf, ksiz, &vsiz)) return -1;
- return vsiz;
-}
-
-
-/* Get the size of the value of a string record in a B+ tree database object. */
-int tcbdbvsiz2(TCBDB *bdb, const char *kstr){
- assert(bdb && kstr);
- return tcbdbvsiz(bdb, kstr, strlen(kstr));
-}
-
-
-/* Get keys of ranged records in a B+ tree database object. */
-TCLIST *tcbdbrange(TCBDB *bdb, const void *bkbuf, int bksiz, bool binc,
- const void *ekbuf, int eksiz, bool einc, int max){
- assert(bdb);
- TCLIST *keys = tclistnew();
- if(!BDBLOCKMETHOD(bdb, false)) return keys;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return keys;
- }
- tcbdbrangeimpl(bdb, bkbuf, bksiz, binc, ekbuf, eksiz, einc, max, keys);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- tcbdbcacheadjust(bdb);
- BDBUNLOCKMETHOD(bdb);
- }
- return keys;
-}
-
-
-/* Get string keys of ranged records in a B+ tree database object. */
-TCLIST *tcbdbrange2(TCBDB *bdb, const char *bkstr, bool binc,
- const char *ekstr, bool einc, int max){
- return tcbdbrange(bdb, bkstr, bkstr ? strlen(bkstr) : 0, binc,
- ekstr, ekstr ? strlen(ekstr) : 0, einc, max);
-}
-
-
-/* Get forward matching keys in a B+ tree database object. */
-TCLIST *tcbdbfwmkeys(TCBDB *bdb, const void *pbuf, int psiz, int max){
- assert(bdb && pbuf && psiz >= 0);
- TCLIST *keys = tclistnew();
- if(!BDBLOCKMETHOD(bdb, false)) return keys;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return keys;
- }
- tcbdbrangefwm(bdb, pbuf, psiz, max, keys);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- tcbdbcacheadjust(bdb);
- BDBUNLOCKMETHOD(bdb);
- }
- return keys;
-}
-
-
-/* Get forward matching string keys in a B+ tree database object. */
-TCLIST *tcbdbfwmkeys2(TCBDB *bdb, const char *pstr, int max){
- assert(bdb && pstr);
- return tcbdbfwmkeys(bdb, pstr, strlen(pstr), max);
-}
-
-
-
-/* Synchronize updated contents of a B+ tree database object with the file and the device. */
-bool tcbdbsync(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode || bdb->tran){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbmemsync(bdb, true);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Optimize the file of a B+ tree database object. */
-bool tcbdboptimize(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
- int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode || bdb->tran){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdboptimizeimpl(bdb, lmemb, nmemb, bnum, apow, fpow, opts);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Remove all records of a B+ tree database object. */
-bool tcbdbvanish(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode || bdb->tran){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbvanishimpl(bdb);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Copy the database file of a B+ tree database object. */
-bool tcbdbcopy(TCBDB *bdb, const char *path){
- assert(bdb && path);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- TCLIST *lids = tclistnew();
- TCLIST *nids = tclistnew();
- const char *vbuf;
- int vsiz;
- TCMAP *leafc = bdb->leafc;
- tcmapiterinit(leafc);
- while((vbuf = tcmapiternext(leafc, &vsiz)) != NULL){
- tclistpush(lids, vbuf, vsiz);
- }
- TCMAP *nodec = bdb->nodec;
- tcmapiterinit(nodec);
- while((vbuf = tcmapiternext(nodec, &vsiz)) != NULL){
- tclistpush(nids, vbuf, vsiz);
- }
- BDBUNLOCKMETHOD(bdb);
- bool err = false;
- int ln = TCLISTNUM(lids);
- for(int i = 0; i < ln; i++){
- vbuf = TCLISTVALPTR(lids, i);
- if(BDBLOCKMETHOD(bdb, true)){
- if(bdb->open){
- int rsiz;
- BDBLEAF *leaf = (BDBLEAF *)tcmapget(bdb->leafc, vbuf, sizeof(leaf->id), &rsiz);
- if(leaf && leaf->dirty && !tcbdbleafsave(bdb, leaf)) err = true;
- } else {
- err = true;
- }
- BDBUNLOCKMETHOD(bdb);
- } else {
- err = true;
- }
- }
- ln = TCLISTNUM(nids);
- for(int i = 0; i < ln; i++){
- vbuf = TCLISTVALPTR(nids, i);
- if(BDBLOCKMETHOD(bdb, true)){
- if(bdb->open){
- int rsiz;
- BDBNODE *node = (BDBNODE *)tcmapget(bdb->nodec, vbuf, sizeof(node->id), &rsiz);
- if(node && node->dirty && !tcbdbnodesave(bdb, node)) err = true;
- } else {
- err = true;
- }
- BDBUNLOCKMETHOD(bdb);
- } else {
- err = true;
- }
- }
- tclistdel(nids);
- tclistdel(lids);
- if(!tcbdbtranbegin(bdb)) err = true;
- if(BDBLOCKMETHOD(bdb, false)){
- if(!tchdbcopy(bdb->hdb, path)) err = true;
- BDBUNLOCKMETHOD(bdb);
- } else {
- err = true;
- }
- if(!tcbdbtrancommit(bdb)) err = true;
- return !err;
-}
-
-
-/* Begin the transaction of a B+ tree database object. */
-bool tcbdbtranbegin(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode || bdb->tran){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(!tcbdbmemsync(bdb, false)){
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(!BDBLOCKTRAN(bdb)){
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bdb->tran = true;
- TCMEMDUP(bdb->rbopaque, bdb->opaque, BDBOPAQUESIZ);
- BDBUNLOCKMETHOD(bdb);
- return true;
-}
-
-
-/* Commit the transaction of a B+ tree database object. */
-bool tcbdbtrancommit(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode || !bdb->tran){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- free(bdb->rbopaque);
- bdb->tran = false;
- bdb->rbopaque = NULL;
- bool err = false;
- if(!tcbdbmemsync(bdb, false)) err = true;
- BDBUNLOCKTRAN(bdb);
- BDBUNLOCKMETHOD(bdb);
- return !err;
-}
-
-
-/* Abort the transaction of a B+ tree database object. */
-bool tcbdbtranabort(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode || !bdb->tran){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- tcbdbcachepurge(bdb);
- memcpy(bdb->opaque, bdb->rbopaque, BDBOPAQUESIZ);
- tcloadmeta(bdb);
- free(bdb->rbopaque);
- bdb->tran = false;
- bdb->rbopaque = NULL;
- BDBUNLOCKTRAN(bdb);
- BDBUNLOCKMETHOD(bdb);
- return true;
-}
-
-
-/* Get the file path of a B+ tree database object. */
-const char *tcbdbpath(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, false)) return NULL;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return NULL;
- }
- const char *rv = tchdbpath(bdb->hdb);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Get the number of records of a B+ tree database object. */
-uint64_t tcbdbrnum(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, false)) return 0;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return 0;
- }
- uint64_t rv = bdb->rnum;
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Get the size of the database file of a B+ tree database object. */
-uint64_t tcbdbfsiz(TCBDB *bdb){
- assert(bdb);
- if(!BDBLOCKMETHOD(bdb, false)) return 0;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return 0;
- }
- uint64_t rv = tchdbfsiz(bdb->hdb);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Create a cursor object. */
-BDBCUR *tcbdbcurnew(TCBDB *bdb){
- assert(bdb);
- BDBCUR *cur;
- TCMALLOC(cur, sizeof(*cur));
- cur->bdb = bdb;
- cur->id = 0;
- cur->kidx = 0;
- cur->vidx = 0;
- return cur;
-}
-
-
-/* Delete a cursor object. */
-void tcbdbcurdel(BDBCUR *cur){
- assert(cur);
- free(cur);
-}
-
-
-/* Move a cursor object to the first record. */
-bool tcbdbcurfirst(BDBCUR *cur){
- assert(cur);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcurfirstimpl(cur);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) rv = false;
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Move a cursor object to the last record. */
-bool tcbdbcurlast(BDBCUR *cur){
- assert(cur);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcurlastimpl(cur);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) rv = false;
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Move a cursor object to the front of records corresponding a key. */
-bool tcbdbcurjump(BDBCUR *cur, const void *kbuf, int ksiz){
- assert(cur && kbuf && ksiz >= 0);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcurjumpimpl(cur, kbuf, ksiz, true);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) rv = false;
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Move a cursor object to the front of records corresponding a key string. */
-bool tcbdbcurjump2(BDBCUR *cur, const char *kstr){
- assert(cur && kstr);
- return tcbdbcurjump(cur, kstr, strlen(kstr));
-}
-
-
-/* Move a cursor object to the previous record. */
-bool tcbdbcurprev(BDBCUR *cur){
- assert(cur);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcurprevimpl(cur);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) rv = false;
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Move a cursor object to the next record. */
-bool tcbdbcurnext(BDBCUR *cur){
- assert(cur);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcurnextimpl(cur);
- bool adj = TCMAPRNUM(bdb->leafc) > bdb->lcnum || TCMAPRNUM(bdb->nodec) > bdb->ncnum;
- BDBUNLOCKMETHOD(bdb);
- if(adj && BDBLOCKMETHOD(bdb, true)){
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) rv = false;
- BDBUNLOCKMETHOD(bdb);
- }
- return rv;
-}
-
-
-/* Insert a record around a cursor object. */
-bool tcbdbcurput(BDBCUR *cur, const void *vbuf, int vsiz, int cpmode){
- assert(cur && vbuf && vsiz >= 0);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcurputimpl(cur, vbuf, vsiz, cpmode);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Insert a string record around a cursor object. */
-bool tcbdbcurput2(BDBCUR *cur, const char *vstr, int cpmode){
- assert(cur && vstr);
- return tcbdbcurput(cur, vstr, strlen(vstr), cpmode);
-}
-
-
-/* Delete the record where a cursor object is. */
-bool tcbdbcurout(BDBCUR *cur){
- assert(cur);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcuroutimpl(cur);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Get the key of the record where the cursor object is. */
-char *tcbdbcurkey(BDBCUR *cur, int *sp){
- assert(cur && sp);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- char *rv;
- if(tcbdbcurrecimpl(cur, &kbuf, &ksiz, &vbuf, &vsiz)){
- TCMEMDUP(rv, kbuf, ksiz);
- *sp = ksiz;
- } else {
- rv = NULL;
- }
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Get the key string of the record where the cursor object is. */
-char *tcbdbcurkey2(BDBCUR *cur){
- assert(cur);
- int ksiz;
- return tcbdbcurkey(cur, &ksiz);
-}
-
-
-/* Get the key of the record where the cursor object is, as a volatile buffer. */
-const char *tcbdbcurkey3(BDBCUR *cur, int *sp){
- assert(cur && sp);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- const char *rv;
- if(tcbdbcurrecimpl(cur, &kbuf, &ksiz, &vbuf, &vsiz)){
- rv = kbuf;
- *sp = ksiz;
- } else {
- rv = NULL;
- }
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Get the value of the record where the cursor object is. */
-char *tcbdbcurval(BDBCUR *cur, int *sp){
- assert(cur && sp);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- char *rv;
- if(tcbdbcurrecimpl(cur, &kbuf, &ksiz, &vbuf, &vsiz)){
- TCMEMDUP(rv, vbuf, vsiz);
- *sp = vsiz;
- } else {
- rv = NULL;
- }
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Get the value string of the record where the cursor object is. */
-char *tcbdbcurval2(BDBCUR *cur){
- assert(cur);
- int vsiz;
- return tcbdbcurval(cur, &vsiz);
-}
-
-
-/* Get the value of the record where the cursor object is, as a volatile buffer. */
-const char *tcbdbcurval3(BDBCUR *cur, int *sp){
- assert(cur && sp);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- const char *rv;
- if(tcbdbcurrecimpl(cur, &kbuf, &ksiz, &vbuf, &vsiz)){
- rv = vbuf;
- *sp = vsiz;
- } else {
- rv = NULL;
- }
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Get the key and the value of the record where the cursor object is. */
-bool tcbdbcurrec(BDBCUR *cur, TCXSTR *kxstr, TCXSTR *vxstr){
- assert(cur && kxstr && vxstr);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- bool rv;
- if(tcbdbcurrecimpl(cur, &kbuf, &ksiz, &vbuf, &vsiz)){
- tcxstrclear(kxstr);
- TCXSTRCAT(kxstr, kbuf, ksiz);
- tcxstrclear(vxstr);
- TCXSTRCAT(vxstr, vbuf, vsiz);
- rv = true;
- } else {
- rv = false;
- }
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-
-/*************************************************************************************************
- * features for experts
- *************************************************************************************************/
-
-
-/* Set the error code of a B+ tree database object. */
-void tcbdbsetecode(TCBDB *bdb, int ecode, const char *filename, int line, const char *func){
- assert(bdb && filename && line >= 1 && func);
- tchdbsetecode(bdb->hdb, ecode, filename, line, func);
-}
-
-
-/* Set the file descriptor for debugging output. */
-void tcbdbsetdbgfd(TCBDB *bdb, int fd){
- assert(bdb && fd >= 0);
- tchdbsetdbgfd(bdb->hdb, fd);
-}
-
-
-/* Get the file descriptor for debugging output. */
-int tcbdbdbgfd(TCBDB *bdb){
- assert(bdb);
- return tchdbdbgfd(bdb->hdb);
-}
-
-
-/* Synchronize updating contents on memory. */
-bool tcbdbmemsync(TCBDB *bdb, bool phys){
- assert(bdb);
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- bool err = false;
- bool clk = BDBLOCKCACHE(bdb);
- const char *vbuf;
- int vsiz;
- TCMAP *leafc = bdb->leafc;
- tcmapiterinit(leafc);
- while((vbuf = tcmapiternext(leafc, &vsiz)) != NULL){
- int rsiz;
- BDBLEAF *leaf = (BDBLEAF *)tcmapiterval(vbuf, &rsiz);
- if(leaf->dirty && !tcbdbleafsave(bdb, leaf)) err = true;
- }
- TCMAP *nodec = bdb->nodec;
- tcmapiterinit(nodec);
- while((vbuf = tcmapiternext(nodec, &vsiz)) != NULL){
- int rsiz;
- BDBNODE *node = (BDBNODE *)tcmapiterval(vbuf, &rsiz);
- if(node->dirty && !tcbdbnodesave(bdb, node)) err = true;
- }
- if(clk) BDBUNLOCKCACHE(bdb);
- tcdumpmeta(bdb);
- if(!tchdbmemsync(bdb->hdb, phys)) err = true;
- return !err;
-}
-
-
-/* Get the comparison function of a B+ tree database object. */
-BDBCMP tcbdbcmpfunc(TCBDB *bdb){
- assert(bdb);
- return bdb->cmp;
-}
-
-
-/* Get the opaque object for the comparison function of a B+ tree database object. */
-void *tcbdbcmpop(TCBDB *bdb){
- assert(bdb);
- return bdb->cmpop;
-}
-
-
-/* Get the maximum number of cached leaf nodes of a B+ tree database object. */
-uint32_t tcbdblmemb(TCBDB *bdb){
- assert(bdb);
- return bdb->lmemb;
-}
-
-
-/* Get the maximum number of cached non-leaf nodes of a B+ tree database object. */
-uint32_t tcbdbnmemb(TCBDB *bdb){
- assert(bdb);
- return bdb->nmemb;
-}
-
-
-/* Get the number of the leaf nodes of B+ tree database object. */
-uint64_t tcbdblnum(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return bdb->lnum;
-}
-
-
-/* Get the number of the non-leaf nodes of B+ tree database object. */
-uint64_t tcbdbnnum(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return bdb->nnum;
-}
-
-
-/* Get the number of elements of the bucket array of a B+ tree database object. */
-uint64_t tcbdbbnum(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbbnum(bdb->hdb);
-}
-
-
-/* Get the record alignment of a B+ tree database object. */
-uint32_t tcbdbalign(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbalign(bdb->hdb);
-}
-
-
-/* Get the maximum number of the free block pool of a B+ tree database object. */
-uint32_t tcbdbfbpmax(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbfbpmax(bdb->hdb);
-}
-
-
-/* Get the inode number of the database file of a B+ tree database object. */
-uint64_t tcbdbinode(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbinode(bdb->hdb);
-}
-
-
-/* Get the modification time of the database file of a B+ tree database object. */
-time_t tcbdbmtime(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbmtime(bdb->hdb);
-}
-
-
-/* Get the additional flags of a B+ tree database object. */
-uint8_t tcbdbflags(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbflags(bdb->hdb);
-}
-
-
-/* Get the options of a B+ tree database object. */
-uint8_t tcbdbopts(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return bdb->opts;
-}
-
-
-/* Get the pointer to the opaque field of a B+ tree database object. */
-char *tcbdbopaque(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbopaque(bdb->hdb) + BDBOPAQUESIZ;
-}
-
-
-/* Get the number of used elements of the bucket array of a B+ tree database object. */
-uint64_t tcbdbbnumused(TCBDB *bdb){
- assert(bdb);
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return tchdbbnumused(bdb->hdb);
-}
-
-
-/* Set the maximum size of each leaf node. */
-bool tcbdbsetlsmax(TCBDB *bdb, uint32_t lsmax){
- assert(bdb);
- if(bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- bdb->lsmax = lsmax;
- return true;
-}
-
-
-/* Set the capacity number of records. */
-bool tcbdbsetcapnum(TCBDB *bdb, uint64_t capnum){
- assert(bdb);
- if(bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- bdb->capnum = capnum;
- return true;
-}
-
-
-/* Store a new record into a B+ tree database object with backward duplication. */
-bool tcbdbputdupback(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(bdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!BDBLOCKMETHOD(bdb, true)) return false;
- if(!bdb->open || !bdb->wmode){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbputimpl(bdb, kbuf, ksiz, vbuf, vsiz, BDBPDDUPB);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Store a new string record into a B+ tree database object with backward duplication. */
-bool tcbdbputdupback2(TCBDB *bdb, const char *kstr, const char *vstr){
- assert(bdb && kstr && vstr);
- return tcbdbputdupback(bdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Move a cursor object to the rear of records corresponding a key. */
-bool tcbdbcurjumpback(BDBCUR *cur, const void *kbuf, int ksiz){
- assert(cur && kbuf && ksiz >= 0);
- TCBDB *bdb = cur->bdb;
- if(!BDBLOCKMETHOD(bdb, false)) return false;
- if(!bdb->open){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- BDBUNLOCKMETHOD(bdb);
- return false;
- }
- bool rv = tcbdbcurjumpimpl(cur, kbuf, ksiz, false);
- BDBUNLOCKMETHOD(bdb);
- return rv;
-}
-
-
-/* Move a cursor object to the rear of records corresponding a key string. */
-bool tcbdbcurjumpback2(BDBCUR *cur, const char *kstr){
- assert(cur && kstr);
- return tcbdbcurjumpback(cur, kstr, strlen(kstr));
-}
-
-
-/* Compare keys of two records by lexical order. */
-int tcbdbcmplexical(const char *aptr, int asiz, const char *bptr, int bsiz, void *op){
- assert(aptr && asiz >= 0 && bptr && bsiz >= 0);
- int rv;
- TCCMPLEXICAL(rv, aptr, asiz, bptr, bsiz);
- return rv;
-}
-
-
-/* Compare two keys as decimal strings of real numbers. */
-int tcbdbcmpdecimal(const char *aptr, int asiz, const char *bptr, int bsiz, void *op){
- assert(aptr && asiz >= 0 && bptr && bsiz >= 0);
- int sign;
- int64_t anum = 0;
- sign = 1;
- if(asiz > 0 && *aptr == '-'){
- aptr++;
- asiz--;
- sign = -1;
- }
- for(int i = 0; i < asiz; i++){
- int c = aptr[i];
- if(c < '0' || c > '9') continue;
- anum = anum * 10 + c - '0';
- }
- anum *= sign;
- int64_t bnum = 0;
- sign = 1;
- if(bsiz > 0 && *bptr == '-'){
- bptr++;
- bsiz--;
- sign = -1;
- }
- for(int i = 0; i < bsiz; i++){
- int c = bptr[i];
- if(c < '0' || c > '9') continue;
- bnum = bnum * 10 + c - '0';
- }
- bnum *= sign;
- return (anum < bnum) ? -1 : anum > bnum;
-}
-
-
-/* Compare two keys as 32-bit integers in the native byte order. */
-int tcbdbcmpint32(const char *aptr, int asiz, const char *bptr, int bsiz, void *op){
- assert(aptr && bptr);
- int32_t anum, bnum;
- if(asiz == sizeof(int32_t)){
- memcpy(&anum, aptr, sizeof(int32_t));
- } else if(asiz < sizeof(int32_t)){
- memset(&anum, 0, sizeof(int32_t));
- memcpy(&anum, aptr, asiz);
- } else {
- memcpy(&anum, aptr, sizeof(int32_t));
- }
- if(bsiz == sizeof(int32_t)){
- memcpy(&bnum, bptr, sizeof(int32_t));
- } else if(bsiz < sizeof(int32_t)){
- memset(&bnum, 0, sizeof(int32_t));
- memcpy(&bnum, bptr, bsiz);
- } else {
- memcpy(&bnum, bptr, sizeof(int32_t));
- }
- return (anum < bnum) ? -1 : anum > bnum;
-}
-
-
-/* Compare two keys as 64-bit integers in the native byte order. */
-int tcbdbcmpint64(const char *aptr, int asiz, const char *bptr, int bsiz, void *op){
- assert(aptr && bptr);
- int64_t anum, bnum;
- if(asiz == sizeof(int64_t)){
- memcpy(&anum, aptr, sizeof(int64_t));
- } else if(asiz < sizeof(int64_t)){
- memset(&anum, 0, sizeof(int64_t));
- memcpy(&anum, aptr, asiz);
- } else {
- memcpy(&anum, aptr, sizeof(int64_t));
- }
- if(bsiz == sizeof(int64_t)){
- memcpy(&bnum, bptr, sizeof(int64_t));
- } else if(bsiz < sizeof(int64_t)){
- memset(&bnum, 0, sizeof(int64_t));
- memcpy(&bnum, bptr, bsiz);
- } else {
- memcpy(&bnum, bptr, sizeof(int64_t));
- }
- return (anum < bnum) ? -1 : anum > bnum;
-}
-
-
-
-/*************************************************************************************************
- * private features
- *************************************************************************************************/
-
-
-/* Clear all members.
- `bdb' specifies the B+ tree database object. */
-static void tcbdbclear(TCBDB *bdb){
- assert(bdb);
- bdb->mmtx = NULL;
- bdb->cmtx = NULL;
- bdb->tmtx = NULL;
- bdb->hdb = NULL;
- bdb->opaque = NULL;
- bdb->open = false;
- bdb->wmode = false;
- bdb->lmemb = BDBDEFLMEMB;
- bdb->nmemb = BDBDEFNMEMB;
- bdb->opts = 0;
- bdb->root = 0;
- bdb->first = 0;
- bdb->last = 0;
- bdb->lnum = 0;
- bdb->nnum = 0;
- bdb->rnum = 0;
- bdb->leafc = NULL;
- bdb->nodec = NULL;
- bdb->cmp = NULL;
- bdb->cmpop = NULL;
- bdb->lcnum = BDBDEFLCNUM;
- bdb->ncnum = BDBDEFNCNUM;
- bdb->lsmax = 0;
- bdb->lschk = 0;
- bdb->capnum = 0;
- bdb->hist = NULL;
- bdb->hnum = 0;
- bdb->hleaf = 0;
- bdb->lleaf = 0;
- bdb->tran = false;
- bdb->rbopaque = NULL;
- bdb->cnt_saveleaf = -1;
- bdb->cnt_loadleaf = -1;
- bdb->cnt_killleaf = -1;
- bdb->cnt_adjleafc = -1;
- bdb->cnt_savenode = -1;
- bdb->cnt_loadnode = -1;
- bdb->cnt_adjnodec = -1;
- TCDODEBUG(bdb->cnt_saveleaf = 0);
- TCDODEBUG(bdb->cnt_loadleaf = 0);
- TCDODEBUG(bdb->cnt_killleaf = 0);
- TCDODEBUG(bdb->cnt_adjleafc = 0);
- TCDODEBUG(bdb->cnt_savenode = 0);
- TCDODEBUG(bdb->cnt_loadnode = 0);
- TCDODEBUG(bdb->cnt_adjnodec = 0);
-}
-
-
-/* Serialize meta data into the opaque field.
- `bdb' specifies the B+ tree database object. */
-static void tcdumpmeta(TCBDB *bdb){
- assert(bdb);
- memset(bdb->opaque, 0, 64);
- char *wp = bdb->opaque;
- if(bdb->cmp == tcbdbcmplexical){
- *(uint8_t *)(wp++) = 0x0;
- } else if(bdb->cmp == tcbdbcmpdecimal){
- *(uint8_t *)(wp++) = 0x1;
- } else if(bdb->cmp == tcbdbcmpint32){
- *(uint8_t *)(wp++) = 0x2;
- } else if(bdb->cmp == tcbdbcmpint64){
- *(uint8_t *)(wp++) = 0x3;
- } else {
- *(uint8_t *)(wp++) = 0xff;
- }
- wp += 7;
- uint32_t lnum;
- lnum = bdb->lmemb;
- lnum = TCHTOIL(lnum);
- memcpy(wp, &lnum, sizeof(lnum));
- wp += sizeof(lnum);
- lnum = bdb->nmemb;
- lnum = TCHTOIL(lnum);
- memcpy(wp, &lnum, sizeof(lnum));
- wp += sizeof(lnum);
- uint64_t llnum;
- llnum = bdb->root;
- llnum = TCHTOILL(llnum);
- memcpy(wp, &llnum, sizeof(llnum));
- wp += sizeof(llnum);
- llnum = bdb->first;
- llnum = TCHTOILL(llnum);
- memcpy(wp, &llnum, sizeof(llnum));
- wp += sizeof(llnum);
- llnum = bdb->last;
- llnum = TCHTOILL(llnum);
- memcpy(wp, &llnum, sizeof(llnum));
- wp += sizeof(llnum);
- llnum = bdb->lnum;
- llnum = TCHTOILL(llnum);
- memcpy(wp, &llnum, sizeof(llnum));
- wp += sizeof(llnum);
- llnum = bdb->nnum;
- llnum = TCHTOILL(llnum);
- memcpy(wp, &llnum, sizeof(llnum));
- wp += sizeof(llnum);
- llnum = bdb->rnum;
- llnum = TCHTOILL(llnum);
- memcpy(wp, &llnum, sizeof(llnum));
- wp += sizeof(llnum);
-}
-
-
-/* Deserialize meta data from the opaque field.
- `bdb' specifies the B+ tree database object. */
-static void tcloadmeta(TCBDB *bdb){
- const char *rp = bdb->opaque;
- uint8_t cnum = *(uint8_t *)(rp++);
- if(cnum == 0x0){
- bdb->cmp = tcbdbcmplexical;
- } else if(cnum == 0x1){
- bdb->cmp = tcbdbcmpdecimal;
- } else if(cnum == 0x2){
- bdb->cmp = tcbdbcmpint32;
- } else if(cnum == 0x3){
- bdb->cmp = tcbdbcmpint64;
- }
- rp += 7;
- uint32_t lnum;
- memcpy(&lnum, rp, sizeof(lnum));
- rp += sizeof(lnum);
- bdb->lmemb = TCITOHL(lnum);
- memcpy(&lnum, rp, sizeof(lnum));
- rp += sizeof(lnum);
- bdb->nmemb = TCITOHL(lnum);
- uint64_t llnum;
- memcpy(&llnum, rp, sizeof(llnum));
- bdb->root = TCITOHLL(llnum);
- rp += sizeof(llnum);
- memcpy(&llnum, rp, sizeof(llnum));
- bdb->first = TCITOHLL(llnum);
- rp += sizeof(llnum);
- memcpy(&llnum, rp, sizeof(llnum));
- bdb->last = TCITOHLL(llnum);
- rp += sizeof(llnum);
- memcpy(&llnum, rp, sizeof(llnum));
- bdb->lnum = TCITOHLL(llnum);
- rp += sizeof(llnum);
- memcpy(&llnum, rp, sizeof(llnum));
- bdb->nnum = TCITOHLL(llnum);
- rp += sizeof(llnum);
- memcpy(&llnum, rp, sizeof(llnum));
- bdb->rnum = TCITOHLL(llnum);
- rp += sizeof(llnum);
-}
-
-
-/* Create a new leaf.
- `bdb' specifies the B+ tree database object.
- `prev' specifies the ID number of the previous leaf.
- `next' specifies the ID number of the next leaf.
- The return value is the new leaf object. */
-static BDBLEAF *tcbdbleafnew(TCBDB *bdb, uint64_t prev, uint64_t next){
- assert(bdb);
- BDBLEAF lent;
- lent.id = ++bdb->lnum;
- lent.recs = tclistnew2(bdb->lmemb + 1);
- lent.prev = prev;
- lent.next = next;
- lent.dirty = true;
- lent.dead = false;
- tcmapputkeep(bdb->leafc, &(lent.id), sizeof(lent.id), &lent, sizeof(lent));
- int rsiz;
- return (BDBLEAF *)tcmapget(bdb->leafc, &(lent.id), sizeof(lent.id), &rsiz);
-}
-
-
-/* Remove a leaf from the cache.
- `bdb' specifies the B+ tree database object.
- `leaf' specifies the leaf object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbleafcacheout(TCBDB *bdb, BDBLEAF *leaf){
- assert(bdb && leaf);
- bool err = false;
- if(leaf->dirty && !tcbdbleafsave(bdb, leaf)) err = true;
- TCLIST *recs = leaf->recs;
- int ln = TCLISTNUM(recs);
- for(int i = 0; i < ln; i++){
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, i);
- free(recp->kbuf);
- free(recp->vbuf);
- if(recp->rest) tclistdel(recp->rest);
- }
- tclistdel(recs);
- tcmapout(bdb->leafc, &(leaf->id), sizeof(leaf->id));
- return !err;
-}
-
-
-/* Save a leaf into the internal database.
- `bdb' specifies the B+ tree database object.
- `leaf' specifies the leaf object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbleafsave(TCBDB *bdb, BDBLEAF *leaf){
- assert(bdb && leaf);
- TCDODEBUG(bdb->cnt_saveleaf++);
- TCXSTR *rbuf = tcxstrnew3(BDBPAGEBUFSIZ);
- char hbuf[(sizeof(uint64_t)+1)*3];
- char *wp = hbuf;
- uint64_t llnum;
- int step;
- llnum = leaf->prev;
- TCSETVNUMBUF64(step, wp, llnum);
- wp += step;
- llnum = leaf->next;
- TCSETVNUMBUF64(step, wp, llnum);
- wp += step;
- TCXSTRCAT(rbuf, hbuf, wp - hbuf);
- TCLIST *recs = leaf->recs;
- int ln = TCLISTNUM(recs);
- for(int i = 0; i < ln; i++){
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, i);
- int lnum;
- wp = hbuf;
- lnum = recp->ksiz;
- TCSETVNUMBUF(step, wp, lnum);
- wp += step;
- lnum = recp->vsiz;
- TCSETVNUMBUF(step, wp, lnum);
- wp += step;
- TCLIST *rest = recp->rest;
- int rnum = rest ? TCLISTNUM(rest) : 0;
- TCSETVNUMBUF(step, wp, rnum);
- wp += step;
- TCXSTRCAT(rbuf, hbuf, wp - hbuf);
- TCXSTRCAT(rbuf, recp->kbuf, recp->ksiz);
- TCXSTRCAT(rbuf, recp->vbuf, recp->vsiz);
- for(int j = 0; j < rnum; j++){
- int vsiz;
- const char *vbuf = tclistval(rest, j, &vsiz);
- TCSETVNUMBUF(step, hbuf, vsiz);
- TCXSTRCAT(rbuf, hbuf, step);
- TCXSTRCAT(rbuf, vbuf, vsiz);
- }
- }
- bool err = false;
- step = sprintf(hbuf, "%llx", (unsigned long long)leaf->id);
- if(ln < 1 && !tchdbout(bdb->hdb, hbuf, step) && tchdbecode(bdb->hdb) != TCENOREC)
- err = true;
- if(!leaf->dead && !tchdbput(bdb->hdb, hbuf, step, TCXSTRPTR(rbuf), TCXSTRSIZE(rbuf)))
- err = true;
- tcxstrdel(rbuf);
- leaf->dirty = false;
- return !err;
-}
-
-
-/* Load a leaf from the internal database.
- `bdb' specifies the B+ tree database object.
- `id' specifies the ID number of the leaf.
- The return value is the leaf object or `NULL' on failure. */
-static BDBLEAF *tcbdbleafload(TCBDB *bdb, uint64_t id){
- assert(bdb && id > 0);
- bool clk = BDBLOCKCACHE(bdb);
- int rsiz;
- BDBLEAF *leaf = (BDBLEAF *)tcmapget3(bdb->leafc, &id, sizeof(id), &rsiz);
- if(leaf){
- if(clk) BDBUNLOCKCACHE(bdb);
- return leaf;
- }
- if(clk) BDBUNLOCKCACHE(bdb);
- TCDODEBUG(bdb->cnt_loadleaf++);
- char hbuf[(sizeof(uint64_t)+1)*3];
- int step;
- step = sprintf(hbuf, "%llx", (unsigned long long)id);
- char *rbuf = NULL;
- char wbuf[BDBPAGEBUFSIZ];
- const char *rp = NULL;
- rsiz = tchdbget3(bdb->hdb, hbuf, step, wbuf, BDBPAGEBUFSIZ);
- if(rsiz < 1){
- tcbdbsetecode(bdb, TCEMISC, __FILE__, __LINE__, __func__);
- return false;
- } else if(rsiz < BDBPAGEBUFSIZ){
- rp = wbuf;
- } else {
- if(!(rbuf = tchdbget(bdb->hdb, hbuf, step, &rsiz))){
- tcbdbsetecode(bdb, TCEMISC, __FILE__, __LINE__, __func__);
- return false;
- }
- rp = rbuf;
- }
- BDBLEAF lent;
- lent.id = id;
- uint64_t llnum;
- TCREADVNUMBUF64(rp, llnum, step);
- lent.prev = llnum;
- rp += step;
- rsiz -= step;
- TCREADVNUMBUF64(rp, llnum, step);
- lent.next = llnum;
- rp += step;
- rsiz -= step;
- lent.dirty = false;
- lent.dead = false;
- lent.recs = tclistnew2(bdb->lmemb + 1);
- bool err = false;
- while(rsiz >= 3){
- BDBREC rec;
- TCREADVNUMBUF(rp, rec.ksiz, step);
- rp += step;
- rsiz -= step;
- TCREADVNUMBUF(rp, rec.vsiz, step);
- rp += step;
- rsiz -= step;
- int rnum;
- TCREADVNUMBUF(rp, rnum, step);
- rp += step;
- rsiz -= step;
- if(rsiz < rec.ksiz + rec.vsiz + rnum){
- err = true;
- break;
- }
- TCMEMDUP(rec.kbuf, rp, rec.ksiz);
- rp += rec.ksiz;
- rsiz -= rec.ksiz;
- TCMEMDUP(rec.vbuf, rp, rec.vsiz);
- rp += rec.vsiz;
- rsiz -= rec.vsiz;
- if(rnum > 0){
- rec.rest = tclistnew2(rnum);
- while(rnum-- > 0 && rsiz > 0){
- int vsiz;
- TCREADVNUMBUF(rp, vsiz, step);
- rp += step;
- rsiz -= step;
- if(rsiz < vsiz){
- err = true;
- break;
- }
- TCLISTPUSH(rec.rest, rp, vsiz);
- rp += vsiz;
- rsiz -= vsiz;
- }
- } else {
- rec.rest = NULL;
- }
- TCLISTPUSH(lent.recs, &rec, sizeof(rec));
- }
- free(rbuf);
- if(err || rsiz != 0){
- tcbdbsetecode(bdb, TCEMISC, __FILE__, __LINE__, __func__);
- return NULL;
- }
- clk = BDBLOCKCACHE(bdb);
- tcmapputkeep(bdb->leafc, &(lent.id), sizeof(lent.id), &lent, sizeof(lent));
- leaf = (BDBLEAF *)tcmapget(bdb->leafc, &(lent.id), sizeof(lent.id), &rsiz);
- if(clk) BDBUNLOCKCACHE(bdb);
- return leaf;
-}
-
-
-/* Load the historical leaf from the internal database.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the pointer to the leaf, else, it is `NULL'. */
-static BDBLEAF *tcbdbgethistleaf(TCBDB *bdb, const char *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- BDBLEAF *leaf = tcbdbleafload(bdb, bdb->hleaf);
- if(!leaf) return NULL;
- int ln = TCLISTNUM(leaf->recs);
- if(ln < 2) return NULL;
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(leaf->recs, 0);
- int rv;
- if(bdb->cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, recp->kbuf, recp->ksiz);
- } else {
- rv = bdb->cmp(kbuf, ksiz, recp->kbuf, recp->ksiz, bdb->cmpop);
- }
- if(rv == 0) return leaf;
- if(rv < 0) return NULL;
- recp = (BDBREC *)TCLISTVALPTR(leaf->recs, ln - 1);
- if(bdb->cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, recp->kbuf, recp->ksiz);
- } else {
- rv = bdb->cmp(kbuf, ksiz, recp->kbuf, recp->ksiz, bdb->cmpop);
- }
- if(rv <= 0 || leaf->next < 1) return leaf;
- return NULL;
-}
-
-
-/* Add a record to a leaf.
- `bdb' specifies the B+ tree database object.
- `leaf' specifies the leaf object.
- `dmode' specifies behavior when the key overlaps.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbleafaddrec(TCBDB *bdb, BDBLEAF *leaf, int dmode,
- const char *kbuf, int ksiz, const char *vbuf, int vsiz){
- assert(bdb && leaf && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- BDBCMP cmp = bdb->cmp;
- void *cmpop = bdb->cmpop;
- TCLIST *recs = leaf->recs;
- int ln = TCLISTNUM(recs);
- int left = 0;
- int right = ln;
- int i = (left + right) / 2;
- while(right >= left && i < ln){
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, i);
- int rv;
- if(cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, recp->kbuf, recp->ksiz);
- } else {
- rv = cmp(kbuf, ksiz, recp->kbuf, recp->ksiz, cmpop);
- }
- if(rv == 0){
- break;
- } else if(rv <= 0){
- right = i - 1;
- } else {
- left = i + 1;
- }
- i = (left + right) / 2;
- }
- while(i < ln){
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, i);
- int rv;
- if(cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, recp->kbuf, recp->ksiz);
- } else {
- rv = cmp(kbuf, ksiz, recp->kbuf, recp->ksiz, cmpop);
- }
- if(rv == 0){
- switch(dmode){
- case BDBPDKEEP:
- return false;
- case BDBPDCAT:
- TCREALLOC(recp->vbuf, recp->vbuf, recp->vsiz + vsiz + 1);
- memcpy(recp->vbuf + recp->vsiz, vbuf, vsiz);
- recp->vsiz += vsiz;
- recp->vbuf[recp->vsiz] = '\0';
- break;
- case BDBPDDUP:
- if(!recp->rest) recp->rest = tclistnew();
- TCLISTPUSH(recp->rest, vbuf, vsiz);
- bdb->rnum++;
- break;
- case BDBPDDUPB:
- if(!recp->rest) recp->rest = tclistnew();
- tclistunshift(recp->rest, recp->vbuf, recp->vsiz);
- if(vsiz > recp->vsiz) TCREALLOC(recp->vbuf, recp->vbuf, vsiz + 1);
- memcpy(recp->vbuf, vbuf, vsiz);
- recp->vbuf[vsiz] = '\0';
- recp->vsiz = vsiz;
- bdb->rnum++;
- break;
- default:
- if(vsiz > recp->vsiz) TCREALLOC(recp->vbuf, recp->vbuf, vsiz + 1);
- memcpy(recp->vbuf, vbuf, vsiz);
- recp->vbuf[vsiz] = '\0';
- recp->vsiz = vsiz;
- break;
- }
- break;
- } else if(rv < 0){
- BDBREC rec;
- TCMEMDUP(rec.kbuf, kbuf, ksiz);
- rec.ksiz = ksiz;
- TCMEMDUP(rec.vbuf, vbuf, vsiz);
- rec.vsiz = vsiz;
- rec.rest = NULL;
- tclistinsert(recs, i, &rec, sizeof(rec));
- bdb->rnum++;
- break;
- }
- i++;
- }
- if(i >= ln){
- BDBREC rec;
- TCMEMDUP(rec.kbuf, kbuf, ksiz);
- rec.ksiz = ksiz;
- TCMEMDUP(rec.vbuf, vbuf, vsiz);
- rec.vsiz = vsiz;
- rec.rest = NULL;
- TCLISTPUSH(recs, &rec, sizeof(rec));
- bdb->rnum++;
- }
- leaf->dirty = true;
- return true;
-}
-
-
-/* Calculate the size of data of a leaf object.
- `bdb' specifies the B+ tree database object.
- `leaf' specifies the leaf object.
- The return value is size of data of the leaf. */
-static int tcbdbleafdatasize(BDBLEAF *leaf){
- assert(leaf);
- int sum = 0;
- TCLIST *recs = leaf->recs;
- int ln = TCLISTNUM(recs);
- for(int i = 0; i < ln; i++){
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, i);
- sum += recp->ksiz + recp->vsiz;
- if(recp->rest){
- TCLIST *rest = recp->rest;
- int rnum = TCLISTNUM(rest);
- for(int j = 0; j < rnum; j++){
- int vsiz;
- tclistval(rest, j, &vsiz);
- sum += vsiz;
- }
- }
- }
- return sum;
-}
-
-
-/* Divide a leaf into two.
- `bdb' specifies the B+ tree database object.
- `leaf' specifies the leaf object.
- The return value is the new leaf object or `NULL' on failure. */
-static BDBLEAF *tcbdbleafdivide(TCBDB *bdb, BDBLEAF *leaf){
- assert(bdb && leaf);
- bdb->hleaf = 0;
- TCLIST *recs = leaf->recs;
- int mid = TCLISTNUM(recs) / 2;
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, mid);
- BDBLEAF *newleaf = tcbdbleafnew(bdb, leaf->id, leaf->next);
- if(newleaf->next > 0){
- BDBLEAF *nextleaf = tcbdbleafload(bdb, newleaf->next);
- if(!nextleaf) return NULL;
- nextleaf->prev = newleaf->id;
- nextleaf->dirty = true;
- }
- leaf->next = newleaf->id;
- leaf->dirty = true;
- int ln = TCLISTNUM(recs);
- TCLIST *newrecs = newleaf->recs;
- for(int i = mid; i < ln; i++){
- recp = (BDBREC *)TCLISTVALPTR(recs, i);
- TCLISTPUSH(newrecs, recp, sizeof(*recp));
- }
- ln = TCLISTNUM(newrecs);
- for(int i = 0; i < ln; i++){
- int rsiz;
- free(tclistpop(recs, &rsiz));
- }
- return newleaf;
-}
-
-
-/* Cut off the path to a leaf and mark it dead.
- `bdb' specifies the B+ tree database object.
- `leaf' specifies the leaf object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbleafkill(TCBDB *bdb, BDBLEAF *leaf){
- assert(bdb && leaf);
- BDBNODE *node = tcbdbnodeload(bdb, bdb->hist[bdb->hnum-1]);
- if(!node) return false;
- if(tcbdbnodesubidx(bdb, node, leaf->id)){
- TCDODEBUG(bdb->cnt_killleaf++);
- if(bdb->hleaf == leaf->id) bdb->hleaf = 0;
- if(leaf->prev > 0){
- BDBLEAF *tleaf = tcbdbleafload(bdb, leaf->prev);
- if(!tleaf) return false;
- tleaf->next = leaf->next;
- tleaf->dirty = true;
- if(bdb->last == leaf->id) bdb->last = leaf->prev;
- }
- if(leaf->next > 0){
- BDBLEAF *tleaf = tcbdbleafload(bdb, leaf->next);
- if(!tleaf) return false;
- tleaf->prev = leaf->prev;
- tleaf->dirty = true;
- if(bdb->first == leaf->id) bdb->first = leaf->next;
- }
- leaf->dead = true;
- }
- return true;
-}
-
-
-/* Create a new node.
- `bdb' specifies the B+ tree database object.
- `heir' specifies the ID of the child before the first index.
- The return value is the new node object. */
-static BDBNODE *tcbdbnodenew(TCBDB *bdb, uint64_t heir){
- assert(bdb && heir > 0);
- BDBNODE nent;
- nent.id = ++bdb->nnum + BDBNODEIDBASE;
- nent.idxs = tclistnew2(bdb->nmemb + 1);
- nent.heir = heir;
- nent.dirty = true;
- tcmapputkeep(bdb->nodec, &(nent.id), sizeof(nent.id), &nent, sizeof(nent));
- int rsiz;
- return (BDBNODE *)tcmapget(bdb->nodec, &(nent.id), sizeof(nent.id), &rsiz);
-}
-
-
-/* Remove a node from the cache.
- `bdb' specifies the B+ tree database object.
- `node' specifies the node object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbnodecacheout(TCBDB *bdb, BDBNODE *node){
- assert(bdb && node);
- bool err = false;
- if(node->dirty && !tcbdbnodesave(bdb, node)) err = true;
- TCLIST *idxs = node->idxs;
- int ln = TCLISTNUM(idxs);
- for(int i = 0; i < ln; i++){
- BDBIDX *idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- free(idxp->kbuf);
- }
- tclistdel(idxs);
- tcmapout(bdb->nodec, &(node->id), sizeof(node->id));
- return !err;
-}
-
-
-/* Save a node into the internal database.
- `bdb' specifies the B+ tree database object.
- `node' specifies the node object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbnodesave(TCBDB *bdb, BDBNODE *node){
- assert(bdb && node);
- TCDODEBUG(bdb->cnt_savenode++);
- TCXSTR *rbuf = tcxstrnew3(BDBPAGEBUFSIZ);
- char hbuf[(sizeof(uint64_t)+1)*2];
- uint64_t llnum;
- int step;
- llnum = node->heir;
- TCSETVNUMBUF64(step, hbuf, llnum);
- TCXSTRCAT(rbuf, hbuf, step);
- TCLIST *idxs = node->idxs;
- int ln = TCLISTNUM(idxs);
- for(int i = 0; i < ln; i++){
- BDBIDX *idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- char *wp = hbuf;
- llnum = idxp->pid;
- TCSETVNUMBUF64(step, wp, llnum);
- wp += step;
- uint32_t lnum = idxp->ksiz;
- TCSETVNUMBUF(step, wp, lnum);
- wp += step;
- TCXSTRCAT(rbuf, hbuf, wp - hbuf);
- TCXSTRCAT(rbuf, idxp->kbuf, idxp->ksiz);
- }
- bool err = false;
- step = sprintf(hbuf, "#%llx", (unsigned long long)(node->id - BDBNODEIDBASE));
- if(!tchdbput(bdb->hdb, hbuf, step, TCXSTRPTR(rbuf), TCXSTRSIZE(rbuf))) err = true;
- tcxstrdel(rbuf);
- node->dirty = false;
- return !err;
-}
-
-
-/* Load a node from the internal database.
- `bdb' specifies the B+ tree database object.
- `id' specifies the ID number of the node.
- The return value is the node object or `NULL' on failure. */
-static BDBNODE *tcbdbnodeload(TCBDB *bdb, uint64_t id){
- assert(bdb && id > BDBNODEIDBASE);
- bool clk = BDBLOCKCACHE(bdb);
- int rsiz;
- BDBNODE *node = (BDBNODE *)tcmapget3(bdb->nodec, &id, sizeof(id), &rsiz);
- if(node){
- if(clk) BDBUNLOCKCACHE(bdb);
- return node;
- }
- if(clk) BDBUNLOCKCACHE(bdb);
- TCDODEBUG(bdb->cnt_loadnode++);
- char hbuf[(sizeof(uint64_t)+1)*2];
- int step;
- step = sprintf(hbuf, "#%llx", (unsigned long long)(id - BDBNODEIDBASE));
- char *rbuf = NULL;
- char wbuf[BDBPAGEBUFSIZ];
- const char *rp = NULL;
- rsiz = tchdbget3(bdb->hdb, hbuf, step, wbuf, BDBPAGEBUFSIZ);
- if(rsiz < 1){
- tcbdbsetecode(bdb, TCEMISC, __FILE__, __LINE__, __func__);
- return false;
- } else if(rsiz < BDBPAGEBUFSIZ){
- rp = wbuf;
- } else {
- if(!(rbuf = tchdbget(bdb->hdb, hbuf, step, &rsiz))){
- tcbdbsetecode(bdb, TCEMISC, __FILE__, __LINE__, __func__);
- return false;
- }
- rp = rbuf;
- }
- BDBNODE nent;
- nent.id = id;
- uint64_t llnum;
- TCREADVNUMBUF64(rp, llnum, step);
- nent.heir = llnum;
- rp += step;
- rsiz -= step;
- nent.dirty = false;
- nent.idxs = tclistnew2(bdb->nmemb + 1);
- bool err = false;
- while(rsiz >= 2){
- BDBIDX idx;
- TCREADVNUMBUF64(rp, idx.pid, step);
- rp += step;
- rsiz -= step;
- TCREADVNUMBUF(rp, idx.ksiz, step);
- rp += step;
- rsiz -= step;
- if(rsiz < idx.ksiz){
- err = true;
- break;
- }
- TCMEMDUP(idx.kbuf, rp, idx.ksiz);
- rp += idx.ksiz;
- rsiz -= idx.ksiz;
- TCLISTPUSH(nent.idxs, &idx, sizeof(idx));
- }
- free(rbuf);
- if(err || rsiz != 0){
- tcbdbsetecode(bdb, TCEMISC, __FILE__, __LINE__, __func__);
- return NULL;
- }
- clk = BDBLOCKCACHE(bdb);
- tcmapputkeep(bdb->nodec, &(nent.id), sizeof(nent.id), &nent, sizeof(nent));
- node = (BDBNODE *)tcmapget(bdb->nodec, &(nent.id), sizeof(nent.id), &rsiz);
- if(clk) BDBUNLOCKCACHE(bdb);
- return node;
-}
-
-
-/* Add an index to a node.
- `bdb' specifies the B+ tree database object.
- `node' specifies the node object.
- `order' specifies whether the calling sequence is orderd or not.
- `pid' specifies the ID number of referred page.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key. */
-static void tcbdbnodeaddidx(TCBDB *bdb, BDBNODE *node, bool order, uint64_t pid,
- const char *kbuf, int ksiz){
- assert(bdb && node && pid > 0 && kbuf && ksiz >= 0);
- BDBIDX idx;
- idx.pid = pid;
- TCMEMDUP(idx.kbuf, kbuf, ksiz);
- idx.ksiz = ksiz;
- BDBCMP cmp = bdb->cmp;
- void *cmpop = bdb->cmpop;
- TCLIST *idxs = node->idxs;
- if(order){
- TCLISTPUSH(idxs, &idx, sizeof(idx));
- } else {
- int ln = TCLISTNUM(idxs);
- int left = 0;
- int right = ln;
- int i = (left + right) / 2;
- while(right >= left && i < ln){
- BDBIDX *idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- int rv;
- if(cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, idxp->kbuf, idxp->ksiz);
- } else {
- rv = cmp(kbuf, ksiz, idxp->kbuf, idxp->ksiz, cmpop);
- }
- if(rv == 0){
- break;
- } else if(rv <= 0){
- right = i - 1;
- } else {
- left = i + 1;
- }
- i = (left + right) / 2;
- }
- while(i < ln){
- BDBIDX *idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- int rv;
- if(cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, idxp->kbuf, idxp->ksiz);
- } else {
- rv = cmp(kbuf, ksiz, idxp->kbuf, idxp->ksiz, cmpop);
- }
- if(rv < 0){
- tclistinsert(idxs, i, &idx, sizeof(idx));
- break;
- }
- i++;
- }
- if(i >= ln) TCLISTPUSH(idxs, &idx, sizeof(idx));
- }
- node->dirty = true;
-}
-
-
-/* Subtract an index from a node.
- `bdb' specifies the B+ tree database object.
- `node' specifies the node object.
- `pid' specifies the ID number of referred page.
- The return value is whether the subtraction is completed. */
-static bool tcbdbnodesubidx(TCBDB *bdb, BDBNODE *node, uint64_t pid){
- assert(bdb && node && pid > 0);
- TCLIST *idxs = node->idxs;
- int ln = TCLISTNUM(idxs);
- if(ln < 2) return false;
- if(node->heir == pid){
- int rsiz;
- BDBIDX *idxp = (BDBIDX *)tclistshift(idxs, &rsiz);
- node->heir = idxp->pid;
- free(idxp->kbuf);
- free(idxp);
- node->dirty = true;
- return true;
- } else {
- int ln = TCLISTNUM(idxs);
- for(int i = 0; i < ln; i++){
- BDBIDX *idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- if(idxp->pid == pid){
- int rsiz;
- free(idxp->kbuf);
- free(tclistremove(idxs, i, &rsiz));
- node->dirty = true;
- return true;
- }
- }
- }
- return false;
-}
-
-
-/* Search the leaf object corresponding to a key.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- The return value is the ID number of the leaf object or 0 on failure. */
-static uint64_t tcbdbsearchleaf(TCBDB *bdb, const char *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- BDBCMP cmp = bdb->cmp;
- void *cmpop = bdb->cmpop;
- uint64_t *hist = bdb->hist;
- uint64_t pid = bdb->root;
- int hnum = 0;
- bdb->hleaf = 0;
- while(pid > BDBNODEIDBASE){
- BDBNODE *node = tcbdbnodeload(bdb, pid);
- if(!node){
- tcbdbsetecode(bdb, TCEMISC, __FILE__, __LINE__, __func__);
- return 0;
- }
- TCLIST *idxs = node->idxs;
- int ln = TCLISTNUM(idxs);
- if(ln < 1){
- tcbdbsetecode(bdb, TCEMISC, __FILE__, __LINE__, __func__);
- return 0;
- }
- hist[hnum++] = node->id;
- int left = 0;
- int right = ln;
- int i = (left + right) / 2;
- BDBIDX *idxp = NULL;
- while(right >= left && i < ln){
- idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- int rv;
- if(cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, idxp->kbuf, idxp->ksiz);
- } else {
- rv = cmp(kbuf, ksiz, idxp->kbuf, idxp->ksiz, cmpop);
- }
- if(rv == 0){
- break;
- } else if(rv <= 0){
- right = i - 1;
- } else {
- left = i + 1;
- }
- i = (left + right) / 2;
- }
- if(i > 0) i--;
- while(i < ln){
- idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- int rv;
- if(cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, idxp->kbuf, idxp->ksiz);
- } else {
- rv = cmp(kbuf, ksiz, idxp->kbuf, idxp->ksiz, cmpop);
- }
- if(rv < 0){
- if(i == 0){
- pid = node->heir;
- break;
- }
- idxp = (BDBIDX *)TCLISTVALPTR(idxs, i - 1);
- pid = idxp->pid;
- break;
- }
- i++;
- }
- if(i >= ln) pid = idxp->pid;
- }
- if(!bdb->mmtx){
- if(bdb->lleaf == pid) bdb->hleaf = pid;
- bdb->lleaf = pid;
- }
- bdb->hnum = hnum;
- return pid;
-}
-
-
-/* Search a record of a leaf.
- `bdb' specifies the B+ tree database object.
- `leaf' specifies the leaf object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `ip' specifies the pointer to a variable to fetch the index of the correspnding record.
- The return value is the pointer to a corresponding record or `NULL' on failure. */
-static BDBREC *tcbdbsearchrec(TCBDB *bdb, BDBLEAF *leaf, const char *kbuf, int ksiz, int *ip){
- assert(bdb && leaf && kbuf && ksiz >= 0);
- BDBCMP cmp = bdb->cmp;
- void *cmpop = bdb->cmpop;
- TCLIST *recs = leaf->recs;
- int ln = TCLISTNUM(recs);
- int left = 0;
- int right = ln;
- int i = (left + right) / 2;
- while(right >= left && i < ln){
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, i);
- int rv;
- if(cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, recp->kbuf, recp->ksiz);
- } else {
- rv = cmp(kbuf, ksiz, recp->kbuf, recp->ksiz, cmpop);
- }
- if(rv == 0){
- if(ip) *ip = i;
- return recp;
- } else if(rv <= 0){
- right = i - 1;
- } else {
- left = i + 1;
- }
- i = (left + right) / 2;
- }
- if(ip) *ip = i;
- return NULL;
-}
-
-
-/* Adjust the caches for leaves and nodes.
- `bdb' specifies the B+ tree database object.
- The return value is true if successful, else, it is false. */
-static bool tcbdbcacheadjust(TCBDB *bdb){
- bool err = false;
- if(TCMAPRNUM(bdb->leafc) > bdb->lcnum){
- TCDODEBUG(bdb->cnt_adjleafc++);
- bool clk = BDBLOCKCACHE(bdb);
- TCMAP *leafc = bdb->leafc;
- tcmapiterinit(leafc);
- for(int i = 0; i < BDBCACHEOUT; i++){
- int rsiz;
- if(!tcbdbleafcacheout(bdb, (BDBLEAF *)tcmapiterval(tcmapiternext(leafc, &rsiz), &rsiz)))
- err = true;
- }
- if(clk) BDBUNLOCKCACHE(bdb);
- }
- if(TCMAPRNUM(bdb->nodec) > bdb->ncnum){
- TCDODEBUG(bdb->cnt_adjnodec++);
- bool clk = BDBLOCKCACHE(bdb);
- TCMAP *nodec = bdb->nodec;
- tcmapiterinit(nodec);
- for(int i = 0; i < BDBCACHEOUT; i++){
- int rsiz;
- if(!tcbdbnodecacheout(bdb, (BDBNODE *)tcmapiterval(tcmapiternext(nodec, &rsiz), &rsiz)))
- err = true;
- }
- if(clk) BDBUNLOCKCACHE(bdb);
- }
- return !err;
-}
-
-
-/* Purge dirty pages of caches for leaves and nodes.
- `bdb' specifies the B+ tree database object. */
-static void tcbdbcachepurge(TCBDB *bdb){
- bool clk = BDBLOCKCACHE(bdb);
- int tsiz;
- const char *tmp;
- tcmapiterinit(bdb->leafc);
- while((tmp = tcmapiternext(bdb->leafc, &tsiz)) != NULL){
- int lsiz;
- BDBLEAF *leaf = (BDBLEAF *)tcmapiterval(tmp, &lsiz);
- if(!leaf->dirty) continue;
- TCLIST *recs = leaf->recs;
- int ln = TCLISTNUM(recs);
- for(int i = 0; i < ln; i++){
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, i);
- free(recp->kbuf);
- free(recp->vbuf);
- if(recp->rest) tclistdel(recp->rest);
- }
- tclistdel(recs);
- tcmapout(bdb->leafc, tmp, tsiz);
- }
- tcmapiterinit(bdb->nodec);
- while((tmp = tcmapiternext(bdb->nodec, &tsiz)) != NULL){
- int nsiz;
- BDBNODE *node = (BDBNODE *)tcmapiterval(tmp, &nsiz);
- if(!node->dirty) continue;
- TCLIST *idxs = node->idxs;
- int ln = TCLISTNUM(idxs);
- for(int i = 0; i < ln; i++){
- BDBIDX *idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- free(idxp->kbuf);
- }
- tclistdel(idxs);
- tcmapout(bdb->nodec, tmp, tsiz);
- }
- if(clk) BDBUNLOCKCACHE(bdb);
-}
-
-
-/* Open a database file and connect a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `path' specifies the path of the internal database file.
- `omode' specifies the connection mode.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbopenimpl(TCBDB *bdb, const char *path, int omode){
- assert(bdb && path);
- int homode = HDBOREADER;
- if(omode & BDBOWRITER){
- homode = HDBOWRITER;
- if(omode & BDBOCREAT) homode |= HDBOCREAT;
- if(omode & BDBOTRUNC) homode |= HDBOTRUNC;
- bdb->wmode = true;
- } else {
- bdb->wmode = false;
- }
- if(omode & BDBONOLCK) homode |= HDBONOLCK;
- if(omode & BDBOLCKNB) homode |= HDBOLCKNB;
- tchdbsettype(bdb->hdb, HDBTBTREE);
- if(!tchdbopen(bdb->hdb, path, homode)) return false;
- bdb->root = 0;
- bdb->first = 0;
- bdb->last = 0;
- bdb->lnum = 0;
- bdb->nnum = 0;
- bdb->rnum = 0;
- bdb->opaque = tchdbopaque(bdb->hdb);
- bdb->leafc = tcmapnew2(bdb->lcnum * 2 + 1);
- bdb->nodec = tcmapnew2(bdb->ncnum * 2 + 1);
- if(bdb->wmode && tchdbrnum(bdb->hdb) < 1){
- BDBLEAF *leaf = tcbdbleafnew(bdb, 0, 0);
- bdb->root = leaf->id;
- bdb->first = leaf->id;
- bdb->last = leaf->id;
- bdb->lnum = 1;
- bdb->nnum = 0;
- bdb->rnum = 0;
- if(!bdb->cmp){
- bdb->cmp = tcbdbcmplexical;
- bdb->cmpop = NULL;
- }
- tcdumpmeta(bdb);
- if(!tcbdbleafsave(bdb, leaf)){
- tcmapdel(bdb->nodec);
- tcmapdel(bdb->leafc);
- tchdbclose(bdb->hdb);
- return false;
- }
- }
- tcloadmeta(bdb);
- if(!bdb->cmp){
- tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);
- tcmapdel(bdb->nodec);
- tcmapdel(bdb->leafc);
- tchdbclose(bdb->hdb);
- return false;
- }
- if(bdb->lmemb < BDBMINLMEMB || bdb->nmemb < BDBMINNMEMB ||
- bdb->root < 1 || bdb->first < 1 || bdb->last < 1 ||
- bdb->lnum < 0 || bdb->nnum < 0 || bdb->rnum < 0){
- tcbdbsetecode(bdb, TCEMETA, __FILE__, __LINE__, __func__);
- tcmapdel(bdb->nodec);
- tcmapdel(bdb->leafc);
- tchdbclose(bdb->hdb);
- return false;
- }
- bdb->open = true;
- uint8_t hopts = tchdbopts(bdb->hdb);
- uint8_t opts = 0;
- if(hopts & HDBTLARGE) opts |= BDBTLARGE;
- if(hopts & HDBTDEFLATE) opts |= BDBTDEFLATE;
- if(hopts & HDBTTCBS) opts |= BDBTTCBS;
- bdb->opts = opts;
- bdb->hleaf = 0;
- bdb->lleaf = 0;
- bdb->tran = false;
- bdb->rbopaque = NULL;
- return true;
-}
-
-
-/* Close a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcloseimpl(TCBDB *bdb){
- assert(bdb);
- if(bdb->tran){
- tcbdbcachepurge(bdb);
- memcpy(bdb->opaque, bdb->rbopaque, BDBOPAQUESIZ);
- tcloadmeta(bdb);
- free(bdb->rbopaque);
- bdb->tran = false;
- bdb->rbopaque = NULL;
- BDBUNLOCKTRAN(bdb);
- }
- bool err = false;
- bdb->open = false;
- const char *vbuf;
- int vsiz;
- TCMAP *leafc = bdb->leafc;
- tcmapiterinit(leafc);
- while((vbuf = tcmapiternext(leafc, &vsiz)) != NULL){
- if(!tcbdbleafcacheout(bdb, (BDBLEAF *)tcmapiterval(vbuf, &vsiz))) err = true;
- }
- TCMAP *nodec = bdb->nodec;
- tcmapiterinit(nodec);
- while((vbuf = tcmapiternext(nodec, &vsiz)) != NULL){
- if(!tcbdbnodecacheout(bdb, (BDBNODE *)tcmapiterval(vbuf, &vsiz))) err = true;
- }
- if(bdb->wmode) tcdumpmeta(bdb);
- tcmapdel(bdb->nodec);
- tcmapdel(bdb->leafc);
- if(!tchdbclose(bdb->hdb)) err = true;
- return !err;
-}
-
-
-/* Store a record into a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- `dmode' specifies behavior when the key overlaps.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbputimpl(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
- int dmode){
- assert(bdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- BDBLEAF *leaf = NULL;
- if(bdb->hleaf < 1 || !(leaf = tcbdbgethistleaf(bdb, kbuf, ksiz))){
- uint64_t pid = tcbdbsearchleaf(bdb, kbuf, ksiz);
- if(pid < 1) return false;
- if(!(leaf = tcbdbleafload(bdb, pid))) return false;
- }
- if(!tcbdbleafaddrec(bdb, leaf, dmode, kbuf, ksiz, vbuf, vsiz)){
- tcbdbsetecode(bdb, TCEKEEP, __FILE__, __LINE__, __func__);
- return false;
- }
- int rnum = TCLISTNUM(leaf->recs);
- if(rnum > bdb->lmemb ||
- (bdb->lsmax > 0 && rnum > BDBMINLMEMB && (bdb->lschk++ & (0x8 - 1)) == 0 &&
- tcbdbleafdatasize(leaf) > bdb->lsmax)){
- bdb->lschk = 0;
- BDBLEAF *newleaf = tcbdbleafdivide(bdb, leaf);
- if(!newleaf) return false;
- if(leaf->id == bdb->last) bdb->last = newleaf->id;
- uint64_t heir = leaf->id;
- uint64_t pid = newleaf->id;
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(newleaf->recs, 0);
- int ksiz = recp->ksiz;
- char *kbuf;
- TCMEMDUP(kbuf, recp->kbuf, ksiz);
- while(true){
- BDBNODE *node;
- if(bdb->hnum < 1){
- node = tcbdbnodenew(bdb, heir);
- tcbdbnodeaddidx(bdb, node, true, pid, kbuf, ksiz);
- bdb->root = node->id;
- free(kbuf);
- break;
- }
- uint64_t parent = bdb->hist[--bdb->hnum];
- if(!(node = tcbdbnodeload(bdb, parent))){
- free(kbuf);
- return false;
- }
- tcbdbnodeaddidx(bdb, node, false, pid, kbuf, ksiz);
- free(kbuf);
- TCLIST *idxs = node->idxs;
- int ln = TCLISTNUM(idxs);
- if(ln <= bdb->nmemb) break;
- int mid = ln / 2;
- BDBIDX *idxp = (BDBIDX *)TCLISTVALPTR(idxs, mid);
- BDBNODE *newnode = tcbdbnodenew(bdb, idxp->pid);
- heir = node->id;
- pid = newnode->id;
- TCMEMDUP(kbuf, idxp->kbuf, idxp->ksiz);
- ksiz = idxp->ksiz;
- for(int i = mid + 1; i < ln; i++){
- idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- tcbdbnodeaddidx(bdb, newnode, true, idxp->pid, idxp->kbuf, idxp->ksiz);
- }
- ln = TCLISTNUM(newnode->idxs);
- for(int i = 0; i < ln; i++){
- int rsiz;
- idxp = (BDBIDX *)tclistpop(idxs, &rsiz);
- free(idxp->kbuf);
- free(idxp);
- }
- node->dirty = true;
- }
- if(bdb->capnum > 0 && bdb->rnum > bdb->capnum){
- uint64_t xnum = bdb->rnum - bdb->capnum;
- BDBCUR *cur = tcbdbcurnew(bdb);
- tcbdbcurfirstimpl(cur);
- while((xnum--) > 0){
- if(!tcbdbcuroutimpl(cur)){
- tcbdbcurdel(cur);
- return false;
- }
- }
- tcbdbcurdel(cur);
- }
- }
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) return false;
- return true;
-}
-
-
-/* Remove a record of a B+ tree database object.
- `hdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false. */
-static bool tcbdboutimpl(TCBDB *bdb, const char *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- BDBLEAF *leaf = NULL;
- if(bdb->hleaf < 1 || !(leaf = tcbdbgethistleaf(bdb, kbuf, ksiz))){
- uint64_t pid = tcbdbsearchleaf(bdb, kbuf, ksiz);
- if(pid < 1) return false;
- if(!(leaf = tcbdbleafload(bdb, pid))) return false;
- }
- int ri;
- BDBREC *recp = tcbdbsearchrec(bdb, leaf, kbuf, ksiz, &ri);
- if(!recp){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
- }
- if(recp->rest){
- free(recp->vbuf);
- recp->vbuf = tclistshift(recp->rest, &(recp->vsiz));
- if(TCLISTNUM(recp->rest) < 1){
- tclistdel(recp->rest);
- recp->rest = NULL;
- }
- } else {
- free(recp->vbuf);
- free(recp->kbuf);
- int rsiz;
- free(tclistremove(leaf->recs, ri, &rsiz));
- }
- leaf->dirty = true;
- bdb->rnum--;
- if(TCLISTNUM(leaf->recs) < 1 && bdb->hnum > 0 && !tcbdbleafkill(bdb, leaf)) return false;
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) return false;
- return true;
-}
-
-
-/* Remove records of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false. */
-static bool tcbdboutlist(TCBDB *bdb, const char *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- BDBLEAF *leaf = NULL;
- if(bdb->hleaf < 1 || !(leaf = tcbdbgethistleaf(bdb, kbuf, ksiz))){
- uint64_t pid = tcbdbsearchleaf(bdb, kbuf, ksiz);
- if(pid < 1) return false;
- if(!(leaf = tcbdbleafload(bdb, pid))) return false;
- }
- int ri;
- BDBREC *recp = tcbdbsearchrec(bdb, leaf, kbuf, ksiz, &ri);
- if(!recp){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
- }
- int rnum = 1;
- if(recp->rest){
- rnum += TCLISTNUM(recp->rest);
- tclistdel(recp->rest);
- }
- free(recp->vbuf);
- free(recp->kbuf);
- int rsiz;
- free(tclistremove(leaf->recs, ri, &rsiz));
- leaf->dirty = true;
- bdb->rnum -= rnum;
- if(TCLISTNUM(leaf->recs) < 1 && bdb->hnum > 0 && !tcbdbleafkill(bdb, leaf)) return false;
- if(!bdb->tran && !tcbdbcacheadjust(bdb)) return false;
- return true;
-}
-
-
-/* Retrieve a record in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the corresponding
- record. */
-static const char *tcbdbgetimpl(TCBDB *bdb, const char *kbuf, int ksiz, int *sp){
- assert(bdb && kbuf && ksiz >= 0 && sp);
- BDBLEAF *leaf = NULL;
- if(bdb->hleaf < 1 || !(leaf = tcbdbgethistleaf(bdb, kbuf, ksiz))){
- uint64_t pid = tcbdbsearchleaf(bdb, kbuf, ksiz);
- if(pid < 1) return NULL;
- if(!(leaf = tcbdbleafload(bdb, pid))) return NULL;
- }
- BDBREC *recp = tcbdbsearchrec(bdb, leaf, kbuf, ksiz, NULL);
- if(!recp){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return NULL;
- }
- *sp = recp->vsiz;
- return recp->vbuf;
-}
-
-
-/* Get the number of records corresponding a key in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the number of the corresponding records, else, it is 0. */
-static int tcbdbgetnum(TCBDB *bdb, const char *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- BDBLEAF *leaf = NULL;
- if(bdb->hleaf < 1 || !(leaf = tcbdbgethistleaf(bdb, kbuf, ksiz))){
- uint64_t pid = tcbdbsearchleaf(bdb, kbuf, ksiz);
- if(pid < 1) return 0;
- if(!(leaf = tcbdbleafload(bdb, pid))) return 0;
- }
- BDBREC *recp = tcbdbsearchrec(bdb, leaf, kbuf, ksiz, NULL);
- if(!recp){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return 0;
- }
- return recp->rest ? TCLISTNUM(recp->rest) + 1 : 1;
-}
-
-
-/* Retrieve records in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is a list object of the values of the corresponding records. */
-static TCLIST *tcbdbgetlist(TCBDB *bdb, const char *kbuf, int ksiz){
- assert(bdb && kbuf && ksiz >= 0);
- BDBLEAF *leaf = NULL;
- if(bdb->hleaf < 1 || !(leaf = tcbdbgethistleaf(bdb, kbuf, ksiz))){
- uint64_t pid = tcbdbsearchleaf(bdb, kbuf, ksiz);
- if(pid < 1) return NULL;
- if(!(leaf = tcbdbleafload(bdb, pid))) return NULL;
- }
- BDBREC *recp = tcbdbsearchrec(bdb, leaf, kbuf, ksiz, NULL);
- if(!recp){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return NULL;
- }
- TCLIST *vals;
- TCLIST *rest = recp->rest;
- if(rest){
- int ln = TCLISTNUM(rest);
- vals = tclistnew2(ln + 1);
- TCLISTPUSH(vals, recp->vbuf, recp->vsiz);
- for(int i = 0; i < ln; i++){
- int vsiz;
- const char *vbuf = tclistval(rest, i, &vsiz);
- TCLISTPUSH(vals, vbuf, vsiz);
- }
- } else {
- vals = tclistnew2(1);
- TCLISTPUSH(vals, recp->vbuf, recp->vsiz);
- }
- return vals;
-}
-
-
-/* Get keys of ranged records in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `bkbuf' specifies the pointer to the region of the key of the beginning border.
- `bksiz' specifies the size of the region of the beginning key.
- `binc' specifies whether the beginning border is inclusive or not.
- `ekbuf' specifies the pointer to the region of the key of the ending border.
- `eksiz' specifies the size of the region of the ending key.
- `einc' specifies whether the ending border is inclusive or not.
- `max' specifies the maximum number of keys to be fetched.
- `keys' specifies a list object to store the result.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbrangeimpl(TCBDB *bdb, const char *bkbuf, int bksiz, bool binc,
- const char *ekbuf, int eksiz, bool einc, int max, TCLIST *keys){
- assert(bdb && keys);
- bool err = false;
- BDBCUR *cur = tcbdbcurnew(bdb);
- if(bkbuf){
- tcbdbcurjumpimpl(cur, bkbuf, bksiz, true);
- } else {
- tcbdbcurfirstimpl(cur);
- }
- BDBCMP cmp = bdb->cmp;
- void *cmpop = bdb->cmpop;
- const char *lbuf = NULL;
- int lsiz = 0;
- while(cur->id > 0){
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- if(!tcbdbcurrecimpl(cur, &kbuf, &ksiz, &vbuf, &vsiz)){
- if(tchdbecode(bdb->hdb) != TCEINVALID && tchdbecode(bdb->hdb) != TCENOREC) err = true;
- break;
- }
- if(bkbuf && !binc){
- if(cmp(kbuf, ksiz, bkbuf, bksiz, cmpop) == 0){
- tcbdbcurnext(cur);
- continue;
- }
- bkbuf = NULL;
- }
- if(ekbuf){
- if(einc){
- if(cmp(kbuf, ksiz, ekbuf, eksiz, cmpop) > 0) break;
- } else {
- if(cmp(kbuf, ksiz, ekbuf, eksiz, cmpop) >= 0) break;
- }
- }
- if(!lbuf || lsiz != ksiz || memcmp(kbuf, lbuf, ksiz)){
- TCLISTPUSH(keys, kbuf, ksiz);
- if(max >= 0 && TCLISTNUM(keys) >= max) break;
- lbuf = kbuf;
- lsiz = ksiz;
- }
- tcbdbcurnextimpl(cur);
- }
- tcbdbcurdel(cur);
- return !err;
-}
-
-
-/* Get forward matching keys in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `pbuf' specifies the pointer to the region of the prefix.
- `psiz' specifies the size of the region of the prefix.
- `max' specifies the maximum number of keys to be fetched.
- `keys' specifies a list object to store the result.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbrangefwm(TCBDB *bdb, const char *pbuf, int psiz, int max, TCLIST *keys){
- assert(bdb && pbuf && psiz >= 0 && keys);
- bool err = false;
- if(max < 0) max = INT_MAX;
- BDBCUR *cur = tcbdbcurnew(bdb);
- tcbdbcurjumpimpl(cur, pbuf, psiz, true);
- const char *lbuf = NULL;
- int lsiz = 0;
- while(cur->id > 0){
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- if(!tcbdbcurrecimpl(cur, &kbuf, &ksiz, &vbuf, &vsiz)){
- if(tchdbecode(bdb->hdb) != TCEINVALID && tchdbecode(bdb->hdb) != TCENOREC) err = true;
- break;
- }
- if(ksiz < psiz || memcmp(kbuf, pbuf, psiz)) break;
- if(!lbuf || lsiz != ksiz || memcmp(kbuf, lbuf, ksiz)){
- TCLISTPUSH(keys, kbuf, ksiz);
- if(TCLISTNUM(keys) >= max) break;
- lbuf = kbuf;
- lsiz = ksiz;
- }
- tcbdbcurnextimpl(cur);
- }
- tcbdbcurdel(cur);
- return !err;
-}
-
-
-/* Optimize the file of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `lmemb' specifies the number of members in each leaf page.
- `nmemb' specifies the number of members in each non-leaf page.
- `bnum' specifies the number of elements of the bucket array.
- `apow' specifies the size of record alignment by power of 2.
- `fpow' specifies the maximum number of elements of the free block pool by power of 2.
- `opts' specifies options by bitwise or.
- If successful, the return value is true, else, it is false. */
-static bool tcbdboptimizeimpl(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
- int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(bdb);
- if(lmemb < 1) lmemb = bdb->lmemb;
- if(nmemb < 1) nmemb = bdb->nmemb;
- if(bnum < 1) bnum = tchdbrnum(bdb->hdb) * 2 + 1;
- if(opts == UINT8_MAX) opts = bdb->opts;
- const char *path = tchdbpath(bdb->hdb);
- char *tpath = tcsprintf("%s%ctmp%c%llu", path, MYEXTCHR, MYEXTCHR, tchdbinode(bdb->hdb));
- TCBDB *tbdb = tcbdbnew();
- tcbdbsetcmpfunc(tbdb, bdb->cmp, bdb->cmpop);
- tcbdbtune(tbdb, lmemb, nmemb, bnum, apow, fpow, opts);
- tcbdbsetlsmax(tbdb, bdb->lsmax);
- if(!tcbdbopen(tbdb, tpath, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
- tcbdbsetecode(bdb, tcbdbecode(tbdb), __FILE__, __LINE__, __func__);
- tcbdbdel(tbdb);
- free(tpath);
- return false;
- }
- bool err = false;
- BDBCUR *cur = tcbdbcurnew(bdb);
- tcbdbcurfirstimpl(cur);
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- while(!err && cur->id > 0 && tcbdbcurrecimpl(cur, &kbuf, &ksiz, &vbuf, &vsiz)){
- if(!tcbdbputdup(tbdb, kbuf, ksiz, vbuf, vsiz)){
- tcbdbsetecode(bdb, tcbdbecode(tbdb), __FILE__, __LINE__, __func__);
- err = true;
- }
- tcbdbcurnextimpl(cur);
- }
- tcbdbcurdel(cur);
- if(!tcbdbclose(tbdb)){
- tcbdbsetecode(bdb, tcbdbecode(tbdb), __FILE__, __LINE__, __func__);
- err = true;
- }
- tcbdbdel(tbdb);
- if(unlink(path) == -1){
- tcbdbsetecode(bdb, TCEUNLINK, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(rename(tpath, path) == -1){
- tcbdbsetecode(bdb, TCERENAME, __FILE__, __LINE__, __func__);
- err = true;
- }
- free(tpath);
- if(err) return false;
- tpath = tcstrdup(path);
- int omode = (tchdbomode(bdb->hdb) & ~BDBOCREAT) & ~BDBOTRUNC;
- if(!tcbdbcloseimpl(bdb)){
- free(tpath);
- return false;
- }
- bool rv = tcbdbopenimpl(bdb, tpath, omode);
- free(tpath);
- return rv;
-}
-
-
-/* Remove all records of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbvanishimpl(TCBDB *bdb){
- assert(bdb);
- char *path = tcstrdup(tchdbpath(bdb->hdb));
- int omode = tchdbomode(bdb->hdb);
- bool err = false;
- if(!tcbdbcloseimpl(bdb)) err = true;
- if(!tcbdbopenimpl(bdb, path, BDBOTRUNC | omode)) err = true;
- free(path);
- return !err;
-}
-
-
-/* Lock a method of the B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `wr' specifies whether the lock is writer or not.
- If successful, the return value is true, else, it is false. */
-static bool tcbdblockmethod(TCBDB *bdb, bool wr){
- assert(bdb);
- if(wr ? pthread_rwlock_wrlock(bdb->mmtx) != 0 : pthread_rwlock_rdlock(bdb->mmtx) != 0){
- tcbdbsetecode(bdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Unlock a method of the B+ tree database object.
- `hdb' specifies the B+ tree database object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbunlockmethod(TCBDB *bdb){
- assert(bdb);
- if(pthread_rwlock_unlock(bdb->mmtx) != 0){
- tcbdbsetecode(bdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Lock the cache of the B+ tree database object.
- `hdb' specifies the B+ tree database object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdblockcache(TCBDB *bdb){
- assert(bdb);
- if(pthread_mutex_lock(bdb->cmtx) != 0){
- tcbdbsetecode(bdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Unlock the cache of the B+ tree database object.
- `hdb' specifies the B+ tree database object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbunlockcache(TCBDB *bdb){
- assert(bdb);
- if(pthread_mutex_unlock(bdb->cmtx) != 0){
- tcbdbsetecode(bdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Lock the transaction of the B+ tree database object.
- `hdb' specifies the B+ tree database object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdblocktran(TCBDB *bdb){
- assert(bdb);
- if(pthread_mutex_lock(bdb->tmtx) != 0){
- tcbdbsetecode(bdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Unlock the transaction of the B+ tree database object.
- `hdb' specifies the B+ tree database object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbunlocktran(TCBDB *bdb){
- assert(bdb);
- if(pthread_mutex_unlock(bdb->tmtx) != 0){
- tcbdbsetecode(bdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Move a cursor object to the first record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcurfirstimpl(BDBCUR *cur){
- assert(cur);
- cur->id = cur->bdb->first;
- cur->kidx = 0;
- cur->vidx = 0;
- return tcbdbcuradjust(cur, true);
-}
-
-
-/* Move a cursor object to the last record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcurlastimpl(BDBCUR *cur){
- assert(cur);
- cur->id = cur->bdb->last;
- cur->kidx = INT_MAX;
- cur->vidx = INT_MAX;
- return tcbdbcuradjust(cur, false);
-}
-
-
-/* Move a cursor object to around records corresponding a key.
- `cur' specifies the cursor object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `forward' specifies whether the cursor is to be the front of records.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcurjumpimpl(BDBCUR *cur, const char *kbuf, int ksiz, bool forward){
- assert(cur && kbuf && ksiz >= 0);
- TCBDB *bdb = cur->bdb;
- uint64_t pid = tcbdbsearchleaf(bdb, kbuf, ksiz);
- if(pid < 1){
- cur->id = 0;
- cur->kidx = 0;
- cur->vidx = 0;
- return false;
- }
- BDBLEAF *leaf = tcbdbleafload(bdb, pid);
- if(!leaf){
- cur->id = 0;
- cur->kidx = 0;
- cur->vidx = 0;
- return false;
- }
- if(TCLISTNUM(leaf->recs) < 1){
- cur->id = pid;
- cur->kidx = 0;
- cur->vidx = 0;
- return forward ? tcbdbcurnextimpl(cur) : tcbdbcurprevimpl(cur);
- }
- int ri;
- BDBREC *recp = tcbdbsearchrec(bdb, leaf, kbuf, ksiz, &ri);
- if(recp){
- cur->id = pid;
- cur->kidx = ri;
- if(forward){
- cur->vidx = 0;
- } else {
- cur->vidx = recp->rest ? TCLISTNUM(recp->rest) : 0;
- }
- return true;
- }
- cur->id = leaf->id;
- if(ri > 0 && ri >= TCLISTNUM(leaf->recs)) ri = TCLISTNUM(leaf->recs) - 1;
- cur->kidx = ri;
- recp = (BDBREC *)TCLISTVALPTR(leaf->recs, ri);
- if(forward){
- int rv;
- if(bdb->cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, recp->kbuf, recp->ksiz);
- } else {
- rv = bdb->cmp(kbuf, ksiz, recp->kbuf, recp->ksiz, bdb->cmpop);
- }
- if(rv < 0) return true;
- cur->vidx = recp->rest ? TCLISTNUM(recp->rest) : 0;
- return tcbdbcurnextimpl(cur);
- }
- int rv;
- if(bdb->cmp == tcbdbcmplexical){
- TCCMPLEXICAL(rv, kbuf, ksiz, recp->kbuf, recp->ksiz);
- } else {
- rv = bdb->cmp(kbuf, ksiz, recp->kbuf, recp->ksiz, bdb->cmpop);
- }
- if(rv > 0) return true;
- cur->vidx = 0;
- return tcbdbcurprevimpl(cur);
-}
-
-
-/* Adjust a cursor object forward to the suitable record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcuradjust(BDBCUR *cur, bool forward){
- assert(cur);
- TCBDB *bdb = cur->bdb;
- while(true){
- if(cur->id < 1){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- cur->id = 0;
- cur->kidx = 0;
- cur->vidx = 0;
- return false;
- }
- BDBLEAF *leaf = tcbdbleafload(bdb, cur->id);
- if(!leaf) return false;
- TCLIST *recs = leaf->recs;
- int knum = TCLISTNUM(recs);
- if(cur->kidx < 0){
- if(forward){
- cur->kidx = 0;
- cur->vidx = 0;
- } else {
- cur->id = leaf->prev;
- cur->kidx = INT_MAX;
- cur->vidx = INT_MAX;
- }
- } else if(cur->kidx >= knum){
- if(forward){
- cur->id = leaf->next;
- cur->kidx = 0;
- cur->vidx = 0;
- } else {
- cur->kidx = knum - 1;
- cur->vidx = INT_MAX;
- }
- } else {
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, cur->kidx);
- int vnum = recp->rest ? TCLISTNUM(recp->rest) + 1 : 1;
- if(cur->vidx < 0){
- if(forward){
- cur->vidx = 0;
- } else {
- cur->kidx--;
- cur->vidx = INT_MAX;
- }
- } else if(cur->vidx >= vnum){
- if(forward){
- cur->kidx++;
- cur->vidx = 0;
- if(cur->kidx >= knum){
- cur->id = leaf->next;
- cur->kidx = 0;
- cur->vidx = 0;
- } else {
- break;
- }
- } else {
- cur->vidx = vnum - 1;
- if(cur->vidx >= 0) break;
- }
- } else {
- break;
- }
- }
- }
- return true;
-}
-
-
-/* Move a cursor object to the previous record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcurprevimpl(BDBCUR *cur){
- assert(cur);
- cur->vidx--;
- return tcbdbcuradjust(cur, false);
-}
-
-
-/* Move a cursor object to the next record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcurnextimpl(BDBCUR *cur){
- assert(cur);
- cur->vidx++;
- return tcbdbcuradjust(cur, true);
-}
-
-
-/* Insert a record around a cursor object.
- `cur' specifies the cursor object.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- `cpmode' specifies detail adjustment.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcurputimpl(BDBCUR *cur, const char *vbuf, int vsiz, int cpmode){
- assert(cur && vbuf && vsiz >= 0);
- TCBDB *bdb = cur->bdb;
- BDBLEAF *leaf = tcbdbleafload(bdb, cur->id);
- if(!leaf) return false;
- TCLIST *recs = leaf->recs;
- if(cur->kidx >= TCLISTNUM(recs)){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
- }
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, cur->kidx);
- int vnum = recp->rest ? TCLISTNUM(recp->rest) + 1 : 1;
- if(cur->vidx >= vnum){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
- }
- switch(cpmode){
- case BDBCPCURRENT:
- if(cur->vidx < 1){
- if(vsiz > recp->vsiz) TCREALLOC(recp->vbuf, recp->vbuf, vsiz + 1);
- memcpy(recp->vbuf, vbuf, vsiz);
- recp->vbuf[vsiz] = '\0';
- recp->vsiz = vsiz;
- } else {
- tclistover(recp->rest, cur->vidx - 1, vbuf, vsiz);
- }
- break;
- case BDBCPBEFORE:
- if(cur->vidx < 1){
- if(!recp->rest) recp->rest = tclistnew();
- tclistunshift(recp->rest, recp->vbuf, recp->vsiz);
- if(vsiz > recp->vsiz) TCREALLOC(recp->vbuf, recp->vbuf, vsiz + 1);
- memcpy(recp->vbuf, vbuf, vsiz);
- recp->vbuf[vsiz] = '\0';
- recp->vsiz = vsiz;
- } else {
- tclistinsert(recp->rest, cur->vidx - 1, vbuf, vsiz);
- }
- bdb->rnum++;
- break;
- case BDBCPAFTER:
- if(!recp->rest) recp->rest = tclistnew();
- tclistinsert(recp->rest, cur->vidx, vbuf, vsiz);
- cur->vidx++;
- bdb->rnum++;
- break;
- }
- leaf->dirty = true;
- return true;
-}
-
-
-/* Delete the record where a cursor object is.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. */
-static bool tcbdbcuroutimpl(BDBCUR *cur){
- assert(cur);
- TCBDB *bdb = cur->bdb;
- BDBLEAF *leaf = tcbdbleafload(bdb, cur->id);
- if(!leaf) return false;
- TCLIST *recs = leaf->recs;
- if(cur->kidx >= TCLISTNUM(recs)){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
- }
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, cur->kidx);
- int vnum = recp->rest ? TCLISTNUM(recp->rest) + 1 : 1;
- if(cur->vidx >= vnum){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
- }
- if(recp->rest){
- if(cur->vidx < 1){
- free(recp->vbuf);
- recp->vbuf = tclistshift(recp->rest, &(recp->vsiz));
- } else {
- int vsiz;
- free(tclistremove(recp->rest, cur->vidx - 1, &vsiz));
- }
- if(TCLISTNUM(recp->rest) < 1){
- tclistdel(recp->rest);
- recp->rest = NULL;
- }
- } else {
- if(TCLISTNUM(recs) < 2 && bdb->hnum > 0){
- uint64_t pid = tcbdbsearchleaf(bdb, recp->kbuf, recp->ksiz);
- if(pid < 1) return false;
- if(!(leaf = tcbdbleafload(bdb, pid))) return false;
- if(!tcbdbleafkill(bdb, leaf)) return false;
- }
- free(recp->vbuf);
- free(recp->kbuf);
- int rsiz;
- free(tclistremove(leaf->recs, cur->kidx, &rsiz));
- }
- bdb->rnum--;
- leaf->dirty = true;
- return tcbdbcuradjust(cur, true) || tchdbecode(bdb->hdb) == TCENOREC;
-}
-
-
-/* Get the key and the value of the current record of the cursor object.
- `cur' specifies the cursor object.
- `kbp' specifies the pointer to the variable into which the pointer to the region of the key is
- assgined.
- `ksp' specifies the pointer to the variable into which the size of the key region is assigned.
- `vbp' specifies the pointer to the variable into which the pointer to the region of the value
- is assgined.
- `vsp' specifies the pointer to the variable into which the size of the value region is
- assigned. */
-static bool tcbdbcurrecimpl(BDBCUR *cur, const char **kbp, int *ksp, const char **vbp, int *vsp){
- assert(cur && kbp && ksp && vbp && vsp);
- TCBDB *bdb = cur->bdb;
- BDBLEAF *leaf = tcbdbleafload(bdb, cur->id);
- if(!leaf) return false;
- TCLIST *recs = leaf->recs;
- if(cur->kidx >= TCLISTNUM(recs)){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
- }
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, cur->kidx);
- int vnum = recp->rest ? TCLISTNUM(recp->rest) + 1 : 1;
- if(cur->vidx >= vnum){
- tcbdbsetecode(bdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
- }
- *kbp = recp->kbuf;
- *ksp = recp->ksiz;
- if(cur->vidx > 0){
- *vbp = tclistval(recp->rest, cur->vidx - 1, vsp);
- } else {
- *vbp = recp->vbuf;
- *vsp = recp->vsiz;
- }
- return true;
-}
-
-
-
-/*************************************************************************************************
- * debugging functions
- *************************************************************************************************/
-
-
-/* Print meta data of the header into the debugging output.
- `bdb' specifies the B+ tree database object. */
-void tcbdbprintmeta(TCBDB *bdb){
- assert(bdb);
- int dbgfd = tchdbdbgfd(bdb->hdb);
- if(dbgfd < 0) return;
- char buf[BDBPAGEBUFSIZ];
- char *wp = buf;
- wp += sprintf(wp, "META:");
- wp += sprintf(wp, " mmtx=%p", (void *)bdb->mmtx);
- wp += sprintf(wp, " cmtx=%p", (void *)bdb->cmtx);
- wp += sprintf(wp, " tmtx=%p", (void *)bdb->tmtx);
- wp += sprintf(wp, " hdb=%p", (void *)bdb->hdb);
- wp += sprintf(wp, " opaque=%p", (void *)bdb->opaque);
- wp += sprintf(wp, " open=%d", bdb->open);
- wp += sprintf(wp, " wmode=%d", bdb->wmode);
- wp += sprintf(wp, " lmemb=%u", bdb->lmemb);
- wp += sprintf(wp, " nmemb=%u", bdb->nmemb);
- wp += sprintf(wp, " opts=%u", bdb->opts);
- wp += sprintf(wp, " root=%llu", (unsigned long long)bdb->root);
- wp += sprintf(wp, " first=%llu", (unsigned long long)bdb->first);
- wp += sprintf(wp, " last=%llu", (unsigned long long)bdb->last);
- wp += sprintf(wp, " lnum=%llu", (unsigned long long)bdb->lnum);
- wp += sprintf(wp, " nnum=%llu", (unsigned long long)bdb->nnum);
- wp += sprintf(wp, " rnum=%llu", (unsigned long long)bdb->rnum);
- wp += sprintf(wp, " leafc=%p", (void *)bdb->leafc);
- wp += sprintf(wp, " nodec=%p", (void *)bdb->nodec);
- wp += sprintf(wp, " cmp=%p", (void *)(intptr_t)bdb->cmp);
- wp += sprintf(wp, " cmpop=%p", (void *)bdb->cmpop);
- wp += sprintf(wp, " lcnum=%u", bdb->lcnum);
- wp += sprintf(wp, " ncnum=%u", bdb->ncnum);
- wp += sprintf(wp, " lsmax=%u", bdb->lsmax);
- wp += sprintf(wp, " lschk=%u", bdb->lschk);
- wp += sprintf(wp, " capnum=%llu", (unsigned long long)bdb->capnum);
- wp += sprintf(wp, " hist=%p", (void *)bdb->hist);
- wp += sprintf(wp, " hnum=%d", bdb->hnum);
- wp += sprintf(wp, " hleaf=%llu", (unsigned long long)bdb->hleaf);
- wp += sprintf(wp, " lleaf=%llu", (unsigned long long)bdb->lleaf);
- wp += sprintf(wp, " tran=%d", bdb->tran);
- wp += sprintf(wp, " rbopaque=%p", (void *)bdb->rbopaque);
- wp += sprintf(wp, " cnt_saveleaf=%lld", (long long)bdb->cnt_saveleaf);
- wp += sprintf(wp, " cnt_loadleaf=%lld", (long long)bdb->cnt_loadleaf);
- wp += sprintf(wp, " cnt_killleaf=%lld", (long long)bdb->cnt_killleaf);
- wp += sprintf(wp, " cnt_adjleafc=%lld", (long long)bdb->cnt_adjleafc);
- wp += sprintf(wp, " cnt_savenode=%lld", (long long)bdb->cnt_savenode);
- wp += sprintf(wp, " cnt_loadnode=%lld", (long long)bdb->cnt_loadnode);
- wp += sprintf(wp, " cnt_adjnodec=%lld", (long long)bdb->cnt_adjnodec);
- *(wp++) = '\n';
- tcwrite(dbgfd, buf, wp - buf);
-}
-
-
-/* Print records of a leaf object into the debugging output.
- `bdb' specifies the B+ tree database object.
- `leaf' specifies the leaf object. */
-void tcbdbprintleaf(TCBDB *bdb, BDBLEAF *leaf){
- assert(bdb && leaf);
- int dbgfd = tchdbdbgfd(bdb->hdb);
- TCLIST *recs = leaf->recs;
- if(dbgfd < 0) return;
- char buf[BDBPAGEBUFSIZ];
- char *wp = buf;
- wp += sprintf(wp, "LEAF:");
- wp += sprintf(wp, " id:%llx", (unsigned long long)leaf->id);
- wp += sprintf(wp, " prev:%llx", (unsigned long long)leaf->prev);
- wp += sprintf(wp, " next:%llx", (unsigned long long)leaf->next);
- wp += sprintf(wp, " dirty:%d", leaf->dirty);
- wp += sprintf(wp, " dead:%d", leaf->dead);
- wp += sprintf(wp, " rnum:%d", TCLISTNUM(recs));
- *(wp++) = ' ';
- for(int i = 0; i < TCLISTNUM(recs); i++){
- tcwrite(dbgfd, buf, wp - buf);
- wp = buf;
- BDBREC *recp = (BDBREC *)TCLISTVALPTR(recs, i);
- wp += sprintf(wp, " [%s:%s]", recp->kbuf, recp->vbuf);
- TCLIST *rest = recp->rest;
- if(rest){
- for(int j = 0; j < TCLISTNUM(rest); j++){
- wp += sprintf(wp, ":%s", (char *)TCLISTVALPTR(rest, j));
- }
- }
- }
- *(wp++) = '\n';
- tcwrite(dbgfd, buf, wp - buf);
-}
-
-
-/* Print indexes of a node object into the debugging output.
- `bdb' specifies the B+ tree database object.
- `node' specifies the node object. */
-void tcbdbprintnode(TCBDB *bdb, BDBNODE *node){
- assert(bdb && node);
- int dbgfd = tchdbdbgfd(bdb->hdb);
- TCLIST *idxs = node->idxs;
- if(dbgfd < 0) return;
- char buf[BDBPAGEBUFSIZ];
- char *wp = buf;
- wp += sprintf(wp, "NODE:");
- wp += sprintf(wp, " id:%llx", (unsigned long long)node->id);
- wp += sprintf(wp, " heir:%llx", (unsigned long long)node->heir);
- wp += sprintf(wp, " dirty:%d", node->dirty);
- wp += sprintf(wp, " rnum:%d", TCLISTNUM(idxs));
- *(wp++) = ' ';
- for(int i = 0; i < TCLISTNUM(idxs); i++){
- tcwrite(dbgfd, buf, wp - buf);
- wp = buf;
- BDBIDX *idxp = (BDBIDX *)TCLISTVALPTR(idxs, i);
- wp += sprintf(wp, " [%llx:%s]", (unsigned long long)idxp->pid, idxp->kbuf);
- }
- *(wp++) = '\n';
- tcwrite(dbgfd, buf, wp - buf);
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The B+ tree database API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#ifndef _TCBDB_H /* duplication check */
-#define _TCBDB_H
-
-#if defined(__cplusplus)
-#define __TCBDB_CLINKAGEBEGIN extern "C" {
-#define __TCBDB_CLINKAGEEND }
-#else
-#define __TCBDB_CLINKAGEBEGIN
-#define __TCBDB_CLINKAGEEND
-#endif
-__TCBDB_CLINKAGEBEGIN
-
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <time.h>
-#include <tcutil.h>
-#include <tchdb.h>
-
-
-
-/*************************************************************************************************
- * API
- *************************************************************************************************/
-
-
-/* type of the pointer to a comparison function.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- `op' specifies the pointer to the optional opaque object.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-typedef int (*BDBCMP)(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
-
-typedef struct { /* type of structure for a B+ tree database */
- void *mmtx; /* mutex for method */
- void *cmtx; /* mutex for cache */
- void *tmtx; /* mutex for transaction */
- TCHDB *hdb; /* internal database object */
- char *opaque; /* opaque buffer */
- bool open; /* whether the internal database is opened */
- bool wmode; /* whether to be writable */
- uint32_t lmemb; /* number of members in each leaf */
- uint32_t nmemb; /* number of members in each node */
- uint8_t opts; /* options */
- uint64_t root; /* ID number of the root page */
- uint64_t first; /* ID number of the first leaf */
- uint64_t last; /* ID number of the last leaf */
- uint64_t lnum; /* number of leaves */
- uint64_t nnum; /* number of nodes */
- uint64_t rnum; /* number of records */
- TCMAP *leafc; /* cache for leaves */
- TCMAP *nodec; /* cache for nodes */
- BDBCMP cmp; /* pointer to the comparison function */
- void *cmpop; /* opaque object for the comparison function */
- uint32_t lcnum; /* max number of cached leaves */
- uint32_t ncnum; /* max number of cached nodes */
- uint32_t lsmax; /* max size of each leaf */
- uint32_t lschk; /* counter for leaf size checking */
- uint64_t capnum; /* capacity number of records */
- uint64_t *hist; /* history array of visited nodes */
- int hnum; /* number of element of the history array */
- uint64_t hleaf; /* ID number of the leaf referred by the history */
- uint64_t lleaf; /* ID number of the last visited leaf */
- bool tran; /* whether in the transaction */
- char *rbopaque; /* opaque for rollback */
- int64_t cnt_saveleaf; /* tesing counter for leaf save times */
- int64_t cnt_loadleaf; /* tesing counter for leaf load times */
- int64_t cnt_killleaf; /* tesing counter for leaf kill times */
- int64_t cnt_adjleafc; /* tesing counter for node cache adjust times */
- int64_t cnt_savenode; /* tesing counter for node save times */
- int64_t cnt_loadnode; /* tesing counter for node load times */
- int64_t cnt_adjnodec; /* tesing counter for node cache adjust times */
-} TCBDB;
-
-enum { /* enumeration for additional flags */
- BDBFOPEN = HDBFOPEN, /* whether opened */
- BDBFFATAL = HDBFFATAL /* whetehr with fatal error */
-};
-
-enum { /* enumeration for tuning options */
- BDBTLARGE = 1 << 0, /* use 64-bit bucket array */
- BDBTDEFLATE = 1 << 1, /* compress each page with Deflate */
- BDBTTCBS = 1 << 2 /* compress each page with TCBS */
-};
-
-enum { /* enumeration for open modes */
- BDBOREADER = 1 << 0, /* open as a reader */
- BDBOWRITER = 1 << 1, /* open as a writer */
- BDBOCREAT = 1 << 2, /* writer creating */
- BDBOTRUNC = 1 << 3, /* writer truncating */
- BDBONOLCK = 1 << 4, /* open without locking */
- BDBOLCKNB = 1 << 5 /* lock without blocking */
-};
-
-typedef struct { /* type of structure for a B+ tree cursor */
- TCBDB *bdb; /* database object */
- uint64_t id; /* ID number of the leaf */
- int32_t kidx; /* number of the key */
- int32_t vidx; /* number of the value */
-} BDBCUR;
-
-enum { /* enumeration for cursor put mode */
- BDBCPCURRENT, /* current */
- BDBCPBEFORE, /* before */
- BDBCPAFTER /* after */
-};
-
-
-/* Get the message string corresponding to an error code.
- `ecode' specifies the error code.
- The return value is the message string of the error code. */
-const char *tcbdberrmsg(int ecode);
-
-
-/* Create a B+ tree database object.
- The return value is the new B+ tree database object. */
-TCBDB *tcbdbnew(void);
-
-
-/* Delete a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- If the database is not closed, it is closed implicitly. Note that the deleted object and its
- derivatives can not be used anymore. */
-void tcbdbdel(TCBDB *bdb);
-
-
-/* Get the last happened error code of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the last happened error code.
- The following error code is defined: `TCESUCCESS' for success, `TCETHREAD' for threading
- error, `TCEINVALID' for invalid operation, `TCENOFILE' for file not found, `TCENOPERM' for no
- permission, `TCEMETA' for invalid meta data, `TCERHEAD' for invalid record header, `TCEOPEN'
- for open error, `TCECLOSE' for close error, `TCETRUNC' for trunc error, `TCESYNC' for sync
- error, `TCESTAT' for stat error, `TCESEEK' for seek error, `TCEREAD' for read error,
- `TCEWRITE' for write error, `TCEMMAP' for mmap error, `TCELOCK' for lock error, `TCEUNLINK'
- for unlink error, `TCERENAME' for rename error, `TCEMKDIR' for mkdir error, `TCERMDIR' for
- rmdir error, `TCEKEEP' for existing record, `TCENOREC' for no record found, and `TCEMISC' for
- miscellaneous error. */
-int tcbdbecode(TCBDB *bdb);
-
-
-/* Set mutual exclusion control of a B+ tree database object for threading.
- `bdb' specifies the B+ tree database object which is not opened.
- If successful, the return value is true, else, it is false.
- Note that the mutual exclusion control is needed if the object is shared by plural threads and
- this function should should be called before the database is opened. */
-bool tcbdbsetmutex(TCBDB *bdb);
-
-
-/* Set the custom comparison function of a B+ tree database object.
- `bdb' specifies the B+ tree database object which is not opened.
- `cmp' specifies the pointer to the custom comparison function.
- `cmpop' specifies an arbitrary pointer to be given as a parameter of the comparison function.
- If it is not needed, `NULL' can be specified.
- If successful, the return value is true, else, it is false.
- The default comparison function compares keys of two records by lexical order. The functions
- `tcbdbcmplexical' (dafault), `tcbdbcmpdecimal', `tcbdbcmpint32', and `tcbdbcmpint64' are
- built-in. Note that the comparison function should be set before the database is opened.
- Moreover, user-defined comparison functions should be set every time the database is being
- opened. */
-bool tcbdbsetcmpfunc(TCBDB *bdb, BDBCMP cmp, void *cmpop);
-
-
-/* Set the tuning parameters of a B+ tree database object.
- `bdb' specifies the B+ tree database object which is not opened.
- `lmemb' specifies the number of members in each leaf page. If it is not more than 0, the
- default value is specified. The default value is 128.
- `nmemb' specifies the number of members in each non-leaf page. If it is not more than 0, the
- default value is specified. The default value is 256.
- `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the
- default value is specified. The default value is 16381. Suggested size of the bucket array
- is about from 1 to 4 times of the number of all pages to be stored.
- `apow' specifies the size of record alignment by power of 2. If it is negative, the default
- value is specified. The default value is 8 standing for 2^8=256.
- `fpow' specifies the maximum number of elements of the free block pool by power of 2. If it
- is negative, the default value is specified. The default value is 10 standing for 2^10=1024.
- `opts' specifies options by bitwise or: `BDBTLARGE' specifies that the size of the database
- can be larger than 2GB by using 64-bit bucket array, `BDBTDEFLATE' specifies that each page
- is compressed with Deflate encoding, `BDBTTCBS' specifies that each page is compressed with
- TCBS encoding.
- If successful, the return value is true, else, it is false.
- Note that the tuning parameters should be set before the database is opened. */
-bool tcbdbtune(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
- int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
-
-
-/* Set the caching parameters of a B+ tree database object.
- `bdb' specifies the B+ tree database object which is not opened.
- `lcnum' specifies the maximum number of leaf nodes to be cached. If it is not more than 0,
- the default value is specified. The default value is 1024.
- `ncnum' specifies the maximum number of non-leaf nodes to be cached. If it is not more than 0,
- the default value is specified. The default value is 512.
- If successful, the return value is true, else, it is false.
- Note that the caching parameters should be set before the database is opened. */
-bool tcbdbsetcache(TCBDB *bdb, int32_t lcnum, int32_t ncnum);
-
-
-/* Open a database file and connect a B+ tree database object.
- `bdb' specifies the B+ tree database object which is not opened.
- `path' specifies the path of the database file.
- `omode' specifies the connection mode: `BDBOWRITER' as a writer, `BDBOREADER' as a reader.
- If the mode is `BDBOWRITER', the following may be added by bitwise or: `BDBOCREAT', which
- means it creates a new database if not exist, `BDBOTRUNC', which means it creates a new database
- regardless if one exists. Both of `BDBOREADER' and `BDBOWRITER' can be added to by
- bitwise or: `BDBONOLCK', which means it opens the database file without file locking, or
- `BDBOLCKNB', which means locking is performed without blocking.
- If successful, the return value is true, else, it is false. */
-bool tcbdbopen(TCBDB *bdb, const char *path, int omode);
-
-
-/* Close a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- If successful, the return value is true, else, it is false.
- Update of a database is assured to be written when the database is closed. If a writer opens
- a database but does not close it appropriately, the database will be broken. */
-bool tcbdbclose(TCBDB *bdb);
-
-
-/* Store a record into a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, it is overwritten. */
-bool tcbdbput(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a string record into a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, it is overwritten. */
-bool tcbdbput2(TCBDB *bdb, const char *kstr, const char *vstr);
-
-
-/* Store a new record into a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tcbdbputkeep(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a new string record into a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tcbdbputkeep2(TCBDB *bdb, const char *kstr, const char *vstr);
-
-
-/* Concatenate a value at the end of the existing record in a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If there is no corresponding record, a new record is created. */
-bool tcbdbputcat(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Concatenate a string value at the end of the existing record in a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If there is no corresponding record, a new record is created. */
-bool tcbdbputcat2(TCBDB *bdb, const char *kstr, const char *vstr);
-
-
-/* Store a record into a B+ tree database object with allowing duplication of keys.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, the new record is placed after the
- existing one. */
-bool tcbdbputdup(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a string record into a B+ tree database object with allowing duplication of keys.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, the new record is placed after the
- existing one. */
-bool tcbdbputdup2(TCBDB *bdb, const char *kstr, const char *vstr);
-
-
-/* Store records into a B+ tree database object with allowing duplication of keys.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kbuf' specifies the pointer to the region of the common key.
- `ksiz' specifies the size of the region of the common key.
- `vals' specifies a list object containing values.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, the new records are placed after the
- existing one. */
-bool tcbdbputdup3(TCBDB *bdb, const void *kbuf, int ksiz, const TCLIST *vals);
-
-
-/* Remove a record of a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false.
- If the key of duplicated records is specified, the first one is selected. */
-bool tcbdbout(TCBDB *bdb, const void *kbuf, int ksiz);
-
-
-/* Remove a string record of a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kstr' specifies the string of the key.
- If successful, the return value is true, else, it is false.
- If the key of duplicated records is specified, the first one is selected. */
-bool tcbdbout2(TCBDB *bdb, const char *kstr);
-
-
-/* Remove records of a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false.
- If the key of duplicated records is specified, all of them are removed. */
-bool tcbdbout3(TCBDB *bdb, const void *kbuf, int ksiz);
-
-
-/* Retrieve a record in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the corresponding
- record. `NULL' is returned if no record corresponds.
- If the key of duplicated records is specified, the first one is selected. Because an
- additional zero code is appended at the end of the region of the return value, the return
- value can be treated as a character string. Because the region of the return value is
- allocated with the `malloc' call, it should be released with the `free' call when it is no
- longer in use. */
-void *tcbdbget(TCBDB *bdb, const void *kbuf, int ksiz, int *sp);
-
-
-/* Retrieve a string record in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the string of the value of the corresponding record.
- `NULL' is returned if no record corresponds.
- If the key of duplicated records is specified, the first one is selected. Because the region
- of the return value is allocated with the `malloc' call, it should be released with the `free'
- call when it is no longer in use. */
-char *tcbdbget2(TCBDB *bdb, const char *kstr);
-
-
-/* Retrieve a record in a B+ tree database object as a volatile buffer.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the corresponding
- record. `NULL' is returned if no record corresponds.
- If the key of duplicated records is specified, the first one is selected. Because an
- additional zero code is appended at the end of the region of the return value, the return
- value can be treated as a character string. Because the region of the return value is
- volatile and it may be spoiled by another operation of the database, the data should be copied
- into another involatile buffer immediately. */
-const void *tcbdbget3(TCBDB *bdb, const void *kbuf, int ksiz, int *sp);
-
-
-/* Retrieve records in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is a list object of the values of the corresponding records.
- `NULL' is returned if no record corresponds.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbget4(TCBDB *bdb, const void *kbuf, int ksiz);
-
-
-/* Get the number of records corresponding a key in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the number of the corresponding records, else, it is 0. */
-int tcbdbvnum(TCBDB *bdb, const void *kbuf, int ksiz);
-
-
-/* Get the number of records corresponding a string key in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the number of the corresponding records, else, it is 0. */
-int tcbdbvnum2(TCBDB *bdb, const char *kstr);
-
-
-/* Get the size of the value of a record in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1.
- If the key of duplicated records is specified, the first one is selected. */
-int tcbdbvsiz(TCBDB *bdb, const void *kbuf, int ksiz);
-
-
-/* Get the size of the value of a string record in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1.
- If the key of duplicated records is specified, the first one is selected. */
-int tcbdbvsiz2(TCBDB *bdb, const char *kstr);
-
-
-/* Get keys of ranged records in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `bkbuf' specifies the pointer to the region of the key of the beginning border. If it is
- `NULL', the first record is specified.
- `bksiz' specifies the size of the region of the beginning key.
- `binc' specifies whether the beginning border is inclusive or not.
- `ekbuf' specifies the pointer to the region of the key of the ending border. If it is `NULL',
- the last record is specified.
- `eksiz' specifies the size of the region of the ending key.
- `einc' specifies whether the ending border is inclusive or not.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the keys of the corresponding records. This function
- does never fail and return an empty list even if no record corresponds.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbrange(TCBDB *bdb, const void *bkbuf, int bksiz, bool binc,
- const void *ekbuf, int eksiz, bool einc, int max);
-
-
-/* Get string keys of ranged records in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `bkstr' specifies the string of the key of the beginning border. If it is `NULL', the first
- record is specified.
- `binc' specifies whether the beginning border is inclusive or not.
- `ekstr' specifies the string of the key of the ending border. If it is `NULL', the last
- record is specified.
- `einc' specifies whether the ending border is inclusive or not.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the keys of the corresponding records. This function
- does never fail and return an empty list even if no record corresponds.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbrange2(TCBDB *bdb, const char *bkstr, bool binc,
- const char *ekstr, bool einc, int max);
-
-
-/* Get forward matching keys in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `pbuf' specifies the pointer to the region of the prefix.
- `psiz' specifies the size of the region of the prefix.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the corresponding keys. This function does never fail
- and return an empty list even if no key corresponds.
- Because the object of the return value is created with the function `tclistnew', it should be
- deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbfwmkeys(TCBDB *bdb, const void *pbuf, int psiz, int max);
-
-
-/* Get forward matching string keys in a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `pstr' specifies the string of the prefix.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the corresponding keys. This function does never fail
- and return an empty list even if no key corresponds.
- Because the object of the return value is created with the function `tclistnew', it should be
- deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcbdbfwmkeys2(TCBDB *bdb, const char *pstr, int max);
-
-
-/* Synchronize updated contents of a B+ tree database object with the file and the device.
- `bdb' specifies the B+ tree database object connected as a writer.
- If successful, the return value is true, else, it is false.
- This function is useful when another process connects the same database file. */
-bool tcbdbsync(TCBDB *bdb);
-
-
-/* Optimize the file of a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- `lmemb' specifies the number of members in each leaf page. If it is not more than 0, the
- current setting is not changed.
- `nmemb' specifies the number of members in each non-leaf page. If it is not more than 0, the
- current setting is not changed.
- `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the
- default value is specified. The default value is two times of the number of pages.
- `apow' specifies the size of record alignment by power of 2. If it is negative, the current
- setting is not changed.
- `fpow' specifies the maximum number of elements of the free block pool by power of 2. If it
- is negative, the current setting is not changed.
- `opts' specifies options by bitwise or: `BDBTLARGE' specifies that the size of the database
- can be larger than 2GB by using 64-bit bucket array, `BDBTDEFLATE' specifies that each record
- is compressed with Deflate encoding, `BDBTTCBS' specifies that each page is compressed with
- TCBS encoding. If it is `UINT8_MAX', the current setting is not changed.
- If successful, the return value is true, else, it is false.
- This function is useful to reduce the size of the database file with data fragmentation by
- successive updating. */
-bool tcbdboptimize(TCBDB *bdb, int32_t lmemb, int32_t nmemb,
- int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
-
-
-/* Remove all records of a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- If successful, the return value is true, else, it is false. */
-bool tcbdbvanish(TCBDB *bdb);
-
-
-/* Copy the database file of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `path' specifies the path of the destination file. If it begins with `@', the trailing
- substring is executed as a command line.
- If successful, the return value is true, else, it is false. False is returned if the executed
- command returns non-zero code.
- The database file is assured to be kept synchronized and not modified while the copying or
- executing operation is in progress. So, this function is useful to create a backup file of
- the database file. */
-bool tcbdbcopy(TCBDB *bdb, const char *path);
-
-
-/* Begin the transaction of a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- If successful, the return value is true, else, it is false.
- The database is locked by the thread while the transaction so that only one transaction can be
- activated with a database object at the same time. Thus, the serializable isolation level is
- assumed if every database operation is performed in the transaction. If the database is
- closed during transaction, the transaction is aborted implicitly. */
-bool tcbdbtranbegin(TCBDB *bdb);
-
-
-/* Commit the transaction of a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- If successful, the return value is true, else, it is false.
- Update in the transaction is fixed when it is committed successfully. */
-bool tcbdbtrancommit(TCBDB *bdb);
-
-
-/* Abort the transaction of a B+ tree database object.
- `bdb' specifies the B+ tree database object connected as a writer.
- If successful, the return value is true, else, it is false.
- Update in the transaction is discarded when it is aborted. The state of the database is
- rollbacked to before transaction. */
-bool tcbdbtranabort(TCBDB *bdb);
-
-
-/* Get the file path of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the path of the database file or `NULL' if the object does not connect to
- any database file. */
-const char *tcbdbpath(TCBDB *bdb);
-
-
-/* Get the number of records of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the number of records or 0 if the object does not connect to any database
- file. */
-uint64_t tcbdbrnum(TCBDB *bdb);
-
-
-/* Get the size of the database file of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the size of the database file or 0 if the object does not connect to any
- database file. */
-uint64_t tcbdbfsiz(TCBDB *bdb);
-
-
-/* Create a cursor object.
- `bdb' specifies the B+ tree database object.
- The return value is the new cursor object.
- Note that the cursor is available only after initialization with the `tcbdbcurfirst' or the
- `tcbdbcurjump' functions and so on. Moreover, the position of the cursor will be indefinite
- when the database is updated after the initialization of the cursor. */
-BDBCUR *tcbdbcurnew(TCBDB *bdb);
-
-
-/* Delete a cursor object.
- `cur' specifies the cursor object. */
-void tcbdbcurdel(BDBCUR *cur);
-
-
-/* Move a cursor object to the first record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. False is returned if there is
- no record in the database. */
-bool tcbdbcurfirst(BDBCUR *cur);
-
-
-/* Move a cursor object to the last record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. False is returned if there is
- no record in the database. */
-bool tcbdbcurlast(BDBCUR *cur);
-
-
-/* Move a cursor object to the front of records corresponding a key.
- `cur' specifies the cursor object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false. False is returned if there is
- no record corresponding the condition.
- The cursor is set to the first record corresponding the key or the next substitute if
- completely matching record does not exist. */
-bool tcbdbcurjump(BDBCUR *cur, const void *kbuf, int ksiz);
-
-
-/* Move a cursor object to the front of records corresponding a key string.
- `cur' specifies the cursor object.
- `kstr' specifies the string of the key.
- If successful, the return value is true, else, it is false. False is returned if there is
- no record corresponding the condition.
- The cursor is set to the first record corresponding the key or the next substitute if
- completely matching record does not exist. */
-bool tcbdbcurjump2(BDBCUR *cur, const char *kstr);
-
-
-/* Move a cursor object to the previous record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. False is returned if there is
- no previous record. */
-bool tcbdbcurprev(BDBCUR *cur);
-
-
-/* Move a cursor object to the next record.
- `cur' specifies the cursor object.
- If successful, the return value is true, else, it is false. False is returned if there is
- no next record. */
-bool tcbdbcurnext(BDBCUR *cur);
-
-
-/* Insert a record around a cursor object.
- `cur' specifies the cursor object of writer connection.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- `cpmode' specifies detail adjustment: `BDBCPCURRENT', which means that the value of the
- current record is overwritten, `BDBCPBEFORE', which means that the new record is inserted
- before the current record, `BDBCPAFTER', which means that the new record is inserted after the
- current record.
- If successful, the return value is true, else, it is false. False is returned when the cursor
- is at invalid position.
- After insertion, the cursor is moved to the inserted record. */
-bool tcbdbcurput(BDBCUR *cur, const void *vbuf, int vsiz, int cpmode);
-
-
-/* Insert a string record around a cursor object.
- `cur' specifies the cursor object of writer connection.
- `vstr' specifies the string of the value.
- `cpmode' specifies detail adjustment: `BDBCPCURRENT', which means that the value of the
- current record is overwritten, `BDBCPBEFORE', which means that the new record is inserted
- before the current record, `BDBCPAFTER', which means that the new record is inserted after the
- current record.
- If successful, the return value is true, else, it is false. False is returned when the cursor
- is at invalid position.
- After insertion, the cursor is moved to the inserted record. */
-bool tcbdbcurput2(BDBCUR *cur, const char *vstr, int cpmode);
-
-
-/* Delete the record where a cursor object is.
- `cur' specifies the cursor object of writer connection.
- If successful, the return value is true, else, it is false. False is returned when the cursor
- is at invalid position.
- After deletion, the cursor is moved to the next record if possible. */
-bool tcbdbcurout(BDBCUR *cur);
-
-
-/* Get the key of the record where the cursor object is.
- `cur' specifies the cursor object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the key, else, it is `NULL'.
- `NULL' is returned when the cursor is at invalid position.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-char *tcbdbcurkey(BDBCUR *cur, int *sp);
-
-
-/* Get the key string of the record where the cursor object is.
- `cur' specifies the cursor object.
- If successful, the return value is the string of the key, else, it is `NULL'. `NULL' is
- returned when the cursor is at invalid position.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcbdbcurkey2(BDBCUR *cur);
-
-
-/* Get the key of the record where the cursor object is, as a volatile buffer.
- `cur' specifies the cursor object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the key, else, it is `NULL'.
- `NULL' is returned when the cursor is at invalid position.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return value
- is volatile and it may be spoiled by another operation of the database, the data should be
- copied into another involatile buffer immediately. */
-const char *tcbdbcurkey3(BDBCUR *cur, int *sp);
-
-
-/* Get the value of the record where the cursor object is.
- `cur' specifies the cursor object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value, else, it is `NULL'.
- `NULL' is returned when the cursor is at invalid position.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-char *tcbdbcurval(BDBCUR *cur, int *sp);
-
-
-/* Get the value string of the record where the cursor object is.
- `cur' specifies the cursor object.
- If successful, the return value is the string of the value, else, it is `NULL'. `NULL' is
- returned when the cursor is at invalid position.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcbdbcurval2(BDBCUR *cur);
-
-
-/* Get the value of the record where the cursor object is, as a volatile buffer.
- `cur' specifies the cursor object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value, else, it is `NULL'.
- `NULL' is returned when the cursor is at invalid position.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return value
- is volatile and it may be spoiled by another operation of the database, the data should be
- copied into another involatile buffer immediately. */
-const char *tcbdbcurval3(BDBCUR *cur, int *sp);
-
-
-/* Get the key and the value of the record where the cursor object is.
- `cur' specifies the cursor object.
- `kxstr' specifies the object into which the key is wrote down.
- `vxstr' specifies the object into which the value is wrote down.
- If successful, the return value is true, else, it is false. False is returned when the cursor
- is at invalid position. */
-bool tcbdbcurrec(BDBCUR *cur, TCXSTR *kxstr, TCXSTR *vxstr);
-
-
-
-/*************************************************************************************************
- * features for experts
- *************************************************************************************************/
-
-
-/* Set the error code of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- `ecode' specifies the error code.
- `file' specifies the file name of the code.
- `line' specifies the line number of the code.
- `func' specifies the function name of the code. */
-void tcbdbsetecode(TCBDB *bdb, int ecode, const char *filename, int line, const char *func);
-
-
-/* Set the file descriptor for debugging output.
- `bdb' specifies the B+ tree database object.
- `fd' specifies the file descriptor for debugging output. */
-void tcbdbsetdbgfd(TCBDB *bdb, int fd);
-
-
-/* Get the file descriptor for debugging output.
- `bdb' specifies the B+ tree database object.
- The return value is the file descriptor for debugging output. */
-int tcbdbdbgfd(TCBDB *bdb);
-
-
-/* Synchronize updating contents on memory.
- `bdb' specifies the B+ tree database object connected as a writer.
- `phys' specifies whether to synchronize physically.
- If successful, the return value is true, else, it is false. */
-bool tcbdbmemsync(TCBDB *bdb, bool phys);
-
-
-/* Get the comparison function of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the pointer to the comparison function. */
-BDBCMP tcbdbcmpfunc(TCBDB *bdb);
-
-
-/* Get the opaque object for the comparison function of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the opaque object for the comparison function. */
-void *tcbdbcmpop(TCBDB *bdb);
-
-
-/* Get the maximum number of cached leaf nodes of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the maximum number of cached leaf nodes. */
-uint32_t tcbdblmemb(TCBDB *bdb);
-
-
-/* Get the maximum number of cached non-leaf nodes of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the maximum number of cached non-leaf nodes. */
-uint32_t tcbdbnmemb(TCBDB *bdb);
-
-
-/* Get the number of the leaf nodes of B+ tree database object.
- `bdb' specifies the B+ tree database object.
- If successful, the return value is the number of the leaf nodes or 0 if the object does not
- connect to any database file. */
-uint64_t tcbdblnum(TCBDB *bdb);
-
-
-/* Get the number of the non-leaf nodes of B+ tree database object.
- `bdb' specifies the B+ tree database object.
- If successful, the return value is the number of the non-leaf nodes or 0 if the object does
- not connect to any database file. */
-uint64_t tcbdbnnum(TCBDB *bdb);
-
-
-/* Get the number of elements of the bucket array of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the number of elements of the bucket array or 0 if the object does not
- connect to any database file. */
-uint64_t tcbdbbnum(TCBDB *bdb);
-
-
-/* Get the record alignment of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the record alignment or 0 if the object does not connect to any database
- file. */
-uint32_t tcbdbalign(TCBDB *bdb);
-
-
-/* Get the maximum number of the free block pool of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the maximum number of the free block pool or 0 if the object does not
- connect to any database file. */
-uint32_t tcbdbfbpmax(TCBDB *bdb);
-
-
-/* Get the inode number of the database file of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the inode number of the database file or 0 the object does not connect to
- any database file. */
-uint64_t tcbdbinode(TCBDB *bdb);
-
-
-/* Get the modification time of the database file of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the inode number of the database file or 0 the object does not connect to
- any database file. */
-time_t tcbdbmtime(TCBDB *bdb);
-
-
-/* Get the additional flags of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the additional flags. */
-uint8_t tcbdbflags(TCBDB *bdb);
-
-
-/* Get the options of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the options. */
-uint8_t tcbdbopts(TCBDB *bdb);
-
-
-/* Get the pointer to the opaque field of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the pointer to the opaque field whose size is 128 bytes. */
-char *tcbdbopaque(TCBDB *bdb);
-
-
-/* Get the number of used elements of the bucket array of a B+ tree database object.
- `bdb' specifies the B+ tree database object.
- The return value is the number of used elements of the bucket array or 0 if the object does not
- connect to any database file. */
-uint64_t tcbdbbnumused(TCBDB *bdb);
-
-
-/* Set the maximum size of each leaf node.
- `bdb' specifies the B+ tree database object which is not opened.
- `lsmax' specifies the maximum size of each leaf node. If it is not more than 0, the maximum
- size is unlimited.
- If successful, the return value is true, else, it is false.
- Note that the tuning parameters of the database should be set before the database is opened. */
-bool tcbdbsetlsmax(TCBDB *bdb, uint32_t lsmax);
-
-
-/* Set the capacity number of records.
- `bdb' specifies the B+ tree database object which is not opened.
- `capnum' specifies the capacity number of records. If it is not more than 0, the capacity is
- unlimited.
- If successful, the return value is true, else, it is false.
- When the number of records exceeds the capacity, forehand records are removed implicitly.
- Note that the tuning parameters of the database should be set before the database is opened. */
-bool tcbdbsetcapnum(TCBDB *bdb, uint64_t capnum);
-
-
-/* Store a new record into a B+ tree database object with backward duplication.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, the new record is placed after the
- existing one. */
-bool tcbdbputdupback(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a new string record into a B+ tree database object with backward duplication.
- `bdb' specifies the B+ tree database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, the new record is placed after the
- existing one. */
-bool tcbdbputdupback2(TCBDB *bdb, const char *kstr, const char *vstr);
-
-
-/* Move a cursor object to the rear of records corresponding a key.
- `cur' specifies the cursor object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false. False is returned if there is
- no record corresponding the condition.
- The cursor is set to the last record corresponding the key or the previous substitute if
- completely matching record does not exist. */
-bool tcbdbcurjumpback(BDBCUR *cur, const void *kbuf, int ksiz);
-
-
-/* Move a cursor object to the rear of records corresponding a key string.
- `cur' specifies the cursor object.
- `kstr' specifies the string of the key.
- If successful, the return value is true, else, it is false. False is returned if there is
- no record corresponding the condition.
- The cursor is set to the last record corresponding the key or the previous substitute if
- completely matching record does not exist. */
-bool tcbdbcurjumpback2(BDBCUR *cur, const char *kstr);
-
-
-/* Compare two keys by lexical order.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- `op' specifies the pointer to the optional opaque object.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-int tcbdbcmplexical(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
-
-
-/* Compare two keys as decimal strings of real numbers.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- `op' is ignored.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-int tcbdbcmpdecimal(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
-
-
-/* Compare two keys as 32-bit integers in the native byte order.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- `op' is ignored.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-int tcbdbcmpint32(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
-
-
-/* Compare two keys as 64-bit integers in the native byte order.
- `aptr' specifies the pointer to the region of one key.
- `asiz' specifies the size of the region of one key.
- `bptr' specifies the pointer to the region of the other key.
- `bsiz' specifies the size of the region of the other key.
- `op' is ignored.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-int tcbdbcmpint64(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
-
-
-/* tricks for backward compatibility */
-#define tcbdbrange3 tcbdbfwmkeys2
-
-
-
-__TCBDB_CLINKAGEEND
-#endif /* duplication check */
-
-
-/* END OF FILE */
+++ /dev/null
-/*************************************************************************************************
- * The command line utility of the B+ tree database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include <tcbdb.h>
-#include "myconf.h"
-
-
-/* global variables */
-const char *g_progname; // program name
-int g_dbgfd; // debugging output
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void printerr(TCBDB *bdb);
-static int printdata(const char *ptr, int size, bool px);
-static char *hextoobj(const char *str, int *sp);
-static char *mygetline(FILE *ifp);
-static int mycmpfunc(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
-static int runcreate(int argc, char **argv);
-static int runinform(int argc, char **argv);
-static int runput(int argc, char **argv);
-static int runout(int argc, char **argv);
-static int runget(int argc, char **argv);
-static int runlist(int argc, char **argv);
-static int runoptimize(int argc, char **argv);
-static int runimporttsv(int argc, char **argv);
-static int runversion(int argc, char **argv);
-static int proccreate(const char *path, int lmemb, int nmemb,
- int bnum, int apow, int fpow, BDBCMP cmp, int opts);
-static int procinform(const char *path, int omode);
-static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- BDBCMP cmp, int omode, int dmode);
-static int procout(const char *path, const char *kbuf, int ksiz, BDBCMP cmp, int omode);
-static int procget(const char *path, const char *kbuf, int ksiz, BDBCMP cmp, int omode,
- bool px, bool pz);
-static int proclist(const char *path, BDBCMP cmp, int omode, int max, bool pv, bool px, bool bk,
- const char *jstr, const char *bstr, const char *estr, const char *fmstr);
-static int procoptimize(const char *path, int lmemb, int nmemb,
- int bnum, int apow, int fpow, BDBCMP cmp, int opts, int omode);
-static int procimporttsv(const char *path, const char *file, int omode, bool sc);
-static int procversion(void);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- g_dbgfd = -1;
- const char *ebuf = getenv("TCDBGFD");
- if(ebuf) g_dbgfd = atoi(ebuf);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "create")){
- rv = runcreate(argc, argv);
- } else if(!strcmp(argv[1], "inform")){
- rv = runinform(argc, argv);
- } else if(!strcmp(argv[1], "put")){
- rv = runput(argc, argv);
- } else if(!strcmp(argv[1], "out")){
- rv = runout(argc, argv);
- } else if(!strcmp(argv[1], "get")){
- rv = runget(argc, argv);
- } else if(!strcmp(argv[1], "list")){
- rv = runlist(argc, argv);
- } else if(!strcmp(argv[1], "optimize")){
- rv = runoptimize(argc, argv);
- } else if(!strcmp(argv[1], "importtsv")){
- rv = runimporttsv(argc, argv);
- } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){
- rv = runversion(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: the command line utility of the B+ tree database API\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s create [-cd|-ci|-cj] [-tl] [-td|-tb] path"
- " [lmemb [nmemb [bnum [apow [fpow]]]]]\n", g_progname);
- fprintf(stderr, " %s inform [-nl|-nb] path\n", g_progname);
- fprintf(stderr, " %s put [-cd|-ci|-cj] [-nl|-nb] [-sx] [-dk|-dc|-dd|-db] path"
- " key value\n", g_progname);
- fprintf(stderr, " %s out [-cd|-ci|-cj] [-nl|-nb] [-sx] path key\n", g_progname);
- fprintf(stderr, " %s get [-cd|-ci|-cj] [-nl|-nb] [-sx] [-px] [-pz] path key\n", g_progname);
- fprintf(stderr, " %s list [-cd|-ci|-cj] [-nl|-nb] [-m num] [-bk] [-pv] [-px] [-j str]"
- " [-rb bkey ekey] [-fm str] path\n", g_progname);
- fprintf(stderr, " %s optimize [-cd|-ci|-cj] [-tl] [-td|-tb] [-tz] [-nl|-nb] path"
- " [lmemb [nmemb [bnum [apow [fpow]]]]]\n", g_progname);
- fprintf(stderr, " %s importtsv [-nl|-nb] [-sc] path [file]\n", g_progname);
- fprintf(stderr, " %s version\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print error information */
-static void printerr(TCBDB *bdb){
- const char *path = tcbdbpath(bdb);
- int ecode = tcbdbecode(bdb);
- fprintf(stderr, "%s: %s: %d: %s\n", g_progname, path ? path : "-", ecode, tcbdberrmsg(ecode));
-}
-
-
-/* print record data */
-static int printdata(const char *ptr, int size, bool px){
- int len = 0;
- while(size-- > 0){
- if(px){
- if(len > 0) putchar(' ');
- len += printf("%02X", *(unsigned char *)ptr);
- } else {
- putchar(*ptr);
- len++;
- }
- ptr++;
- }
- return len;
-}
-
-
-/* create a binary object from a hexadecimal string */
-static char *hextoobj(const char *str, int *sp){
- int len = strlen(str);
- char *buf = tcmalloc(len + 1);
- int j = 0;
- for(int i = 0; i < len; i += 2){
- while(strchr(" \n\r\t\f\v", str[i])){
- i++;
- }
- char mbuf[3];
- if((mbuf[0] = str[i]) == '\0') break;
- if((mbuf[1] = str[i+1]) == '\0') break;
- mbuf[2] = '\0';
- buf[j++] = (char)strtol(mbuf, NULL, 16);
- }
- buf[j] = '\0';
- *sp = j;
- return buf;
-}
-
-
-/* read a line from a file descriptor */
-static char *mygetline(FILE *ifp){
- char *buf;
- int c, len, blen;
- buf = NULL;
- len = 0;
- blen = 256;
- while((c = fgetc(ifp)) != EOF){
- if(blen <= len) blen *= 2;
- buf = tcrealloc(buf, blen + 1);
- if(c == '\n' || c == '\r') c = '\0';
- buf[len++] = c;
- if(c == '\0') break;
- }
- if(!buf) return NULL;
- buf[len] = '\0';
- return buf;
-}
-
-
-/* dummy comparison function */
-static int mycmpfunc(const char *aptr, int asiz, const char *bptr, int bsiz, void *op){
- return 0;
-}
-
-
-/* parse arguments of create command */
-static int runcreate(int argc, char **argv){
- char *path = NULL;
- char *lmstr = NULL;
- char *nmstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- BDBCMP cmp = NULL;
- int opts = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!lmstr){
- lmstr = argv[i];
- } else if(!nmstr){
- nmstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int lmemb = lmstr ? atoi(lmstr) : -1;
- int nmemb = nmstr ? atoi(nmstr) : -1;
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = proccreate(path, lmemb, nmemb, bnum, apow, fpow, cmp, opts);
- return rv;
-}
-
-
-/* parse arguments of inform command */
-static int runinform(int argc, char **argv){
- char *path = NULL;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = procinform(path, omode);
- return rv;
-}
-
-
-/* parse arguments of put command */
-static int runput(int argc, char **argv){
- char *path = NULL;
- char *key = NULL;
- char *value = NULL;
- BDBCMP cmp = NULL;
- int omode = 0;
- int dmode = 0;
- bool sx = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-dk")){
- dmode = -1;
- } else if(!strcmp(argv[i], "-dc")){
- dmode = 1;
- } else if(!strcmp(argv[i], "-dd")){
- dmode = 2;
- } else if(!strcmp(argv[i], "-db")){
- dmode = 3;
- } else if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!key){
- key = argv[i];
- } else if(!value){
- value = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !key || !value) usage();
- int ksiz, vsiz;
- char *kbuf, *vbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- vbuf = hextoobj(value, &vsiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- vsiz = strlen(value);
- vbuf = tcmemdup(value, vsiz);
- }
- int rv = procput(path, kbuf, ksiz, vbuf, vsiz, cmp, omode, dmode);
- free(vbuf);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of out command */
-static int runout(int argc, char **argv){
- char *path = NULL;
- char *key = NULL;
- BDBCMP cmp = NULL;
- int omode = 0;
- bool sx = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!key){
- key = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !key) usage();
- int ksiz;
- char *kbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- }
- int rv = procout(path, kbuf, ksiz, cmp, omode);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of get command */
-static int runget(int argc, char **argv){
- char *path = NULL;
- char *key = NULL;
- BDBCMP cmp = NULL;
- int omode = 0;
- bool sx = false;
- bool px = false;
- bool pz = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else if(!strcmp(argv[i], "-px")){
- px = true;
- } else if(!strcmp(argv[i], "-pz")){
- pz = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!key){
- key = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !key) usage();
- int ksiz;
- char *kbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- }
- int rv = procget(path, kbuf, ksiz, cmp, omode, px, pz);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of list command */
-static int runlist(int argc, char **argv){
- char *path = NULL;
- BDBCMP cmp = NULL;
- int omode = 0;
- int max = -1;
- bool pv = false;
- bool px = false;
- bool bk = false;
- char *jstr = NULL;
- char *bstr = NULL;
- char *estr = NULL;
- char *fmstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-m")){
- if(++i >= argc) usage();
- max = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-bk")){
- bk = true;
- } else if(!strcmp(argv[i], "-pv")){
- pv = true;
- } else if(!strcmp(argv[i], "-px")){
- px = true;
- } else if(!strcmp(argv[i], "-j")){
- if(++i >= argc) usage();
- jstr = argv[i];
- } else if(!strcmp(argv[i], "-rb")){
- if(++i >= argc) usage();
- bstr = argv[i];
- if(++i >= argc) usage();
- estr = argv[i];
- } else if(!strcmp(argv[i], "-fm")){
- if(++i >= argc) usage();
- fmstr = argv[i];
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = proclist(path, cmp, omode, max, pv, px, bk, jstr, bstr, estr, fmstr);
- return rv;
-}
-
-
-/* parse arguments of optimize command */
-static int runoptimize(int argc, char **argv){
- char *path = NULL;
- char *lmstr = NULL;
- char *nmstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- BDBCMP cmp = NULL;
- int opts = UINT8_MAX;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-tl")){
- if(opts == UINT8_MAX) opts = 0;
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- if(opts == UINT8_MAX) opts = 0;
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- if(opts == UINT8_MAX) opts = 0;
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-tz")){
- if(opts == UINT8_MAX) opts = 0;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!lmstr){
- lmstr = argv[i];
- } else if(!nmstr){
- nmstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int lmemb = lmstr ? atoi(lmstr) : -1;
- int nmemb = nmstr ? atoi(nmstr) : -1;
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procoptimize(path, lmemb, nmemb, bnum, apow, fpow, cmp, opts, omode);
- return rv;
-}
-
-
-/* parse arguments of importtsv command */
-static int runimporttsv(int argc, char **argv){
- char *path = NULL;
- char *file = NULL;
- int omode = 0;
- bool sc = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-sc")){
- sc = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!file){
- file = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = procimporttsv(path, file, omode, sc);
- return rv;
-}
-
-
-/* parse arguments of version command */
-static int runversion(int argc, char **argv){
- int rv = procversion();
- return rv;
-}
-
-
-/* perform create command */
-static int proccreate(const char *path, int lmemb, int nmemb,
- int bnum, int apow, int fpow, BDBCMP cmp, int opts){
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
- if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- bool err = false;
- if(!tcbdbclose(bdb)){
- printerr(bdb);
- err = true;
- }
- tcbdbdel(bdb);
- return err ? 1 : 0;
-}
-
-
-/* perform inform command */
-static int procinform(const char *path, int omode){
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- tcbdbsetcmpfunc(bdb, mycmpfunc, NULL);
- if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- bool err = false;
- const char *npath = tcbdbpath(bdb);
- if(!npath) npath = "(unknown)";
- printf("path: %s\n", npath);
- printf("database type: btree\n");
- uint8_t flags = tcbdbflags(bdb);
- printf("additional flags:");
- if(flags & BDBFOPEN) printf(" open");
- if(flags & BDBFFATAL) printf(" fatal");
- printf("\n");
- BDBCMP cmp = tcbdbcmpfunc(bdb);
- printf("comparison function: ");
- if(cmp == tcbdbcmplexical){
- printf("lexical");
- } else if(cmp == tcbdbcmpdecimal){
- printf("decimal");
- } else if(cmp == tcbdbcmpint32){
- printf("int32");
- } else if(cmp == tcbdbcmpint64){
- printf("int64");
- } else {
- printf("custom");
- }
- printf("\n");
- printf("max leaf member: %d\n", tcbdblmemb(bdb));
- printf("max node member: %d\n", tcbdbnmemb(bdb));
- printf("leaf number: %llu\n", (unsigned long long)tcbdblnum(bdb));
- printf("node number: %llu\n", (unsigned long long)tcbdbnnum(bdb));
- printf("bucket number: %llu\n", (unsigned long long)tcbdbbnum(bdb));
- if(bdb->hdb->cnt_writerec >= 0)
- printf("used bucket number: %lld\n", (long long)tcbdbbnumused(bdb));
- printf("alignment: %u\n", tcbdbalign(bdb));
- printf("free block pool: %u\n", tcbdbfbpmax(bdb));
- printf("inode number: %lld\n", (long long)tcbdbinode(bdb));
- char date[48];
- tcdatestrwww(tcbdbmtime(bdb), INT_MAX, date);
- printf("modified time: %s\n", date);
- uint8_t opts = tcbdbopts(bdb);
- printf("options:");
- if(opts & BDBTLARGE) printf(" large");
- if(opts & BDBTDEFLATE) printf(" deflate");
- if(opts & BDBTTCBS) printf(" tcbs");
- printf("\n");
- printf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- printf("file size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- if(!tcbdbclose(bdb)){
- if(!err) printerr(bdb);
- err = true;
- }
- tcbdbdel(bdb);
- return err ? 1 : 0;
-}
-
-
-/* perform put command */
-static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- BDBCMP cmp, int omode, int dmode){
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
- if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- bool err = false;
- switch(dmode){
- case -1:
- if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz)){
- printerr(bdb);
- err = true;
- }
- break;
- case 1:
- if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
- printerr(bdb);
- err = true;
- }
- break;
- case 2:
- if(!tcbdbputdup(bdb, kbuf, ksiz, vbuf, vsiz)){
- printerr(bdb);
- err = true;
- }
- break;
- case 3:
- if(!tcbdbputdupback(bdb, kbuf, ksiz, vbuf, vsiz)){
- printerr(bdb);
- err = true;
- }
- break;
- default:
- if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
- printerr(bdb);
- err = true;
- }
- break;
- }
- if(!tcbdbclose(bdb)){
- if(!err) printerr(bdb);
- err = true;
- }
- tcbdbdel(bdb);
- return err ? 1 : 0;
-}
-
-
-/* perform out command */
-static int procout(const char *path, const char *kbuf, int ksiz, BDBCMP cmp, int omode){
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
- if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- bool err = false;
- if(!tcbdbout(bdb, kbuf, ksiz)){
- printerr(bdb);
- err = true;
- }
- if(!tcbdbclose(bdb)){
- if(!err) printerr(bdb);
- err = true;
- }
- tcbdbdel(bdb);
- return err ? 1 : 0;
-}
-
-
-/* perform get command */
-static int procget(const char *path, const char *kbuf, int ksiz, BDBCMP cmp, int omode,
- bool px, bool pz){
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
- if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- bool err = false;
- int vsiz;
- char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
- if(vbuf){
- printdata(vbuf, vsiz, px);
- if(!pz) putchar('\n');
- free(vbuf);
- } else {
- printerr(bdb);
- err = true;
- }
- if(!tcbdbclose(bdb)){
- if(!err) printerr(bdb);
- err = true;
- }
- tcbdbdel(bdb);
- return err ? 1 : 0;
-}
-
-
-/* perform list command */
-static int proclist(const char *path, BDBCMP cmp, int omode, int max, bool pv, bool px, bool bk,
- const char *jstr, const char *bstr, const char *estr, const char *fmstr){
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
- if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- bool err = false;
- if(bstr || fmstr){
- TCLIST *keys = fmstr ? tcbdbfwmkeys2(bdb, fmstr, max) :
- tcbdbrange(bdb, bstr, strlen(bstr), true, estr, strlen(estr), true, max);
- int cnt = 0;
- for(int i = 0; i < tclistnum(keys); i++){
- int ksiz;
- const char *kbuf = tclistval(keys, i, &ksiz);
- if(pv){
- TCLIST *vals = tcbdbget4(bdb, kbuf, ksiz);
- if(vals){
- for(int j = 0; j < tclistnum(vals); j++){
- int vsiz;
- const char *vbuf = tclistval(vals, j, &vsiz);
- printdata(kbuf, ksiz, px);
- putchar('\t');
- printdata(vbuf, vsiz, px);
- putchar('\n');
- if(max >= 0 && ++cnt >= max) break;
- }
- tclistdel(vals);
- }
- } else {
- int num = tcbdbvnum(bdb, kbuf, ksiz);
- for(int j = 0; j < num; j++){
- printdata(kbuf, ksiz, px);
- putchar('\n');
- if(max >= 0 && ++cnt >= max) break;
- }
- }
- if(max >= 0 && cnt >= max) break;
- }
- tclistdel(keys);
- } else {
- BDBCUR *cur = tcbdbcurnew(bdb);
- if(bk){
- if(jstr){
- if(!tcbdbcurjumpback(cur, jstr, strlen(jstr)) && tcbdbecode(bdb) != TCENOREC){
- printerr(bdb);
- err = true;
- }
- } else {
- if(!tcbdbcurlast(cur) && tcbdbecode(bdb) != TCENOREC){
- printerr(bdb);
- err = true;
- }
- }
- } else {
- if(jstr){
- if(!tcbdbcurjump(cur, jstr, strlen(jstr)) && tcbdbecode(bdb) != TCENOREC){
- printerr(bdb);
- err = true;
- }
- } else {
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- printerr(bdb);
- err = true;
- }
- }
- }
- TCXSTR *key = tcxstrnew();
- TCXSTR *val = tcxstrnew();
- int cnt = 0;
- while(tcbdbcurrec(cur, key, val)){
- printdata(tcxstrptr(key), tcxstrsize(key), px);
- if(pv){
- putchar('\t');
- printdata(tcxstrptr(val), tcxstrsize(val), px);
- }
- putchar('\n');
- if(bk){
- if(!tcbdbcurprev(cur) && tcbdbecode(bdb) != TCENOREC){
- printerr(bdb);
- err = true;
- }
- } else {
- if(!tcbdbcurnext(cur) && tcbdbecode(bdb) != TCENOREC){
- printerr(bdb);
- err = true;
- }
- }
- if(max >= 0 && ++cnt >= max) break;
- }
- tcxstrdel(val);
- tcxstrdel(key);
- tcbdbcurdel(cur);
- }
- if(!tcbdbclose(bdb)){
- if(!err) printerr(bdb);
- err = true;
- }
- tcbdbdel(bdb);
- return err ? 1 : 0;
-}
-
-
-/* perform optimize command */
-static int procoptimize(const char *path, int lmemb, int nmemb,
- int bnum, int apow, int fpow, BDBCMP cmp, int opts, int omode){
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
- if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- bool err = false;
- if(!tcbdboptimize(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
- printerr(bdb);
- err = true;
- }
- if(!tcbdbclose(bdb)){
- if(!err) printerr(bdb);
- err = true;
- }
- tcbdbdel(bdb);
- return err ? 1 : 0;
-}
-
-
-/* perform importtsv command */
-static int procimporttsv(const char *path, const char *file, int omode, bool sc){
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- FILE *ifp = file ? fopen(file, "rb") : stdin;
- if(!ifp){
- fprintf(stderr, "%s: could not open\n", file ? file : "(stdin)");
- tcbdbdel(bdb);
- return 1;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | omode)){
- printerr(bdb);
- tcbdbdel(bdb);
- return 1;
- }
- bool err = false;
- char *line;
- int cnt = 0;
- while(!err && (line = mygetline(ifp)) != NULL){
- char *pv = strchr(line, '\t');
- if(!pv) continue;
- *pv = '\0';
- if(sc) tcstrtolower(line);
- if(!tcbdbputdup2(bdb, line, pv + 1) && tcbdbecode(bdb) != TCEKEEP){
- printerr(bdb);
- err = true;
- }
- free(line);
- if(cnt > 0 && cnt % 100 == 0){
- putchar('.');
- fflush(stdout);
- if(cnt % 5000 == 0) printf(" (%08d)\n", cnt);
- }
- cnt++;
- }
- printf(" (%08d)\n", cnt);
- if(!tcbdbclose(bdb)){
- if(!err) printerr(bdb);
- err = true;
- }
- tcbdbdel(bdb);
- if(ifp != stdin) fclose(ifp);
- return err ? 1 : 0;
-}
-
-
-/* perform version command */
-static int procversion(void){
- printf("Tokyo Cabinet version %s (%d:%s)\n", tcversion, _TC_LIBVER, _TC_FORMATVER);
- printf("Copyright (C) 2006-2008 Mikio Hirabayashi\n");
- return 0;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The test cases of the B+ tree database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include <tcbdb.h>
-#include "myconf.h"
-
-#define RECBUFSIZ 32 // buffer for records
-
-typedef struct { // type of structure for write thread
- TCBDB *bdb;
- int rnum;
- bool rnd;
- int id;
-} TARGWRITE;
-
-typedef struct { // type of structure for read thread
- TCBDB *bdb;
- int rnum;
- bool wb;
- bool rnd;
- int id;
-} TARGREAD;
-
-typedef struct { // type of structure for remove thread
- TCBDB *bdb;
- int rnum;
- bool rnd;
- int id;
-} TARGREMOVE;
-
-typedef struct { // type of structure for wicked thread
- TCBDB *bdb;
- int rnum;
- bool nc;
- int id;
- TCMAP *map;
-} TARGWICKED;
-
-typedef struct { // type of structure for typical thread
- TCBDB *bdb;
- int rnum;
- bool nc;
- int rratio;
- int id;
-} TARGTYPICAL;
-
-
-/* global variables */
-const char *g_progname; // program name
-int g_dbgfd; // debugging output
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void iprintf(const char *format, ...);
-static void eprint(TCBDB *bdb, const char *func);
-static void mprint(TCBDB *bdb);
-static int myrand(int range);
-static int myrandnd(int range);
-static int runwrite(int argc, char **argv);
-static int runread(int argc, char **argv);
-static int runremove(int argc, char **argv);
-static int runwicked(int argc, char **argv);
-static int runtypical(int argc, char **argv);
-static int procwrite(const char *path, int tnum, int rnum, int lmemb, int nmemb,
- int bnum, int apow, int fpow, int opts, int omode, bool rnd);
-static int procread(const char *path, int tnum, int omode, bool wb, bool rnd);
-static int procremove(const char *path, int tnum, int omode, bool rnd);
-static int procwicked(const char *path, int tnum, int rnum, int opts, int omode, bool nc);
-static int proctypical(const char *path, int tnum, int rnum, int lmemb, int nmemb,
- int bnum, int apow, int fpow, int opts, int omode, bool nc, int rratio);
-static void *threadwrite(void *targ);
-static void *threadread(void *targ);
-static void *threadremove(void *targ);
-static void *threadwicked(void *targ);
-static void *threadtypical(void *targ);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- g_dbgfd = -1;
- const char *ebuf = getenv("TCDBGFD");
- if(ebuf) g_dbgfd = atoi(ebuf);
- srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "write")){
- rv = runwrite(argc, argv);
- } else if(!strcmp(argv[1], "read")){
- rv = runread(argc, argv);
- } else if(!strcmp(argv[1], "remove")){
- rv = runremove(argc, argv);
- } else if(!strcmp(argv[1], "wicked")){
- rv = runwicked(argc, argv);
- } else if(!strcmp(argv[1], "typical")){
- rv = runtypical(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: test cases of the B+ tree database API of Tokyo Cabinet\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s write [-tl] [-td|-tb] [-nl|-nb] [-rnd] path tnum rnum"
- " [lmemb [nmemb [bnum [apow [fpow]]]]]\n", g_progname);
- fprintf(stderr, " %s read [-nl|-nb] [-wb] [-rnd] path tnum\n", g_progname);
- fprintf(stderr, " %s remove [-nl|-nb] [-rnd] path tnum\n", g_progname);
- fprintf(stderr, " %s wicked [-tl] [-td|-tb] [-nl|-nb] [-nc] path tnum rnum\n",
- g_progname);
- fprintf(stderr, " %s typical [-tl] [-td|-tb] [-nl|-nb] [-nc] [-rr] path tnum rnum"
- " [lmemb [nmemb [bnum [apow [fpow]]]]]\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print formatted information string and flush the buffer */
-static void iprintf(const char *format, ...){
- va_list ap;
- va_start(ap, format);
- vprintf(format, ap);
- fflush(stdout);
- va_end(ap);
-}
-
-
-/* print error message of hash database */
-static void eprint(TCBDB *bdb, const char *func){
- const char *path = tcbdbpath(bdb);
- int ecode = tcbdbecode(bdb);
- fprintf(stderr, "%s: %s: %s: error: %d: %s\n",
- g_progname, path ? path : "-", func, ecode, tcbdberrmsg(ecode));
-}
-
-
-/* print members of hash database */
-static void mprint(TCBDB *bdb){
- if(bdb->hdb->cnt_writerec < 0) return;
- iprintf("max leaf member: %d\n", tcbdblmemb(bdb));
- iprintf("max node member: %d\n", tcbdbnmemb(bdb));
- iprintf("leaf number: %d\n", tcbdblnum(bdb));
- iprintf("node number: %d\n", tcbdbnnum(bdb));
- iprintf("bucket number: %lld\n", (long long)tcbdbbnum(bdb));
- iprintf("used bucket number: %lld\n", (long long)tcbdbbnumused(bdb));
- iprintf("cnt_saveleaf: %lld\n", (long long)bdb->cnt_saveleaf);
- iprintf("cnt_loadleaf: %lld\n", (long long)bdb->cnt_loadleaf);
- iprintf("cnt_killleaf: %lld\n", (long long)bdb->cnt_killleaf);
- iprintf("cnt_adjleafc: %lld\n", (long long)bdb->cnt_adjleafc);
- iprintf("cnt_savenode: %lld\n", (long long)bdb->cnt_savenode);
- iprintf("cnt_loadnode: %lld\n", (long long)bdb->cnt_loadnode);
- iprintf("cnt_adjnodec: %lld\n", (long long)bdb->cnt_adjnodec);
- iprintf("cnt_writerec: %lld\n", (long long)bdb->hdb->cnt_writerec);
- iprintf("cnt_reuserec: %lld\n", (long long)bdb->hdb->cnt_reuserec);
- iprintf("cnt_moverec: %lld\n", (long long)bdb->hdb->cnt_moverec);
- iprintf("cnt_readrec: %lld\n", (long long)bdb->hdb->cnt_readrec);
- iprintf("cnt_searchfbp: %lld\n", (long long)bdb->hdb->cnt_searchfbp);
- iprintf("cnt_insertfbp: %lld\n", (long long)bdb->hdb->cnt_insertfbp);
- iprintf("cnt_splicefbp: %lld\n", (long long)bdb->hdb->cnt_splicefbp);
- iprintf("cnt_dividefbp: %lld\n", (long long)bdb->hdb->cnt_dividefbp);
- iprintf("cnt_mergefbp: %lld\n", (long long)bdb->hdb->cnt_mergefbp);
- iprintf("cnt_reducefbp: %lld\n", (long long)bdb->hdb->cnt_reducefbp);
- iprintf("cnt_appenddrp: %lld\n", (long long)bdb->hdb->cnt_appenddrp);
- iprintf("cnt_deferdrp: %lld\n", (long long)bdb->hdb->cnt_deferdrp);
- iprintf("cnt_flushdrp: %lld\n", (long long)bdb->hdb->cnt_flushdrp);
- iprintf("cnt_adjrecc: %lld\n", (long long)bdb->hdb->cnt_adjrecc);
-}
-
-
-/* get a random number */
-static int myrand(int range){
- return (int)((double)range * rand() / (RAND_MAX + 1.0));
-}
-
-
-/* get a random number based on normal distribution */
-static int myrandnd(int range){
- int num = (int)tcdrandnd(range >> 1, range / 10);
- return (num < 0 || num >= range) ? 0 : num;
-}
-
-
-/* parse arguments of write command */
-static int runwrite(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- char *rstr = NULL;
- char *lmstr = NULL;
- char *nmstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- int opts = 0;
- int omode = 0;
- bool rnd = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-rnd")){
- rnd = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!lmstr){
- lmstr = argv[i];
- } else if(!nmstr){
- nmstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr || !rstr) usage();
- int tnum = atoi(tstr);
- int rnum = atoi(rstr);
- if(tnum < 1 || rnum < 1) usage();
- int lmemb = lmstr ? atoi(lmstr) : -1;
- int nmemb = nmstr ? atoi(nmstr) : -1;
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procwrite(path, tnum, rnum, lmemb, nmemb, bnum, apow, fpow, opts, omode, rnd);
- return rv;
-}
-
-
-/* parse arguments of read command */
-static int runread(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- int omode = 0;
- bool rnd = false;
- bool wb = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-wb")){
- wb = true;
- } else if(!strcmp(argv[i], "-rnd")){
- rnd = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr) usage();
- int tnum = atoi(tstr);
- if(tnum < 1) usage();
- int rv = procread(path, tnum, omode, wb, rnd);
- return rv;
-}
-
-
-/* parse arguments of remove command */
-static int runremove(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- int omode = 0;
- bool rnd = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-rnd")){
- rnd = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr) usage();
- int tnum = atoi(tstr);
- if(tnum < 1) usage();
- int rv = procremove(path, tnum, omode, rnd);
- return rv;
-}
-
-
-/* parse arguments of wicked command */
-static int runwicked(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- char *rstr = NULL;
- int opts = 0;
- int omode = 0;
- bool nc = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-nc")){
- nc = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr || !rstr) usage();
- int tnum = atoi(tstr);
- int rnum = atoi(rstr);
- if(tnum < 1 || rnum < 1) usage();
- int rv = procwicked(path, tnum, rnum, opts, omode, nc);
- return rv;
-}
-
-
-/* parse arguments of typical command */
-static int runtypical(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- char *rstr = NULL;
- char *lmstr = NULL;
- char *nmstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- int opts = 0;
- int omode = 0;
- int rratio = -1;
- bool nc = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-nc")){
- nc = true;
- } else if(!strcmp(argv[i], "-rr")){
- if(++i >= argc) usage();
- rratio = atoi(argv[i]);
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!lmstr){
- lmstr = argv[i];
- } else if(!nmstr){
- nmstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr || !rstr) usage();
- int tnum = atoi(tstr);
- int rnum = atoi(rstr);
- if(tnum < 1 || rnum < 1) usage();
- int lmemb = lmstr ? atoi(lmstr) : -1;
- int nmemb = nmstr ? atoi(nmstr) : -1;
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = proctypical(path, tnum, rnum, lmemb, nmemb, bnum, apow, fpow, opts, omode, nc, rratio);
- return rv;
-}
-
-
-/* perform write command */
-static int procwrite(const char *path, int tnum, int rnum, int lmemb, int nmemb,
- int bnum, int apow, int fpow, int opts, int omode, bool rnd){
- iprintf("<Writing Test>\n path=%s tnum=%d rnum=%d lmemb=%d nmemb=%d"
- " bnum=%d apow=%d fpow=%d opts=%d omode=%d rnd=%d\n\n",
- path, tnum, rnum, lmemb, nmemb, bnum, apow, fpow, opts, omode, rnd);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(!tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
- eprint(bdb, "tcbdbtune");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- TARGWRITE targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].bdb = bdb;
- targs[0].rnum = rnum;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadwrite(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].bdb = bdb;
- targs[i].rnum = rnum;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadwrite, targs + i) != 0){
- eprint(bdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(bdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform read command */
-static int procread(const char *path, int tnum, int omode, bool wb, bool rnd){
- iprintf("<Reading Test>\n path=%s tnum=%d omode=%d wb=%d rnd=%d\n\n",
- path, tnum, omode, wb, rnd);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(!tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- int rnum = tcbdbrnum(bdb) / tnum;
- TARGREAD targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].bdb = bdb;
- targs[0].rnum = rnum;
- targs[0].wb = wb;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadread(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].bdb = bdb;
- targs[i].rnum = rnum;
- targs[i].wb = wb;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadread, targs + i) != 0){
- eprint(bdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(bdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform remove command */
-static int procremove(const char *path, int tnum, int omode, bool rnd){
- iprintf("<Removing Test>\n path=%s tnum=%d omode=%d rnd=%d\n\n", path, tnum, omode, rnd);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(!tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- int rnum = tcbdbrnum(bdb) / tnum;
- TARGREMOVE targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].bdb = bdb;
- targs[0].rnum = rnum;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadremove(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].bdb = bdb;
- targs[i].rnum = rnum;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadremove, targs + i) != 0){
- eprint(bdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(bdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform wicked command */
-static int procwicked(const char *path, int tnum, int rnum, int opts, int omode, bool nc){
- iprintf("<Writing Test>\n path=%s tnum=%d rnum=%d opts=%d omode=%d nc=%d\n\n",
- path, tnum, rnum, opts, omode, nc);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(!tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(!tcbdbtune(bdb, 10, 10, rnum / 50, 10, -1, opts)){
- eprint(bdb, "tcbdbtune");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- TARGWICKED targs[tnum];
- pthread_t threads[tnum];
- TCMAP *map = tcmapnew();
- if(tnum == 1){
- targs[0].bdb = bdb;
- targs[0].rnum = rnum;
- targs[0].nc = nc;
- targs[0].id = 0;
- targs[0].map = map;
- if(threadwicked(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].bdb = bdb;
- targs[i].rnum = rnum;
- targs[i].nc = nc;
- targs[i].id = i;
- targs[i].map = map;
- targs[i].map = map;
- if(pthread_create(threads + i, NULL, threadwicked, targs + i) != 0){
- eprint(bdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(bdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- if(!nc){
- if(!tcbdbsync(bdb)){
- eprint(bdb, "tcbdbsync");
- err = true;
- }
- if(tcbdbrnum(bdb) != tcmaprnum(map)){
- eprint(bdb, "(validation)");
- err = true;
- }
- int end = rnum * tnum;
- for(int i = 1; i <= end && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", i - 1);
- int vsiz;
- const char *vbuf = tcmapget(map, kbuf, ksiz, &vsiz);
- int rsiz;
- char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
- if(vbuf){
- putchar('.');
- if(!rbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(bdb, "(validation)");
- err = true;
- }
- } else {
- putchar('*');
- if(rbuf || tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "(validation)");
- err = true;
- }
- }
- free(rbuf);
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- }
- tcmapdel(map);
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform typical command */
-static int proctypical(const char *path, int tnum, int rnum, int lmemb, int nmemb,
- int bnum, int apow, int fpow, int opts, int omode, bool nc, int rratio){
- iprintf("<Typical Access Test>\n path=%s tnum=%d rnum=%d lmemb=%d nmemb=%d"
- " bnum=%d apow=%d fpow=%d opts=%d omode=%d nc=%d rratio=%d\n\n",
- path, tnum, rnum, lmemb, nmemb, bnum, apow, fpow, opts, omode, nc, rratio);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(!tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
- eprint(bdb, "tcbdbtune");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- TARGTYPICAL targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].bdb = bdb;
- targs[0].rnum = rnum;
- targs[0].nc = nc;
- targs[0].rratio = rratio;
- targs[0].id = 0;
- if(threadtypical(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].bdb = bdb;
- targs[i].rnum = rnum;
- targs[i].nc = nc;
- targs[i].rratio = rratio;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadtypical, targs + i) != 0){
- eprint(bdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(bdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* thread the write function */
-static void *threadwrite(void *targ){
- TCBDB *bdb = ((TARGWRITE *)targ)->bdb;
- int rnum = ((TARGWRITE *)targ)->rnum;
- bool rnd = ((TARGWRITE *)targ)->rnd;
- int id = ((TARGWRITE *)targ)->id;
- bool err = false;
- int base = id * rnum;
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", base + (rnd ? myrand(i) : i));
- if(!tcbdbput(bdb, buf, len, buf, len)){
- eprint(bdb, "tcbdbput");
- err = true;
- break;
- }
- if(id <= 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- return err ? "error" : NULL;
-}
-
-
-/* thread the read function */
-static void *threadread(void *targ){
- TCBDB *bdb = ((TARGREAD *)targ)->bdb;
- int rnum = ((TARGREAD *)targ)->rnum;
- bool wb = ((TARGREAD *)targ)->wb;
- bool rnd = ((TARGREAD *)targ)->rnd;
- int id = ((TARGREAD *)targ)->id;
- bool err = false;
- int base = id * rnum;
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", base + (rnd ? myrandnd(i) : i));
- int vsiz;
- if(wb){
- int vsiz;
- const char *vbuf = tcbdbget3(bdb, kbuf, ksiz, &vsiz);
- if(!vbuf && (!rnd || tcbdbecode(bdb) != TCENOREC)){
- eprint(bdb, "tcbdbget3");
- err = true;
- }
- } else {
- char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
- if(!vbuf && (!rnd || tcbdbecode(bdb) != TCENOREC)){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- free(vbuf);
- }
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- return err ? "error" : NULL;
-}
-
-
-/* thread the remove function */
-static void *threadremove(void *targ){
- TCBDB *bdb = ((TARGREMOVE *)targ)->bdb;
- int rnum = ((TARGREMOVE *)targ)->rnum;
- bool rnd = ((TARGREMOVE *)targ)->rnd;
- int id = ((TARGREMOVE *)targ)->id;
- bool err = false;
- int base = id * rnum;
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", base + (rnd ? myrand(i + 1) : i));
- if(!tcbdbout(bdb, kbuf, ksiz) && (!rnd || tcbdbecode(bdb) != TCENOREC)){
- eprint(bdb, "tcbdbout");
- err = true;
- break;
- }
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- return err ? "error" : NULL;
-}
-
-
-/* thread the wicked function */
-static void *threadwicked(void *targ){
- TCBDB *bdb = ((TARGWICKED *)targ)->bdb;
- int rnum = ((TARGWICKED *)targ)->rnum;
- bool nc = ((TARGWICKED *)targ)->nc;
- int id = ((TARGWICKED *)targ)->id;
- TCMAP *map = ((TARGWICKED *)targ)->map;
- BDBCUR *cur = tcbdbcurnew(bdb);
- bool err = false;
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum * (id + 1)));
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '*', vsiz);
- vbuf[vsiz] = '\0';
- char *rbuf;
- if(!nc) tcglobalmutexlock();
- switch(myrand(16)){
- case 0:
- if(id == 0) putchar('0');
- if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbput");
- err = true;
- }
- if(!nc) tcmapput(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 1:
- if(id == 0) putchar('1');
- if(!tcbdbput2(bdb, kbuf, vbuf)){
- eprint(bdb, "tcbdbput2");
- err = true;
- }
- if(!nc) tcmapput2(map, kbuf, vbuf);
- break;
- case 2:
- if(id == 0) putchar('2');
- if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz) && tcbdbecode(bdb) != TCEKEEP){
- eprint(bdb, "tcbdbputkeep");
- err = true;
- }
- if(!nc) tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 3:
- if(id == 0) putchar('3');
- if(!tcbdbputkeep2(bdb, kbuf, vbuf) && tcbdbecode(bdb) != TCEKEEP){
- eprint(bdb, "tcbdbputkeep2");
- err = true;
- }
- if(!nc) tcmapputkeep2(map, kbuf, vbuf);
- break;
- case 4:
- if(id == 0) putchar('4');
- if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputcat");
- err = true;
- }
- if(!nc) tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 5:
- if(id == 0) putchar('5');
- if(!tcbdbputcat2(bdb, kbuf, vbuf)){
- eprint(bdb, "tcbdbputcat2");
- err = true;
- }
- if(!nc) tcmapputcat2(map, kbuf, vbuf);
- break;
- case 6:
- if(id == 0) putchar('6');
- if(nc){
- if(!tcbdbputdup(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputdup");
- err = true;
- }
- }
- break;
- case 7:
- if(id == 0) putchar('7');
- if(nc){
- if(!tcbdbputdup2(bdb, kbuf, vbuf)){
- eprint(bdb, "tcbdbputdup2");
- err = true;
- }
- }
- break;
- case 8:
- if(id == 0) putchar('8');
- if(myrand(10) == 0){
- if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout");
- err = true;
- }
- if(!nc) tcmapout(map, kbuf, ksiz);
- }
- break;
- case 9:
- if(id == 0) putchar('9');
- if(myrand(10) == 0){
- if(!tcbdbout2(bdb, kbuf) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout2");
- err = true;
- }
- if(!nc) tcmapout2(map, kbuf);
- }
- break;
- case 10:
- if(id == 0) putchar('A');
- if(!(rbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz))){
- if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- rbuf = tcsprintf("[%d]", myrand(i + 1));
- vsiz = strlen(rbuf);
- }
- vsiz += myrand(vsiz);
- if(myrand(3) == 0) vsiz += PATH_MAX;
- rbuf = tcrealloc(rbuf, vsiz + 1);
- for(int j = 0; j < vsiz; j++){
- rbuf[j] = myrand(0x100);
- }
- if(!tcbdbput(bdb, kbuf, ksiz, rbuf, vsiz)){
- eprint(bdb, "tcbdbput");
- err = true;
- }
- if(!nc) tcmapput(map, kbuf, ksiz, rbuf, vsiz);
- free(rbuf);
- break;
- case 11:
- if(id == 0) putchar('B');
- if(!(rbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz)) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- free(rbuf);
- break;
- case 12:
- if(id == 0) putchar('C');
- if(!(rbuf = tcbdbget2(bdb, kbuf)) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- free(rbuf);
- break;
- case 13:
- if(id == 0) putchar('D');
- if(!tcbdbget3(bdb, kbuf, ksiz, &vsiz) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- break;
- case 14:
- if(id == 0) putchar('E');
- if(myrand(rnum / 50) == 0){
- switch(myrand(5)){
- case 0:
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- break;
- case 1:
- if(!tcbdbcurlast(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- break;
- default:
- if(!tcbdbcurjump(cur, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurjump");
- err = true;
- }
- break;
- }
- }
- TCXSTR *ikey = tcxstrnew();
- TCXSTR *ival = tcxstrnew();
- for(int j = myrand(rnum) / 1000 + 1; j >= 0; j--){
- if(j % 3 == 0){
- if(!tcbdbcurrec(cur, ikey, ival)){
- int ecode = tcbdbecode(bdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(bdb, "tcbdbcurrec");
- err = true;
- }
- }
- } else {
- int iksiz;
- if(!tcbdbcurkey3(cur, &iksiz)){
- int ecode = tcbdbecode(bdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(bdb, "tcbdbcurkey3");
- err = true;
- }
- }
- }
- if(myrand(5) == 0){
- if(!tcbdbcurprev(cur)){
- int ecode = tcbdbecode(bdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(bdb, "tcbdbcurprev");
- err = true;
- }
- }
- } else {
- if(!tcbdbcurnext(cur)){
- int ecode = tcbdbecode(bdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(bdb, "tcbdbcurnext");
- err = true;
- }
- }
- }
- }
- tcxstrdel(ival);
- tcxstrdel(ikey);
- break;
- default:
- if(id == 0) putchar('@');
- if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- break;
- }
- if(!nc) tcglobalmutexunlock();
- if(id == 0){
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- if(id == 0 && i == rnum / 4){
- if(!tcbdboptimize(bdb, -1, -1, -1, -1, -1, -1)){
- eprint(bdb, "tcbdboptimize");
- err = true;
- }
- if(!tcbdbcurfirst(cur)){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- }
- }
- }
- tcbdbcurdel(cur);
- return err ? "error" : NULL;
-}
-
-
-/* thread the typical function */
-static void *threadtypical(void *targ){
- TCBDB *bdb = ((TARGTYPICAL *)targ)->bdb;
- int rnum = ((TARGTYPICAL *)targ)->rnum;
- bool nc = ((TARGTYPICAL *)targ)->nc;
- int rratio = ((TARGTYPICAL *)targ)->rratio;
- int id = ((TARGTYPICAL *)targ)->id;
- bool err = false;
- TCMAP *map = (!nc && id == 0) ? tcmapnew2(rnum + 1) : NULL;
- int base = id * rnum;
- int mrange = tclmax(50 + rratio, 100);
- BDBCUR *cur = tcbdbcurnew(bdb);
- for(int i = 1; !err && i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", base + myrandnd(i));
- int rnd = myrand(mrange);
- if(rnd < 10){
- if(!tcbdbput(bdb, buf, len, buf, len)){
- eprint(bdb, "tcbdbput");
- err = true;
- }
- if(map) tcmapput(map, buf, len, buf, len);
- } else if(rnd < 15){
- if(!tcbdbputkeep(bdb, buf, len, buf, len) && tcbdbecode(bdb) != TCEKEEP){
- eprint(bdb, "tcbdbputkeep");
- err = true;
- }
- if(map) tcmapputkeep(map, buf, len, buf, len);
- } else if(rnd < 20){
- if(!tcbdbputcat(bdb, buf, len, buf, len)){
- eprint(bdb, "tcbdbputcat");
- err = true;
- }
- if(map) tcmapputcat(map, buf, len, buf, len);
- } else if(rnd < 25){
- if(!tcbdbout(bdb, buf, len) && tcbdbecode(bdb) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout");
- err = true;
- }
- if(map) tcmapout(map, buf, len);
- } else if(rnd < 27){
- switch(myrand(3)){
- case 0:
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- for(int j = 0; !err && j < 10; j++){
- int ksiz;
- char *kbuf = tcbdbcurkey(cur, &ksiz);
- if(kbuf){
- int vsiz;
- char *vbuf = tcbdbcurval(cur, &vsiz);
- if(vbuf){
- free(vbuf);
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurval");
- err = true;
- }
- free(kbuf);
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurkey");
- err = true;
- }
- tcbdbcurnext(cur);
- }
- break;
- case 1:
- if(!tcbdbcurlast(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurlast");
- err = true;
- }
- for(int j = 0; !err && j < 10; j++){
- int ksiz;
- char *kbuf = tcbdbcurkey(cur, &ksiz);
- if(kbuf){
- int vsiz;
- char *vbuf = tcbdbcurval(cur, &vsiz);
- if(vbuf){
- free(vbuf);
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurval");
- err = true;
- }
- free(kbuf);
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurkey");
- err = true;
- }
- tcbdbcurprev(cur);
- }
- break;
- case 2:
- if(!tcbdbcurjump(cur, buf, len) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurjump");
- err = true;
- }
- for(int j = 0; !err && j < 10; j++){
- int ksiz;
- char *kbuf = tcbdbcurkey(cur, &ksiz);
- if(kbuf){
- int vsiz;
- char *vbuf = tcbdbcurval(cur, &vsiz);
- if(vbuf){
- free(vbuf);
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurval");
- err = true;
- }
- free(kbuf);
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurkey");
- err = true;
- }
- tcbdbcurnext(cur);
- }
- break;
- }
- } else {
- int vsiz;
- char *vbuf = tcbdbget(bdb, buf, len, &vsiz);
- if(vbuf){
- if(map){
- int msiz;
- const char *mbuf = tcmapget(map, buf, len, &msiz);
- if(msiz != vsiz || memcmp(mbuf, vbuf, vsiz)){
- eprint(bdb, "(validation)");
- err = true;
- }
- }
- free(vbuf);
- } else {
- if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- if(map && tcmapget(map, buf, len, &vsiz)){
- eprint(bdb, "(validation)");
- err = true;
- }
- }
- }
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- tcbdbcurdel(cur);
- if(map){
- tcmapiterinit(map);
- int ksiz;
- const char *kbuf;
- while(!err && (kbuf = tcmapiternext(map, &ksiz)) != NULL){
- int vsiz;
- char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
- if(vbuf){
- int msiz;
- const char *mbuf = tcmapget(map, kbuf, ksiz, &msiz);
- if(!mbuf || msiz != vsiz || memcmp(mbuf, vbuf, vsiz)){
- eprint(bdb, "(validation)");
- err = true;
- }
- free(vbuf);
- } else {
- eprint(bdb, "(validation)");
- err = true;
- }
- }
- tcmapdel(map);
- }
- return err ? "error" : NULL;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The test cases of the B+ tree database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include <tcbdb.h>
-#include "myconf.h"
-
-#define RECBUFSIZ 32 // buffer for records
-
-
-/* global variables */
-const char *g_progname; // program name
-int g_dbgfd; // debugging output
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void iprintf(const char *format, ...);
-static void eprint(TCBDB *bdb, const char *func);
-static void mprint(TCBDB *bdb);
-static int myrand(int range);
-static int runwrite(int argc, char **argv);
-static int runread(int argc, char **argv);
-static int runremove(int argc, char **argv);
-static int runrcat(int argc, char **argv);
-static int runqueue(int argc, char **argv);
-static int runmisc(int argc, char **argv);
-static int runwicked(int argc, char **argv);
-static int procwrite(const char *path, int rnum, int lmemb, int nmemb, int bnum,
- int apow, int fpow, bool mt, BDBCMP cmp, int opts,
- int lcnum, int ncnum, int lsmax, int capnum, int omode);
-static int procread(const char *path, bool mt, BDBCMP cmp, int lcnum, int ncnum,
- int omode, bool wb);
-static int procremove(const char *path, bool mt, BDBCMP cmp, int lcnum, int ncnum, int omode);
-static int procrcat(const char *path, int rnum,
- int lmemb, int nmemb, int bnum, int apow, int fpow,
- bool mt, BDBCMP cmp, int opts, int lcnum, int ncnum, int lsmax, int capnum,
- int omode, int pnum, bool rl);
-static int procqueue(const char *path, int rnum, int lmemb, int nmemb, int bnum,
- int apow, int fpow, bool mt, BDBCMP cmp, int opts,
- int lcnum, int ncnum, int lsmax, int capnum, int omode);
-static int procmisc(const char *path, int rnum, bool mt, int opts, int omode);
-static int procwicked(const char *path, int rnum, bool mt, int opts, int omode);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- g_dbgfd = -1;
- const char *ebuf = getenv("TCDBGFD");
- if(ebuf) g_dbgfd = atoi(ebuf);
- srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "write")){
- rv = runwrite(argc, argv);
- } else if(!strcmp(argv[1], "read")){
- rv = runread(argc, argv);
- } else if(!strcmp(argv[1], "remove")){
- rv = runremove(argc, argv);
- } else if(!strcmp(argv[1], "rcat")){
- rv = runrcat(argc, argv);
- } else if(!strcmp(argv[1], "queue")){
- rv = runqueue(argc, argv);
- } else if(!strcmp(argv[1], "misc")){
- rv = runmisc(argc, argv);
- } else if(!strcmp(argv[1], "wicked")){
- rv = runwicked(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: test cases of the B+ tree database API of Tokyo Cabinet\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s write [-mt] [-cd|-ci|-cj] [-tl] [-td|-tb] [-lc num] [-nc num]"
- " [-ls num] [-ca num] [-nl|-nb] path rnum [lmemb [nmemb [bnum [apow [fpow]]]]]\n",
- g_progname);
- fprintf(stderr, " %s read [-mt] [-cd|-ci|-cj] [-lc num] [-nc num] [-nl|-nb] [-wb]"
- " path\n", g_progname);
- fprintf(stderr, " %s remove [-mt] [-cd|-ci|-cj] [-lc num] [-nc num] [-nl|-nb]"
- " path\n", g_progname);
- fprintf(stderr, " %s rcat [-mt] [-cd|-ci|-cj] [-tl] [-td|-tb] [-lc num] [-nc num]"
- " [-ls num] [-ca num] [-nl|-nb] [-pn num] [-rl] path rnum"
- " [lmemb [nmemb [bnum [apow [fpow]]]]]\n", g_progname);
- fprintf(stderr, " %s queue [-mt] [-cd|-ci|-cj] [-tl] [-td|-tb] [-lc num] [-nc num]"
- " [-ls num] [-ca num] [-nl|-nb] path rnum [lmemb [nmemb [bnum [apow [fpow]]]]]\n",
- g_progname);
- fprintf(stderr, " %s misc [-mt] [-tl] [-td|-tb] [-nl|-nb] path rnum\n", g_progname);
- fprintf(stderr, " %s wicked [-mt] [-tl] [-td|-tb] [-nl|-nb] path rnum\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print formatted information string and flush the buffer */
-static void iprintf(const char *format, ...){
- va_list ap;
- va_start(ap, format);
- vprintf(format, ap);
- fflush(stdout);
- va_end(ap);
-}
-
-
-/* print error message of hash database */
-static void eprint(TCBDB *bdb, const char *func){
- const char *path = tcbdbpath(bdb);
- int ecode = tcbdbecode(bdb);
- fprintf(stderr, "%s: %s: %s: error: %d: %s\n",
- g_progname, path ? path : "-", func, ecode, tcbdberrmsg(ecode));
-}
-
-
-/* print members of B+ tree database */
-static void mprint(TCBDB *bdb){
- if(bdb->hdb->cnt_writerec < 0) return;
- iprintf("max leaf member: %d\n", tcbdblmemb(bdb));
- iprintf("max node member: %d\n", tcbdbnmemb(bdb));
- iprintf("leaf number: %d\n", tcbdblnum(bdb));
- iprintf("node number: %d\n", tcbdbnnum(bdb));
- iprintf("bucket number: %lld\n", (long long)tcbdbbnum(bdb));
- iprintf("used bucket number: %lld\n", (long long)tcbdbbnumused(bdb));
- iprintf("cnt_saveleaf: %lld\n", (long long)bdb->cnt_saveleaf);
- iprintf("cnt_loadleaf: %lld\n", (long long)bdb->cnt_loadleaf);
- iprintf("cnt_killleaf: %lld\n", (long long)bdb->cnt_killleaf);
- iprintf("cnt_adjleafc: %lld\n", (long long)bdb->cnt_adjleafc);
- iprintf("cnt_savenode: %lld\n", (long long)bdb->cnt_savenode);
- iprintf("cnt_loadnode: %lld\n", (long long)bdb->cnt_loadnode);
- iprintf("cnt_adjnodec: %lld\n", (long long)bdb->cnt_adjnodec);
- iprintf("cnt_writerec: %lld\n", (long long)bdb->hdb->cnt_writerec);
- iprintf("cnt_reuserec: %lld\n", (long long)bdb->hdb->cnt_reuserec);
- iprintf("cnt_moverec: %lld\n", (long long)bdb->hdb->cnt_moverec);
- iprintf("cnt_readrec: %lld\n", (long long)bdb->hdb->cnt_readrec);
- iprintf("cnt_searchfbp: %lld\n", (long long)bdb->hdb->cnt_searchfbp);
- iprintf("cnt_insertfbp: %lld\n", (long long)bdb->hdb->cnt_insertfbp);
- iprintf("cnt_splicefbp: %lld\n", (long long)bdb->hdb->cnt_splicefbp);
- iprintf("cnt_dividefbp: %lld\n", (long long)bdb->hdb->cnt_dividefbp);
- iprintf("cnt_mergefbp: %lld\n", (long long)bdb->hdb->cnt_mergefbp);
- iprintf("cnt_reducefbp: %lld\n", (long long)bdb->hdb->cnt_reducefbp);
- iprintf("cnt_appenddrp: %lld\n", (long long)bdb->hdb->cnt_appenddrp);
- iprintf("cnt_deferdrp: %lld\n", (long long)bdb->hdb->cnt_deferdrp);
- iprintf("cnt_flushdrp: %lld\n", (long long)bdb->hdb->cnt_flushdrp);
- iprintf("cnt_adjrecc: %lld\n", (long long)bdb->hdb->cnt_adjrecc);
-}
-
-
-/* get a random number */
-static int myrand(int range){
- return (int)((double)range * rand() / (RAND_MAX + 1.0));
-}
-
-
-/* parse arguments of write command */
-static int runwrite(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- char *lmstr = NULL;
- char *nmstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- bool mt = false;
- BDBCMP cmp = NULL;
- int opts = 0;
- int lcnum = 0;
- int ncnum = 0;
- int lsmax = 0;
- int capnum = 0;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-lc")){
- if(++i >= argc) usage();
- lcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nc")){
- if(++i >= argc) usage();
- ncnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-ls")){
- if(++i >= argc) usage();
- lsmax = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-ca")){
- if(++i >= argc) usage();
- capnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!lmstr){
- lmstr = argv[i];
- } else if(!nmstr){
- nmstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int lmemb = lmstr ? atoi(lmstr) : -1;
- int nmemb = nmstr ? atoi(nmstr) : -1;
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procwrite(path, rnum, lmemb, nmemb, bnum, apow, fpow,
- mt, cmp, opts, lcnum, ncnum, lsmax, capnum, omode);
- return rv;
-}
-
-
-/* parse arguments of read command */
-static int runread(int argc, char **argv){
- char *path = NULL;
- bool mt = false;
- BDBCMP cmp = NULL;
- int lcnum = 0;
- int ncnum = 0;
- int omode = 0;
- bool wb = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-lc")){
- if(++i >= argc) usage();
- lcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nc")){
- if(++i >= argc) usage();
- ncnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-wb")){
- wb = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = procread(path, mt, cmp, lcnum, ncnum, omode, wb);
- return rv;
-}
-
-
-/* parse arguments of remove command */
-static int runremove(int argc, char **argv){
- char *path = NULL;
- bool mt = false;
- BDBCMP cmp = NULL;
- int lcnum = 0;
- int ncnum = 0;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-lc")){
- if(++i >= argc) usage();
- lcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nc")){
- if(++i >= argc) usage();
- ncnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = procremove(path, mt, cmp, lcnum, ncnum, omode);
- return rv;
-}
-
-
-/* parse arguments of rcat command */
-static int runrcat(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- char *lmstr = NULL;
- char *nmstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- bool mt = false;
- BDBCMP cmp = NULL;
- int opts = 0;
- int lcnum = 0;
- int ncnum = 0;
- int lsmax = 0;
- int capnum = 0;
- int omode = 0;
- int pnum = 0;
- bool rl = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-lc")){
- if(++i >= argc) usage();
- lcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nc")){
- if(++i >= argc) usage();
- ncnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-ls")){
- if(++i >= argc) usage();
- lsmax = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-ca")){
- if(++i >= argc) usage();
- capnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else if(!strcmp(argv[i], "-pn")){
- if(++i >= argc) usage();
- pnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-rl")){
- rl = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!lmstr){
- lmstr = argv[i];
- } else if(!nmstr){
- nmstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int lmemb = lmstr ? atoi(lmstr) : -1;
- int nmemb = nmstr ? atoi(nmstr) : -1;
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procrcat(path, rnum, lmemb, nmemb, bnum, apow, fpow, mt, cmp, opts,
- lcnum, ncnum, lsmax, capnum, omode, pnum, rl);
- return rv;
-}
-
-
-/* parse arguments of queue command */
-static int runqueue(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- char *lmstr = NULL;
- char *nmstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- bool mt = false;
- BDBCMP cmp = NULL;
- int opts = 0;
- int lcnum = 0;
- int ncnum = 0;
- int lsmax = 0;
- int capnum = 0;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-cd")){
- cmp = tcbdbcmpdecimal;
- } else if(!strcmp(argv[i], "-ci")){
- cmp = tcbdbcmpint32;
- } else if(!strcmp(argv[i], "-cj")){
- cmp = tcbdbcmpint64;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-lc")){
- if(++i >= argc) usage();
- lcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nc")){
- if(++i >= argc) usage();
- ncnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-ls")){
- if(++i >= argc) usage();
- lsmax = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-ca")){
- if(++i >= argc) usage();
- capnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!lmstr){
- lmstr = argv[i];
- } else if(!nmstr){
- nmstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int lmemb = lmstr ? atoi(lmstr) : -1;
- int nmemb = nmstr ? atoi(nmstr) : -1;
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procqueue(path, rnum, lmemb, nmemb, bnum, apow, fpow,
- mt, cmp, opts, lcnum, ncnum, lsmax, capnum, omode);
- return rv;
-}
-
-
-/* parse arguments of misc command */
-static int runmisc(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- bool mt = false;
- int opts = 0;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procmisc(path, rnum, mt, opts, omode);
- return rv;
-}
-
-
-/* parse arguments of wicked command */
-static int runwicked(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- bool mt = false;
- int opts = 0;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= BDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= BDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= BDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= BDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= BDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procwicked(path, rnum, mt, opts, omode);
- return rv;
-}
-
-
-/* perform write command */
-static int procwrite(const char *path, int rnum, int lmemb, int nmemb, int bnum,
- int apow, int fpow, bool mt, BDBCMP cmp, int opts,
- int lcnum, int ncnum, int lsmax, int capnum, int omode){
- iprintf("<Writing Test>\n path=%s rnum=%d lmemb=%d nmemb=%d bnum=%d apow=%d fpow=%d"
- " mt=%d cmp=%p opts=%d lcnum=%d ncnum=%d lsmax=%d capnum=%d omode=%d\n\n",
- path, rnum, lmemb, nmemb, bnum, apow, fpow, mt, (void *)(intptr_t)cmp,
- opts, lcnum, ncnum, lsmax, capnum, omode);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(mt && !tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
- eprint(bdb, "tcbdbsetcmpfunc");
- err = true;
- }
- if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
- eprint(bdb, "tcbdbtune");
- err = true;
- }
- if(!tcbdbsetcache(bdb, lcnum, ncnum)){
- eprint(bdb, "tcbdbsetcache");
- err = true;
- }
- if(!tcbdbsetlsmax(bdb, lsmax)){
- eprint(bdb, "tcbdbsetlsmax");
- err = true;
- }
- if(!tcbdbsetcapnum(bdb, capnum)){
- eprint(bdb, "tcbdbsetcapnum");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len;
- if(cmp == tcbdbcmpdecimal){
- len = sprintf(buf, "%d", i);
- } else if(cmp == tcbdbcmpint32){
- int32_t lnum = i;
- memcpy(buf, &lnum, sizeof(lnum));
- len = sizeof(lnum);
- } else if(cmp == tcbdbcmpint64){
- int64_t llnum = i;
- memcpy(buf, &llnum, sizeof(llnum));
- len = sizeof(llnum);
- } else {
- len = sprintf(buf, "%08d", i);
- }
- if(!tcbdbput(bdb, buf, len, buf, len)){
- eprint(bdb, "tcbdbput");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform read command */
-static int procread(const char *path, bool mt, BDBCMP cmp, int lcnum, int ncnum,
- int omode, bool wb){
- iprintf("<Reading Test>\n path=%s mt=%d cmp=%p lcnum=%d ncnum=%d omode=%d wb=%d\n",
- path, mt, (void *)(intptr_t)cmp, lcnum, ncnum, omode, wb);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(mt && !tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
- eprint(bdb, "tcbdbsetcmpfunc");
- err = true;
- }
- if(!tcbdbsetcache(bdb, lcnum, ncnum)){
- eprint(bdb, "tcbdbsetcache");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- int rnum = tcbdbrnum(bdb);
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz;
- if(cmp == tcbdbcmpdecimal){
- ksiz = sprintf(kbuf, "%d", i);
- } else if(cmp == tcbdbcmpint32){
- int32_t lnum = i;
- memcpy(kbuf, &lnum, sizeof(lnum));
- ksiz = sizeof(lnum);
- } else if(cmp == tcbdbcmpint64){
- int64_t llnum = i;
- memcpy(kbuf, &llnum, sizeof(llnum));
- ksiz = sizeof(llnum);
- } else {
- ksiz = sprintf(kbuf, "%08d", i);
- }
- int vsiz;
- if(wb){
- int vsiz;
- const char *vbuf = tcbdbget3(bdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(bdb, "tcbdbget3");
- err = true;
- break;
- }
- } else {
- char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- break;
- }
- free(vbuf);
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform remove command */
-static int procremove(const char *path, bool mt, BDBCMP cmp, int lcnum, int ncnum, int omode){
- iprintf("<Removing Test>\n path=%s mt=%d cmp=%p lcnum=%d ncnum=%d omode=%d\n",
- path, mt, (void *)(intptr_t)cmp, lcnum, ncnum, omode);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(mt && !tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
- eprint(bdb, "tcbdbsetcmpfunc");
- err = true;
- }
- if(!tcbdbsetcache(bdb, lcnum, ncnum)){
- eprint(bdb, "tcbdbsetcache");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- int rnum = tcbdbrnum(bdb);
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz;
- if(cmp == tcbdbcmpdecimal){
- ksiz = sprintf(kbuf, "%d", i);
- } else if(cmp == tcbdbcmpint32){
- int32_t lnum = i;
- memcpy(kbuf, &lnum, sizeof(lnum));
- ksiz = sizeof(lnum);
- } else if(cmp == tcbdbcmpint64){
- int64_t llnum = i;
- memcpy(kbuf, &llnum, sizeof(llnum));
- ksiz = sizeof(llnum);
- } else {
- ksiz = sprintf(kbuf, "%08d", i);
- }
- if(!tcbdbout(bdb, kbuf, ksiz)){
- eprint(bdb, "tcbdbout");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform rcat command */
-static int procrcat(const char *path, int rnum,
- int lmemb, int nmemb, int bnum, int apow, int fpow,
- bool mt, BDBCMP cmp, int opts, int lcnum, int ncnum, int lsmax, int capnum,
- int omode, int pnum, bool rl){
- iprintf("<Random Concatenating Test>\n"
- " path=%s rnum=%d lmemb=%d nmemb=%d bnum=%d apow=%d fpow=%d"
- " mt=%d cmp=%p opts=%d lcnum=%d ncnum=%d lsmax=%d capnum=%d"
- " omode=%d pnum=%d rl=%d\n\n",
- path, rnum, lmemb, nmemb, bnum, apow, fpow, mt, (void *)(intptr_t)cmp,
- opts, lcnum, ncnum, lsmax, capnum, omode, pnum, rl);
- if(pnum < 1) pnum = rnum;
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(mt && !tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
- eprint(bdb, "tcbdbtune");
- err = true;
- }
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
- eprint(bdb, "tcbdbsetcmpfunc");
- err = true;
- }
- if(!tcbdbsetcache(bdb, lcnum, ncnum)){
- eprint(bdb, "tcbdbsetcache");
- err = true;
- }
- if(!tcbdbsetlsmax(bdb, lsmax)){
- eprint(bdb, "tcbdbsetlsmax");
- err = true;
- }
- if(!tcbdbsetcapnum(bdb, capnum)){
- eprint(bdb, "tcbdbsetcapnum");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz;
- if(cmp == tcbdbcmpdecimal){
- ksiz = sprintf(kbuf, "%d", myrand(pnum));
- } else if(cmp == tcbdbcmpint32){
- int32_t lnum = myrand(pnum);
- memcpy(kbuf, &lnum, sizeof(lnum));
- ksiz = sizeof(lnum);
- } else if(cmp == tcbdbcmpint64){
- int64_t llnum = myrand(pnum);
- memcpy(kbuf, &llnum, sizeof(llnum));
- ksiz = sizeof(llnum);
- } else {
- ksiz = sprintf(kbuf, "%08d", myrand(pnum));
- }
- if(rl){
- char vbuf[PATH_MAX];
- int vsiz = myrand(PATH_MAX);
- for(int j = 0; j < vsiz; j++){
- vbuf[j] = myrand(0x100);
- }
- if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputcat");
- err = true;
- break;
- }
- } else {
- if(!tcbdbputcat(bdb, kbuf, ksiz, kbuf, ksiz)){
- eprint(bdb, "tcbdbputcat");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform queue command */
-static int procqueue(const char *path, int rnum, int lmemb, int nmemb, int bnum,
- int apow, int fpow, bool mt, BDBCMP cmp, int opts,
- int lcnum, int ncnum, int lsmax, int capnum, int omode){
- iprintf("<Queueing Test>\n path=%s rnum=%d lmemb=%d nmemb=%d bnum=%d apow=%d fpow=%d"
- " mt=%d cmp=%p opts=%d lcnum=%d ncnum=%d lsmax=%d capnum=%d omode=%d\n\n",
- path, rnum, lmemb, nmemb, bnum, apow, fpow, mt, (void *)(intptr_t)cmp,
- opts, lcnum, ncnum, lsmax, capnum, omode);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(mt && !tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
- eprint(bdb, "tcbdbsetcmpfunc");
- err = true;
- }
- if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
- eprint(bdb, "tcbdbtune");
- err = true;
- }
- if(!tcbdbsetcache(bdb, lcnum, ncnum)){
- eprint(bdb, "tcbdbsetcache");
- err = true;
- }
- if(!tcbdbsetlsmax(bdb, lsmax)){
- eprint(bdb, "tcbdbsetlsmax");
- err = true;
- }
- if(!tcbdbsetcapnum(bdb, capnum)){
- eprint(bdb, "tcbdbsetcapnum");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- int deqfreq = (lmemb > 0) ? lmemb * 2 : 256;
- BDBCUR *cur = tcbdbcurnew(bdb);
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len;
- if(cmp == tcbdbcmpdecimal){
- len = sprintf(buf, "%d", i);
- } else if(cmp == tcbdbcmpint32){
- int32_t lnum = i;
- memcpy(buf, &lnum, sizeof(lnum));
- len = sizeof(lnum);
- } else if(cmp == tcbdbcmpint64){
- int64_t llnum = i;
- memcpy(buf, &llnum, sizeof(llnum));
- len = sizeof(llnum);
- } else {
- len = sprintf(buf, "%08d", i);
- }
- if(!tcbdbput(bdb, buf, len, buf, len)){
- eprint(bdb, "tcbdbput");
- err = true;
- break;
- }
- if(myrand(deqfreq) == 0){
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- break;
- }
- int num = myrand(deqfreq * 2 + 1);
- while(num >= 0){
- if(tcbdbcurout(cur)){
- num--;
- } else {
- if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurout");
- err = true;
- }
- break;
- }
- }
- if(err) break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- while(true){
- if(tcbdbcurout(cur)) continue;
- if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurout");
- err = true;
- }
- break;
- }
- tcbdbcurdel(cur);
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform misc command */
-static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
- iprintf("<Miscellaneous Test>\n path=%s rnum=%d mt=%d opts=%d omode=%d\n\n",
- path, rnum, mt, opts, omode);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(mt && !tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(!tcbdbtune(bdb, 10, 10, rnum / 50, 100, -1, opts)){
- eprint(bdb, "tcbdbtune");
- err = true;
- }
- if(!tcbdbsetcache(bdb, 128, 256)){
- eprint(bdb, "tcbdbsetcache");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- iprintf("writing:\n");
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- if(!tcbdbputkeep(bdb, buf, len, buf, len)){
- eprint(bdb, "tcbdbputkeep");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("reading:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- int vsiz;
- char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- break;
- } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
- eprint(bdb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- free(vbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(tcbdbrnum(bdb) != rnum){
- eprint(bdb, "(validation)");
- err = true;
- }
- iprintf("random writing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '*', vsiz);
- if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbput");
- err = true;
- break;
- }
- int rsiz;
- char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
- if(!rbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- break;
- }
- if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(bdb, "(validation)");
- err = true;
- free(rbuf);
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- free(rbuf);
- }
- iprintf("word writing:\n");
- const char *words[] = {
- "a", "A", "bb", "BB", "ccc", "CCC", "dddd", "DDDD", "eeeee", "EEEEEE",
- "mikio", "hirabayashi", "tokyo", "cabinet", "hyper", "estraier", "19780211", "birth day",
- "one", "first", "two", "second", "three", "third", "four", "fourth", "five", "fifth",
- "_[1]_", "uno", "_[2]_", "dos", "_[3]_", "tres", "_[4]_", "cuatro", "_[5]_", "cinco",
- "[\xe5\xb9\xb3\xe6\x9e\x97\xe5\xb9\xb9\xe9\x9b\x84]", "[\xe9\xa6\xac\xe9\xb9\xbf]", NULL
- };
- for(int i = 0; words[i] != NULL; i += 2){
- const char *kbuf = words[i];
- int ksiz = strlen(kbuf);
- const char *vbuf = words[i+1];
- int vsiz = strlen(vbuf);
- if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputkeep");
- err = true;
- break;
- }
- if(rnum > 250) putchar('.');
- }
- if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
- iprintf("random erasing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("writing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "[%d]", i);
- char vbuf[RECBUFSIZ];
- int vsiz = i % RECBUFSIZ;
- memset(vbuf, '*', vsiz);
- if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputkeep");
- err = true;
- break;
- }
- if(vsiz < 1){
- char tbuf[PATH_MAX];
- for(int j = 0; j < PATH_MAX; j++){
- tbuf[j] = myrand(0x100);
- }
- if(!tcbdbput(bdb, kbuf, ksiz, tbuf, PATH_MAX)){
- eprint(bdb, "tcbdbput");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("erasing:\n");
- for(int i = 1; i <= rnum; i++){
- if(i % 2 == 1){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "[%d]", i);
- if(!tcbdbout(bdb, kbuf, ksiz)){
- eprint(bdb, "tcbdbout");
- err = true;
- break;
- }
- if(tcbdbout(bdb, kbuf, ksiz) || tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("random writing and reopening:\n");
- for(int i = 1; i <= rnum; i++){
- if(myrand(10) == 0){
- int ksiz, vsiz;
- char *kbuf, *vbuf;
- ksiz = (myrand(5) == 0) ? myrand(UINT16_MAX) : myrand(RECBUFSIZ);
- kbuf = tcmalloc(ksiz + 1);
- for(int j = 0; j < ksiz; j++){
- kbuf[j] = 128 + myrand(128);
- }
- vsiz = (myrand(5) == 0) ? myrand(UINT16_MAX) : myrand(RECBUFSIZ);
- vbuf = tcmalloc(vsiz + 1);
- for(int j = 0; j < vsiz; j++){
- vbuf[j] = myrand(256);
- }
- switch(myrand(5)){
- case 0:
- if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbput");
- err = true;
- }
- break;
- case 1:
- if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputcat");
- err = true;
- }
- break;
- case 2:
- if(!tcbdbputdup(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputdup");
- err = true;
- }
- break;
- case 3:
- if(!tcbdbputdupback(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputdupback");
- err = true;
- }
- break;
- default:
- if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout");
- err = true;
- }
- break;
- }
- free(vbuf);
- free(kbuf);
- } else {
- char kbuf[RECBUFSIZ];
- int ksiz = myrand(RECBUFSIZ);
- memset(kbuf, '@', ksiz);
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '@', vsiz);
- if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputcat");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- iprintf("checking:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "[%d]", i);
- int vsiz;
- char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
- if(i % 2 == 0){
- if(!vbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- break;
- }
- if(vsiz != i % RECBUFSIZ && vsiz != PATH_MAX){
- eprint(bdb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- } else {
- if(vbuf || tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- }
- free(vbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("writing:\n");
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- if(!tcbdbput(bdb, buf, len, buf, len)){
- eprint(bdb, "tcbdbput");
- err = true;
- break;
- }
- if(i % 10 == 0){
- TCLIST *vals = tclistnew();
- for(int j = myrand(5) + 1; j >= 0; j--){
- tclistpush(vals, buf, len);
- }
- if(!tcbdbputdup3(bdb, buf, len, vals)){
- eprint(bdb, "tcbdbput3");
- err = true;
- break;
- }
- tclistdel(vals);
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("reading:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- int vsiz;
- char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- break;
- } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
- eprint(bdb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- free(vbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("word checking:\n");
- for(int i = 0; words[i] != NULL; i += 2){
- const char *kbuf = words[i];
- int ksiz = strlen(kbuf);
- const char *vbuf = words[i+1];
- int vsiz = strlen(vbuf);
- int rsiz;
- char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
- if(!rbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- break;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(bdb, "(validation)");
- err = true;
- free(rbuf);
- break;
- }
- free(rbuf);
- if(rnum > 250) putchar('.');
- }
- if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
- iprintf("cursor checking:\n");
- BDBCUR *cur = tcbdbcurnew(bdb);
- if(!tcbdbcurfirst(cur)){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- char *kbuf;
- int ksiz;
- int inum = 0;
- for(int i = 1; (kbuf = tcbdbcurkey(cur, &ksiz)) != NULL; i++, inum++){
- int vsiz;
- char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- free(kbuf);
- break;
- }
- free(vbuf);
- free(kbuf);
- tcbdbcurnext(cur);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(rnum > 250) iprintf(" (%08d)\n", inum);
- if(tcbdbecode(bdb) != TCENOREC || inum != tcbdbrnum(bdb)){
- eprint(bdb, "(validation)");
- err = true;
- }
- iprintf("cursor updating:\n");
- if(!tcbdbcurfirst(cur)){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- inum = 0;
- for(int i = 1; !err && (kbuf = tcbdbcurkey(cur, &ksiz)) != NULL; i++, inum++){
- switch(myrand(6)){
- case 0:
- if(!tcbdbputdup(bdb, kbuf, ksiz, "0123456789", 10)){
- eprint(bdb, "tcbdbputcat");
- err = true;
- }
- break;
- case 1:
- if(!tcbdbout(bdb, kbuf, ksiz)){
- eprint(bdb, "tcbdbout");
- err = true;
- }
- break;
- case 2:
- if(!tcbdbcurput(cur, kbuf, ksiz, BDBCPCURRENT)){
- eprint(bdb, "tcbdbcurput");
- err = true;
- }
- break;
- case 3:
- if(!tcbdbcurput(cur, kbuf, ksiz, BDBCPBEFORE)){
- eprint(bdb, "tcbdbcurput");
- err = true;
- }
- break;
- case 4:
- if(!tcbdbcurput(cur, kbuf, ksiz, BDBCPAFTER)){
- eprint(bdb, "tcbdbcurput");
- err = true;
- }
- break;
- default:
- if(!tcbdbcurout(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurout");
- err = true;
- }
- break;
- }
- free(kbuf);
- tcbdbcurnext(cur);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(rnum > 250) iprintf(" (%08d)\n", inum);
- if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "(validation)");
- err = true;
- }
- if(!tcbdbsync(bdb)){
- eprint(bdb, "tcbdbsync");
- err = true;
- }
- iprintf("cursor updating from empty:\n");
- tcbdbcurfirst(cur);
- inum = 0;
- for(int i = 1; (kbuf = tcbdbcurkey(cur, &ksiz)) != NULL; i++, inum++){
- free(kbuf);
- if(!tcbdbcurout(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurout");
- err = true;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(rnum > 250) iprintf(" (%08d)\n", inum);
- if(tcbdbrnum(bdb) != 0){
- eprint(bdb, "(validation)");
- err = true;
- }
- if(!tcbdbput2(bdb, "one", "first")){
- eprint(bdb, "tcbdbput");
- err = true;
- }
- if(!tcbdbcurlast(cur)){
- eprint(bdb, "tcbdbcurlast");
- err = true;
- }
- if(!tcbdbcurput2(cur, "second", BDBCPCURRENT) || !tcbdbcurput2(cur, "first", BDBCPBEFORE) ||
- !tcbdbcurput2(cur, "zero", BDBCPBEFORE) || !tcbdbcurput2(cur, "top", BDBCPBEFORE)){
- eprint(bdb, "tcbdbcurput2");
- err = true;
- }
- if(!tcbdbcurlast(cur)){
- eprint(bdb, "tcbdbcurlast");
- err = true;
- }
- if(!tcbdbcurput2(cur, "third", BDBCPAFTER) || !tcbdbcurput2(cur, "fourth", BDBCPAFTER) ||
- !tcbdbcurput2(cur, "end", BDBCPCURRENT) || !tcbdbcurput2(cur, "bottom", BDBCPAFTER)){
- eprint(bdb, "tcbdbcurput2");
- err = true;
- }
- iprintf("checking transaction commit:\n");
- if(!tcbdbtranbegin(bdb)){
- eprint(bdb, "tcbdbtranbegin");
- err = true;
- }
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- if(!tcbdbputdup(bdb, kbuf, ksiz, kbuf, ksiz)){
- eprint(bdb, "tcbdbputdup");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(!tcbdbtrancommit(bdb)){
- eprint(bdb, "tcbdbtrancommit");
- err = true;
- }
- iprintf("checking transaction abort:\n");
- uint64_t ornum = tcbdbrnum(bdb);
- if(!tcbdbtranbegin(bdb)){
- eprint(bdb, "tcbdbtranbegin");
- err = true;
- }
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(!tcbdbtranabort(bdb)){
- eprint(bdb, "tcbdbtranabort");
- err = true;
- }
- if(tcbdbrnum(bdb) != ornum){
- eprint(bdb, "(validation)");
- err = true;
- }
- if(ornum > 1000){
- if(!tcbdbcurfirst(cur)){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- for(int i = 1; i < 500 && !err && (kbuf = tcbdbcurkey(cur, &ksiz)) != NULL; i++){
- int vsiz;
- if(myrand(20) == 0){
- if(!tcbdbget3(bdb, kbuf, ksiz, &vsiz)){
- eprint(bdb, "tcbdbget3");
- err = true;
- }
- if(myrand(2) == 0 && !tcbdbout(bdb, kbuf, ksiz)){
- eprint(bdb, "tcbdbget3");
- err = true;
- }
- if(myrand(2) == 0 && !tcbdbputdup(bdb, kbuf, ksiz, kbuf, ksiz)){
- eprint(bdb, "tcbdbput");
- err = true;
- }
- } else {
- if(!tcbdbcurout(cur)){
- eprint(bdb, "tcbdbcurout");
- err = true;
- }
- }
- free(kbuf);
- if(myrand(30) == 0 && !tcbdbcurfirst(cur)){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- }
- }
- if(!tcbdbvanish(bdb)){
- eprint(bdb, "tcbdbvanish");
- err = true;
- }
- if(!tcbdbtranbegin(bdb)){
- eprint(bdb, "tcbdbtranbegin");
- err = true;
- }
- if(!tcbdbput2(bdb, "mikio", "hirabayashi")){
- eprint(bdb, "tcbdbput2");
- err = true;
- }
- tcbdbcurdel(cur);
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform wicked command */
-static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
- iprintf("<Wicked Writing Test>\n path=%s rnum=%d mt=%d opts=%d omode=%d\n\n",
- path, rnum, mt, opts, omode);
- bool err = false;
- double stime = tctime();
- TCBDB *bdb = tcbdbnew();
- if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
- if(mt && !tcbdbsetmutex(bdb)){
- eprint(bdb, "tcbdbsetmutex");
- err = true;
- }
- if(!tcbdbtune(bdb, 10, 10, rnum / 50, 100, -1, opts)){
- eprint(bdb, "tcbdbtune");
- err = true;
- }
- if(!tcbdbsetcache(bdb, 128, 256)){
- eprint(bdb, "tcbdbsetcache");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- BDBCUR *cur = tcbdbcurnew(bdb);
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- TCMAP *map = tcmapnew2(rnum / 5);
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '*', vsiz);
- vbuf[vsiz] = '\0';
- char *rbuf;
- switch(myrand(16)){
- case 0:
- putchar('0');
- if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbput");
- err = true;
- }
- tcmapput(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 1:
- putchar('1');
- if(!tcbdbput2(bdb, kbuf, vbuf)){
- eprint(bdb, "tcbdbput2");
- err = true;
- }
- tcmapput2(map, kbuf, vbuf);
- break;
- case 2:
- putchar('2');
- if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz) && tcbdbecode(bdb) != TCEKEEP){
- eprint(bdb, "tcbdbputkeep");
- err = true;
- }
- tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 3:
- putchar('3');
- if(!tcbdbputkeep2(bdb, kbuf, vbuf) && tcbdbecode(bdb) != TCEKEEP){
- eprint(bdb, "tcbdbputkeep2");
- err = true;
- }
- tcmapputkeep2(map, kbuf, vbuf);
- break;
- case 4:
- putchar('4');
- if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(bdb, "tcbdbputcat");
- err = true;
- }
- tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 5:
- putchar('5');
- if(!tcbdbputcat2(bdb, kbuf, vbuf)){
- eprint(bdb, "tcbdbputcat2");
- err = true;
- }
- tcmapputcat2(map, kbuf, vbuf);
- break;
- case 6:
- putchar('6');
- if(myrand(10) == 0){
- if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout");
- err = true;
- }
- tcmapout(map, kbuf, ksiz);
- }
- break;
- case 7:
- putchar('7');
- if(myrand(10) == 0){
- if(!tcbdbout2(bdb, kbuf) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout2");
- err = true;
- }
- tcmapout2(map, kbuf);
- }
- break;
- case 8:
- putchar('8');
- if(!(rbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz))){
- if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- rbuf = tcsprintf("[%d]", myrand(i + 1));
- vsiz = strlen(rbuf);
- }
- vsiz += myrand(vsiz);
- if(myrand(3) == 0) vsiz += PATH_MAX;
- rbuf = tcrealloc(rbuf, vsiz + 1);
- for(int j = 0; j < vsiz; j++){
- rbuf[j] = myrand(0x100);
- }
- if(!tcbdbput(bdb, kbuf, ksiz, rbuf, vsiz)){
- eprint(bdb, "tcbdbput");
- err = true;
- }
- tcmapput(map, kbuf, ksiz, rbuf, vsiz);
- free(rbuf);
- break;
- case 9:
- putchar('9');
- if(!(rbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz)) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- free(rbuf);
- break;
- case 10:
- putchar('A');
- if(!(rbuf = tcbdbget2(bdb, kbuf)) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- free(rbuf);
- break;
- case 11:
- putchar('B');
- if(myrand(1) == 0) vsiz = 1;
- if(!tcbdbget3(bdb, kbuf, ksiz, &vsiz) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbget");
- err = true;
- }
- break;
- case 12:
- putchar('C');
- if(myrand(rnum / 50) == 0){
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- }
- TCXSTR *ikey = tcxstrnew();
- TCXSTR *ival = tcxstrnew();
- for(int j = myrand(rnum) / 1000 + 1; j >= 0; j--){
- if(j % 3 == 0){
- if(tcbdbcurrec(cur, ikey, ival)){
- if(tcbdbvnum(bdb, tcxstrptr(ikey), tcxstrsize(ikey)) != 1){
- eprint(bdb, "(validation)");
- err = true;
- }
- if(tcxstrsize(ival) != tcbdbvsiz(bdb, tcxstrptr(ikey), tcxstrsize(ikey))){
- eprint(bdb, "(validation)");
- err = true;
- }
- } else {
- int ecode = tcbdbecode(bdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(bdb, "tcbdbcurrec");
- err = true;
- }
- }
- } else {
- int iksiz;
- char *ikbuf = tcbdbcurkey(cur, &iksiz);
- if(ikbuf){
- free(ikbuf);
- } else {
- int ecode = tcbdbecode(bdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(bdb, "tcbdbcurkey");
- err = true;
- }
- }
- }
- tcbdbcurnext(cur);
- }
- tcxstrdel(ival);
- tcxstrdel(ikey);
- break;
- default:
- putchar('@');
- if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(myrand(rnum / 32 + 1) == 0){
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- int cnt = myrand(30);
- for(int j = 0; j < rnum && !err; j++){
- ksiz = sprintf(kbuf, "%d", i + j);
- if(myrand(4) == 0){
- if(tcbdbout3(bdb, kbuf, ksiz)){
- cnt--;
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout3");
- err = true;
- }
- tcmapout(map, kbuf, ksiz);
- } else if(myrand(30) == 0){
- int tksiz;
- char *tkbuf = tcbdbcurkey(cur, &tksiz);
- if(tkbuf){
- if(tcbdbcurout(cur)){
- cnt--;
- } else {
- eprint(bdb, "tcbdbcurout");
- err = true;
- }
- tcmapout(map, tkbuf, tksiz);
- free(tkbuf);
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- } else {
- if(tcbdbout(bdb, kbuf, ksiz)){
- cnt--;
- } else if(tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbout");
- err = true;
- }
- tcmapout(map, kbuf, ksiz);
- }
- if(cnt < 0) break;
- }
- }
- break;
- }
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- if(i == rnum / 2){
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
- eprint(bdb, "tcbdbopen");
- err = true;
- }
- } else if(i == rnum / 4){
- char *npath = tcsprintf("%s-tmp", path);
- if(!tcbdbcopy(bdb, npath)){
- eprint(bdb, "tcbdbcopy");
- err = true;
- }
- TCBDB *nbdb = tcbdbnew();
- if(!tcbdbopen(nbdb, npath, BDBOREADER | omode)){
- eprint(nbdb, "tcbdbopen");
- err = true;
- }
- tcbdbdel(nbdb);
- unlink(npath);
- free(npath);
- if(!tcbdboptimize(bdb, -1, -1, -1, -1, -1, -1)){
- eprint(bdb, "tcbdboptimize");
- err = true;
- }
- if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "tcbdbcurfirst");
- err = true;
- }
- } else if(i == rnum / 8){
- if(!tcbdbtranbegin(bdb)){
- eprint(bdb, "tcbdbtranbegin");
- err = true;
- }
- } else if(i == rnum / 8 + rnum / 16){
- if(!tcbdbtrancommit(bdb)){
- eprint(bdb, "tcbdbtrancommit");
- err = true;
- }
- }
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- if(!tcbdbsync(bdb)){
- eprint(bdb, "tcbdbsync");
- err = true;
- }
- if(tcbdbrnum(bdb) != tcmaprnum(map)){
- eprint(bdb, "(validation)");
- err = true;
- }
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", i - 1);
- int vsiz;
- const char *vbuf = tcmapget(map, kbuf, ksiz, &vsiz);
- int rsiz;
- char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
- if(vbuf){
- putchar('.');
- if(!rbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(bdb, "(validation)");
- err = true;
- }
- } else {
- putchar('*');
- if(rbuf || tcbdbecode(bdb) != TCENOREC){
- eprint(bdb, "(validation)");
- err = true;
- }
- }
- free(rbuf);
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- tcmapiterinit(map);
- int ksiz;
- const char *kbuf;
- for(int i = 1; (kbuf = tcmapiternext(map, &ksiz)) != NULL; i++){
- putchar('+');
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- int rsiz;
- char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
- if(!rbuf){
- eprint(bdb, "tcbdbget");
- err = true;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(bdb, "(validation)");
- err = true;
- }
- free(rbuf);
- if(!tcbdbout(bdb, kbuf, ksiz)){
- eprint(bdb, "tcbdbout");
- err = true;
- }
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- int mrnum = tcmaprnum(map);
- if(mrnum % 50 > 0) iprintf(" (%08d)\n", mrnum);
- if(tcbdbrnum(bdb) != 0){
- eprint(bdb, "(validation)");
- err = true;
- }
- tcbdbcurdel(cur);
- iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
- iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
- mprint(bdb);
- tcmapdel(map);
- if(!tcbdbclose(bdb)){
- eprint(bdb, "tcbdbclose");
- err = true;
- }
- tcbdbdel(bdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The hash database API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include "tcutil.h"
-#include "tchdb.h"
-#include "myconf.h"
-
-#define HDBFILEMODE 00644 // permission of created files
-#define HDBIOBUFSIZ 8192 // size of an I/O buffer
-
-#define HDBMAGICDATA "ToKyO CaBiNeT" // magic data for identification
-#define HDBHEADSIZ 256 // size of the reagion of the header
-#define HDBTYPEOFF 32 // offset of the region for the database type
-#define HDBFLAGSOFF 33 // offset of the region for the additional flags
-#define HDBAPOWOFF 34 // offset of the region for the alignment power
-#define HDBFPOWOFF 35 // offset of the region for the free block pool power
-#define HDBOPTSOFF 36 // offset of the region for the options
-#define HDBBNUMOFF 40 // offset of the region for the bucket number
-#define HDBRNUMOFF 48 // offset of the region for the record number
-#define HDBFSIZOFF 56 // offset of the region for the file size
-#define HDBFRECOFF 64 // offset of the region for the first record offset
-#define HDBOPAQUEOFF 128 // offset of the region for the opaque field
-
-#define HDBDEFBNUM 16381 // default bucket number
-#define HDBDEFAPOW 4 // default alignment power
-#define HDBMAXAPOW 16 // maximum alignment power
-#define HDBDEFFPOW 10 // default free block pool power
-#define HDBMAXFPOW 20 // maximum free block pool power
-#define HDBMINRUNIT 48 // minimum record reading unit
-#define HDBMAXHSIZ 32 // maximum record header size
-#define HDBFBPBSIZ 64 // base region size of the free block pool
-#define HDBFBPESIZ 4 // size of each region of the free block pool
-#define HDBFBPMGFREQ 256 // frequency to merge the free block pool
-#define HDBDRPUNIT 65536 // unit size of the delayed record pool
-#define HDBDRPLAT 2048 // latitude size of the delayed record pool
-#define HDBCACHEOUT 128 // number of records in a process of cacheout
-
-typedef struct { // type of structure for a record
- uint64_t off; // offset of the record
- uint32_t rsiz; // size of the whole record
- uint8_t magic; // magic number
- uint8_t hash; // second hash value
- uint64_t left; // offset of the left child record
- uint64_t right; // offset of the right child record
- uint32_t ksiz; // size of the key
- uint32_t vsiz; // size of the value
- uint16_t psiz; // size of the padding
- const char *kbuf; // pointer to the key
- const char *vbuf; // pointer to the value
- uint64_t boff; // offset of the body
- char *bbuf; // buffer of the body
-} TCHREC;
-
-typedef struct { // type of structure for a free block
- uint64_t off; // offset of the block
- uint32_t rsiz; // size of the block
-} HDBFB;
-
-enum { // enumeration for magic data
- HDBMAGICREC = 0xc8, // for data block
- HDBMAGICFB = 0xb0 // for free block
-};
-
-enum { // enumeration for duplication behavior
- HDBPDOVER, // overwrite an existing value
- HDBPDKEEP, // keep the existing value
- HDBPDCAT // concatenate values
-};
-
-
-/* private macros */
-#define HDBLOCKMETHOD(TC_hdb, TC_wr) \
- ((TC_hdb)->mmtx ? tchdblockmethod((TC_hdb), (TC_wr)) : true)
-#define HDBUNLOCKMETHOD(TC_hdb) \
- ((TC_hdb)->mmtx ? tchdbunlockmethod(TC_hdb) : true)
-#define HDBLOCKDRP(TC_hdb) \
- ((TC_hdb)->mmtx ? tchdblockdrp(TC_hdb) : true)
-#define HDBUNLOCKDRP(TC_hdb) \
- ((TC_hdb)->mmtx ? tchdbunlockdrp(TC_hdb) : true)
-
-
-/* private function prototypes */
-static bool tcseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size);
-static bool tcseekread(TCHDB *hdb, off_t off, void *buf, size_t size);
-static void tcdumpmeta(TCHDB *hdb, char *hbuf);
-static void tcloadmeta(TCHDB *hdb, const char *hbuf);
-static uint64_t tcgetprime(uint64_t num);
-static void tchdbclear(TCHDB *hdb);
-static int32_t tchdbpadsize(TCHDB *hdb);
-static void tchdbsetflag(TCHDB *hdb, int flag, bool sign);
-static uint64_t tchdbbidx(TCHDB *hdb, const char *kbuf, int ksiz, uint8_t *hp);
-static off_t tchdbgetbucket(TCHDB *hdb, uint64_t bidx);
-static void tchdbsetbucket(TCHDB *hdb, uint64_t bidx, uint64_t off);
-static bool tchdbsavefbp(TCHDB *hdb);
-static bool tchdbloadfbp(TCHDB *hdb);
-static void tcfbpsortbyoff(HDBFB *fbpool, int fbpnum);
-static void tcfbpsortbyrsiz(HDBFB *fbpool, int fbpnum);
-static void tchdbfbpmerge(TCHDB *hdb);
-static void tchdbfbpinsert(TCHDB *hdb, uint64_t off, uint32_t rsiz);
-static bool tchdbfbpsearch(TCHDB *hdb, TCHREC *rec);
-static bool tchdbfbpsplice(TCHDB *hdb, TCHREC *rec, uint32_t nsiz);
-static bool tchdbwritefb(TCHDB *hdb, uint64_t off, uint32_t rsiz);
-static bool tchdbwriterec(TCHDB *hdb, TCHREC *rec, uint64_t bidx, off_t entoff);
-static bool tchdbreadrec(TCHDB *hdb, TCHREC *rec, char *rbuf);
-static bool tchdbreadrecbody(TCHDB *hdb, TCHREC *rec);
-static int tcreckeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz);
-static bool tchdbflushdrp(TCHDB *hdb);
-static void tchdbcacheadjust(TCHDB *hdb);
-static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode);
-static bool tchdbcloseimpl(TCHDB *hdb);
-static bool tchdbputimpl(TCHDB *hdb, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- int dmode);
-static void tchdbdrpappend(TCHDB *hdb, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- uint8_t hash);
-static bool tchdbputasyncimpl(TCHDB *hdb, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
-static bool tchdboutimpl(TCHDB *hdb, const char *kbuf, int ksiz);
-static char *tchdbgetimpl(TCHDB *hdb, const char *kbuf, int ksiz, int *sp);
-static int tchdbgetintobuf(TCHDB *hdb, const char *kbuf, int ksiz, char *vbuf, int max);
-static int tchdbvsizimpl(TCHDB *hdb, const char *kbuf, int ksiz);
-static bool tchdbiterinitimpl(TCHDB *hdb);
-static char *tchdbiternextimpl(TCHDB *hdb, int *sp);
-static bool tchdbiternextintoxstr(TCHDB *hdb, TCXSTR *kxstr, TCXSTR *vxstr);
-static bool tchdboptimizeimpl(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
-static bool tchdbvanishimpl(TCHDB *hdb);
-static bool tchdblockmethod(TCHDB *hdb, bool wr);
-static bool tchdbunlockmethod(TCHDB *hdb);
-static bool tchdblockdrp(TCHDB *hdb);
-static bool tchdbunlockdrp(TCHDB *hdb);
-
-
-/* debugging function prototypes */
-void tchdbprintmeta(TCHDB *hdb);
-void tchdbprintrec(TCHDB *hdb, TCHREC *rec);
-
-
-
-/*************************************************************************************************
- * API
- *************************************************************************************************/
-
-
-/* Get the message string corresponding to an error code. */
-const char *tchdberrmsg(int ecode){
- switch(ecode){
- case TCESUCCESS: return "success";
- case TCETHREAD: return "threading error";
- case TCEINVALID: return "invalid operation";
- case TCENOFILE: return "file not found";
- case TCENOPERM: return "no permission";
- case TCEMETA: return "invalid meta data";
- case TCERHEAD: return "invalid record header";
- case TCEOPEN: return "open error";
- case TCECLOSE: return "close error";
- case TCETRUNC: return "trunc error";
- case TCESYNC: return "sync error";
- case TCESTAT: return "stat error";
- case TCESEEK: return "seek error";
- case TCEREAD: return "read error";
- case TCEWRITE: return "write error";
- case TCEMMAP: return "mmap error";
- case TCELOCK: return "lock error";
- case TCEUNLINK: return "unlink error";
- case TCERENAME: return "rename error";
- case TCEMKDIR: return "mkdir error";
- case TCERMDIR: return "rmdir error";
- case TCEKEEP: return "existing record";
- case TCENOREC: return "no record found";
- case TCEMISC: return "miscellaneous error";
- }
- return "unknown error";
-}
-
-
-/* Create a hash database object. */
-TCHDB *tchdbnew(void){
- TCHDB *hdb;
- TCMALLOC(hdb, sizeof(*hdb));
- tchdbclear(hdb);
- return hdb;
-}
-
-
-/* Delete a hash database object. */
-void tchdbdel(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd >= 0) tchdbclose(hdb);
- if(hdb->mmtx){
- pthread_key_delete(*(pthread_key_t *)hdb->eckey);
- pthread_mutex_destroy(hdb->dmtx);
- pthread_rwlock_destroy(hdb->mmtx);
- free(hdb->eckey);
- free(hdb->dmtx);
- free(hdb->mmtx);
- }
- free(hdb);
-}
-
-
-/* Get the last happened error code of a hash database object. */
-int tchdbecode(TCHDB *hdb){
- assert(hdb);
- return hdb->mmtx ?
- (int)(intptr_t)pthread_getspecific(*(pthread_key_t *)hdb->eckey) : hdb->ecode;
-}
-
-
-/* Set mutual exclusion control of a hash database object for threading. */
-bool tchdbsetmutex(TCHDB *hdb){
- assert(hdb);
- if(!TCUSEPTHREAD) return true;
- if(!tcglobalmutexlock()) return false;
- if(hdb->mmtx || hdb->fd >= 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- tcglobalmutexunlock();
- return false;
- }
- pthread_mutexattr_t rma;
- pthread_mutexattr_init(&rma);
- TCMALLOC(hdb->mmtx, sizeof(pthread_rwlock_t));
- TCMALLOC(hdb->dmtx, sizeof(pthread_mutex_t));
- TCMALLOC(hdb->eckey, sizeof(pthread_key_t));
- if(pthread_mutexattr_settype(&rma, PTHREAD_MUTEX_RECURSIVE) != 0 ||
- pthread_rwlock_init(hdb->mmtx, NULL) != 0 || pthread_mutex_init(hdb->dmtx, &rma) != 0 ||
- pthread_key_create(hdb->eckey, NULL) != 0){
- tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
- pthread_mutexattr_destroy(&rma);
- free(hdb->eckey);
- free(hdb->dmtx);
- free(hdb->mmtx);
- hdb->eckey = NULL;
- hdb->dmtx = NULL;
- hdb->mmtx = NULL;
- tcglobalmutexunlock();
- return false;
- }
- pthread_mutexattr_destroy(&rma);
- tcglobalmutexunlock();
- return true;
-}
-
-
-/* Set the tuning parameters of a hash database object. */
-bool tchdbtune(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(hdb);
- if(hdb->fd >= 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- hdb->bnum = (bnum > 0) ? tcgetprime(bnum) : HDBDEFBNUM;
- hdb->apow = (apow >= 0) ? tclmin(apow, HDBMAXAPOW) : HDBDEFAPOW;
- hdb->fpow = (fpow >= 0) ? tclmin(fpow, HDBMAXFPOW) : HDBDEFFPOW;
- hdb->opts = opts;
- if(!_tc_deflate) hdb->opts &= ~HDBTDEFLATE;
- return true;
-}
-
-
-/* Set the caching parameters of a hash database object. */
-bool tchdbsetcache(TCHDB *hdb, int32_t rcnum){
- assert(hdb);
- if(hdb->fd >= 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- hdb->rcnum = (rcnum > 0) ? tclmin(tclmax(rcnum, HDBCACHEOUT * 2), INT_MAX / 4) : 0;
- return true;
-}
-
-
-/* Open a database file and connect a hash database object. */
-bool tchdbopen(TCHDB *hdb, const char *path, int omode){
- assert(hdb && path);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd >= 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbopenimpl(hdb, path, omode);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Close a database object. */
-bool tchdbclose(TCHDB *hdb){
- assert(hdb);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbcloseimpl(hdb);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Store a record into a hash database object. */
-bool tchdbput(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->zmode){
- char *zbuf;
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_deflate(vbuf, vsiz, &vsiz, _TCZMRAW);
- } else {
- zbuf = tcbsencode(vbuf, vsiz, &vsiz);
- }
- if(!zbuf){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbputimpl(hdb, kbuf, ksiz, zbuf, vsiz, HDBPDOVER);
- free(zbuf);
- HDBUNLOCKMETHOD(hdb);
- return rv;
- }
- bool rv = tchdbputimpl(hdb, kbuf, ksiz, vbuf, vsiz, HDBPDOVER);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Store a string record into a hash database object. */
-bool tchdbput2(TCHDB *hdb, const char *kstr, const char *vstr){
- assert(hdb && kstr && vstr);
- return tchdbput(hdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Store a new record into a hash database object. */
-bool tchdbputkeep(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->zmode){
- char *zbuf;
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_deflate(vbuf, vsiz, &vsiz, _TCZMRAW);
- } else {
- zbuf = tcbsencode(vbuf, vsiz, &vsiz);
- }
- if(!zbuf){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbputimpl(hdb, kbuf, ksiz, zbuf, vsiz, HDBPDKEEP);
- free(zbuf);
- HDBUNLOCKMETHOD(hdb);
- return rv;
- }
- bool rv = tchdbputimpl(hdb, kbuf, ksiz, vbuf, vsiz, HDBPDKEEP);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Store a new string record into a hash database object. */
-bool tchdbputkeep2(TCHDB *hdb, const char *kstr, const char *vstr){
- return tchdbputkeep(hdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Concatenate a value at the end of the existing record in a hash database object. */
-bool tchdbputcat(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->zmode){
- char *zbuf;
- int osiz;
- char *obuf = tchdbgetimpl(hdb, kbuf, ksiz, &osiz);
- if(obuf){
- TCREALLOC(obuf, obuf, osiz + vsiz + 1);
- memcpy(obuf + osiz, vbuf, vsiz);
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_deflate(obuf, osiz + vsiz, &vsiz, _TCZMRAW);
- } else {
- zbuf = tcbsencode(obuf, osiz + vsiz, &vsiz);
- }
- free(obuf);
- } else {
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_deflate(vbuf, vsiz, &vsiz, _TCZMRAW);
- } else {
- zbuf = tcbsencode(vbuf, vsiz, &vsiz);
- }
- }
- if(!zbuf){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbputimpl(hdb, kbuf, ksiz, zbuf, vsiz, HDBPDOVER);
- free(zbuf);
- HDBUNLOCKMETHOD(hdb);
- return rv;
- }
- bool rv = tchdbputimpl(hdb, kbuf, ksiz, vbuf, vsiz, HDBPDCAT);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Concatenate a string value at the end of the existing record in a hash database object. */
-bool tchdbputcat2(TCHDB *hdb, const char *kstr, const char *vstr){
- assert(hdb && kstr && vstr);
- return tchdbputcat(hdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Store a record into a hash database object in asynchronous fashion. */
-bool tchdbputasync(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- hdb->async = true;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->zmode){
- char *zbuf;
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_deflate(vbuf, vsiz, &vsiz, _TCZMRAW);
- } else {
- zbuf = tcbsencode(vbuf, vsiz, &vsiz);
- }
- if(!zbuf){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbputasyncimpl(hdb, kbuf, ksiz, zbuf, vsiz);
- free(zbuf);
- HDBUNLOCKMETHOD(hdb);
- return rv;
- }
- bool rv = tchdbputasyncimpl(hdb, kbuf, ksiz, vbuf, vsiz);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Store a string record into a hash database object in asynchronous fashion. */
-bool tchdbputasync2(TCHDB *hdb, const char *kstr, const char *vstr){
- assert(hdb && kstr && vstr);
- return tchdbputasync(hdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Remove a record of a hash database object. */
-bool tchdbout(TCHDB *hdb, const void *kbuf, int ksiz){
- assert(hdb && kbuf && ksiz >= 0);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdboutimpl(hdb, kbuf, ksiz);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Remove a string record of a hash database object. */
-bool tchdbout2(TCHDB *hdb, const char *kstr){
- assert(hdb && kstr);
- return tchdbout(hdb, kstr, strlen(kstr));
-}
-
-
-/* Retrieve a record in a hash database object. */
-void *tchdbget(TCHDB *hdb, const void *kbuf, int ksiz, int *sp){
- assert(hdb && kbuf && ksiz >= 0 && sp);
- if(!HDBLOCKMETHOD(hdb, false)) return NULL;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return NULL;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return NULL;
- }
- char *rv = tchdbgetimpl(hdb, kbuf, ksiz, sp);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Retrieve a string record in a hash database object. */
-char *tchdbget2(TCHDB *hdb, const char *kstr){
- assert(hdb && kstr);
- int vsiz;
- return tchdbget(hdb, kstr, strlen(kstr), &vsiz);
-}
-
-
-/* Retrieve a record in a hash database object and write the value into a buffer. */
-int tchdbget3(TCHDB *hdb, const void *kbuf, int ksiz, void *vbuf, int max){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && max >= 0);
- if(!HDBLOCKMETHOD(hdb, false)) return -1;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return -1;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return -1;
- }
- int rv = tchdbgetintobuf(hdb, kbuf, ksiz, vbuf, max);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Get the size of the value of a record in a hash database object. */
-int tchdbvsiz(TCHDB *hdb, const void *kbuf, int ksiz){
- assert(hdb && kbuf && ksiz >= 0);
- if(!HDBLOCKMETHOD(hdb, false)) return -1;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return -1;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return -1;
- }
- int rv = tchdbvsizimpl(hdb, kbuf, ksiz);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Get the size of the value of a string record in a hash database object. */
-int tchdbvsiz2(TCHDB *hdb, const char *kstr){
- assert(hdb && kstr);
- return tchdbvsiz(hdb, kstr, strlen(kstr));
-}
-
-
-/* Initialize the iterator of a hash database object. */
-bool tchdbiterinit(TCHDB *hdb){
- assert(hdb);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbiterinitimpl(hdb);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Get the next key of the iterator of a hash database object. */
-void *tchdbiternext(TCHDB *hdb, int *sp){
- assert(hdb && sp);
- if(!HDBLOCKMETHOD(hdb, true)) return NULL;
- if(hdb->fd < 0 || hdb->iter < 1){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return NULL;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return NULL;
- }
- char *rv = tchdbiternextimpl(hdb, sp);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Get the next key string of the iterator of a hash database object. */
-char *tchdbiternext2(TCHDB *hdb){
- assert(hdb);
- int vsiz;
- return tchdbiternext(hdb, &vsiz);
-}
-
-
-/* Get the next extensible objects of the iterator of a hash database object. */
-bool tchdbiternext3(TCHDB *hdb, TCXSTR *kxstr, TCXSTR *vxstr){
- assert(hdb && kxstr && vxstr);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0 || hdb->iter < 1){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbiternextintoxstr(hdb, kxstr, vxstr);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Get forward matching keys in a hash database object. */
-TCLIST *tchdbfwmkeys(TCHDB *hdb, const void *pbuf, int psiz, int max){
- assert(hdb && pbuf && psiz >= 0);
- TCLIST* keys = tclistnew();
- if(!HDBLOCKMETHOD(hdb, true)) return keys;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return keys;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return keys;
- }
- if(max < 0) max = INT_MAX;
- uint64_t iter = hdb->iter;
- tchdbiterinitimpl(hdb);
- char *kbuf;
- int ksiz;
- while(TCLISTNUM(keys) < max && (kbuf = tchdbiternextimpl(hdb, &ksiz)) != NULL){
- if(ksiz >= psiz && !memcmp(kbuf, pbuf, psiz)){
- tclistpushmalloc(keys, kbuf, ksiz);
- } else {
- free(kbuf);
- }
- }
- hdb->iter = iter;
- HDBUNLOCKMETHOD(hdb);
- return keys;
-}
-
-
-/* Get forward matching string keys in a hash database object. */
-TCLIST *tchdbfwmkeys2(TCHDB *hdb, const char *pstr, int max){
- assert(hdb && pstr);
- return tchdbfwmkeys(hdb, pstr, strlen(pstr), max);
-}
-
-
-/* Synchronize updated contents of a hash database object with the file and the device. */
-bool tchdbsync(TCHDB *hdb){
- assert(hdb);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbmemsync(hdb, true);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Optimize the file of a hash database object. */
-bool tchdboptimize(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(hdb);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdboptimizeimpl(hdb, bnum, apow, fpow, opts);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Remove all records of a hash database object. */
-bool tchdbvanish(TCHDB *hdb){
- assert(hdb);
- if(!HDBLOCKMETHOD(hdb, true)) return false;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool rv = tchdbvanishimpl(hdb);
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Copy the database file of a hash database object. */
-bool tchdbcopy(TCHDB *hdb, const char *path){
- assert(hdb && path);
- if(!HDBLOCKMETHOD(hdb, false)) return false;
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(hdb->async && !tchdbflushdrp(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- if(!HDBLOCKDRP(hdb)){
- HDBUNLOCKMETHOD(hdb);
- return false;
- }
- bool err = false;
- hdb->flags &= ~HDBFOPEN;
- if(hdb->omode & HDBOWRITER){
- if(!tchdbsavefbp(hdb)) err = true;
- if(!tchdbmemsync(hdb, false)) err = true;
- }
- if(*path == '@'){
- int len = strlen(hdb->path);
- char name[len*2+1];
- char *wp = name;
- for(int i = 0; i < len; i++){
- switch(hdb->path[i]){
- case '\\':
- case '$':
- *(wp++) = '\\';
- *(wp++) = hdb->path[i];
- break;
- default:
- *(wp++) = hdb->path[i];
- break;
- }
- }
- *wp = '\0';
- char *cmd = tcsprintf("%s \"%s\" \"%llu\"",
- path + 1, name, (unsigned long long)(tctime() * 1000000));
- if(system(cmd) != 0) err = true;
- free(cmd);
- } else {
- if(!tccopyfile(hdb->path, path)){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- err = true;
- }
- }
- hdb->flags |= HDBFOPEN;
- HDBUNLOCKDRP(hdb);
- HDBUNLOCKMETHOD(hdb);
- return !err;
-}
-
-
-/* Get the file path of a hash database object. */
-const char *tchdbpath(TCHDB *hdb){
- assert(hdb);
- if(!HDBLOCKMETHOD(hdb, false)) return NULL;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return NULL;
- }
- const char *rv = hdb->path;
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Get the number of records of a hash database object. */
-uint64_t tchdbrnum(TCHDB *hdb){
- assert(hdb);
- if(!HDBLOCKMETHOD(hdb, false)) return 0;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return 0;
- }
- uint64_t rv = hdb->rnum;
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-/* Get the size of the database file of a hash database object. */
-uint64_t tchdbfsiz(TCHDB *hdb){
- assert(hdb);
- if(!HDBLOCKMETHOD(hdb, false)) return 0;
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- HDBUNLOCKMETHOD(hdb);
- return 0;
- }
- uint64_t rv = hdb->fsiz;
- HDBUNLOCKMETHOD(hdb);
- return rv;
-}
-
-
-
-/*************************************************************************************************
- * features for experts
- *************************************************************************************************/
-
-
-/* Set the error code of a hash database object. */
-void tchdbsetecode(TCHDB *hdb, int ecode, const char *filename, int line, const char *func){
- assert(hdb && filename && line >= 1 && func);
- if(!hdb->fatal){
- hdb->ecode = ecode;
- if(hdb->mmtx) pthread_setspecific(*(pthread_key_t *)hdb->eckey, (void *)(intptr_t)ecode);
- }
- if(ecode != TCEINVALID && ecode != TCEKEEP && ecode != TCENOREC){
- hdb->fatal = true;
- if(hdb->omode & HDBOWRITER) tchdbsetflag(hdb, HDBFFATAL, true);
- }
- if(hdb->dbgfd >= 0){
- char obuf[HDBIOBUFSIZ];
- int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s\n", filename, line, func,
- hdb->path ? hdb->path : "-", ecode, tchdberrmsg(ecode));
- tcwrite(hdb->dbgfd, obuf, osiz);
- }
-}
-
-
-/* Set the type of a hash database object. */
-void tchdbsettype(TCHDB *hdb, uint8_t type){
- assert(hdb);
- if(hdb->fd >= 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return;
- }
- hdb->type = type;
-}
-
-
-/* Set the file descriptor for debugging output. */
-void tchdbsetdbgfd(TCHDB *hdb, int fd){
- assert(hdb && fd >= 0);
- hdb->dbgfd = fd;
-}
-
-
-/* Get the file descriptor for debugging output. */
-int tchdbdbgfd(TCHDB *hdb){
- assert(hdb);
- return hdb->dbgfd;
-}
-
-
-/* Synchronize updating contents on memory. */
-bool tchdbmemsync(TCHDB *hdb, bool phys){
- assert(hdb);
- if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return false;
- }
- bool err = false;
- char hbuf[HDBHEADSIZ];
- tcdumpmeta(hdb, hbuf);
- memcpy(hdb->map, hbuf, HDBOPAQUEOFF);
- if(phys){
- if(msync(hdb->map, hdb->msiz, MS_SYNC) == -1){
- tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(fsync(hdb->fd) == -1){
- tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__);
- err = true;
- }
- }
- return !err;
-}
-
-
-/* Get the number of elements of the bucket array of a hash database object. */
-uint64_t tchdbbnum(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->bnum;
-}
-
-
-/* Get the record alignment a hash database object. */
-uint32_t tchdbalign(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->align;
-}
-
-
-/* Get the maximum number of the free block pool of a a hash database object. */
-uint32_t tchdbfbpmax(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->fbpmax;
-}
-
-
-/* Get the inode number of the database file of a hash database object. */
-uint64_t tchdbinode(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->inode;
-}
-
-
-/* Get the modification time of the database file of a hash database object. */
-time_t tchdbmtime(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->mtime;
-}
-
-
-/* Get the connection mode of a hash database object. */
-int tchdbomode(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->omode;
-}
-
-
-/* Get the database type of a hash database object. */
-uint8_t tchdbtype(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->type;
-}
-
-
-/* Get the additional flags of a hash database object. */
-uint8_t tchdbflags(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->flags;
-}
-
-
-/* Get the options of a hash database object. */
-uint8_t tchdbopts(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- return hdb->opts;
-}
-
-
-/* Get the pointer to the opaque field of a hash database object. */
-char *tchdbopaque(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return NULL;
- }
- return hdb->map + HDBOPAQUEOFF;
-}
-
-
-/* Get the number of used elements of the bucket array of a hash database object. */
-uint64_t tchdbbnumused(TCHDB *hdb){
- assert(hdb);
- if(hdb->fd < 0){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- return 0;
- }
- uint64_t unum = 0;
- if(hdb->ba64){
- uint64_t *buckets = hdb->ba64;
- for(int i = 0; i < hdb->bnum; i++){
- if(buckets[i]) unum++;
- }
- } else {
- uint32_t *buckets = hdb->ba32;
- for(int i = 0; i < hdb->bnum; i++){
- if(buckets[i]) unum++;
- }
- }
- return unum;
-}
-
-
-
-/*************************************************************************************************
- * private features
- *************************************************************************************************/
-
-
-/* Seek and read data from a file.
- `hdb' specifies the hash database object.
- `off' specifies the offset of the region to seek.
- `buf' specifies the buffer to store into.
- `size' specifies the size of the buffer.
- The return value is true if successful, else, it is false. */
-static bool tcseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size){
- assert(hdb && off >= 0 && buf && size >= 0);
- while(true){
- int wb = pwrite(hdb->fd, buf, size, off);
- if(wb >= size){
- return true;
- } else if(wb > 0){
- buf = (char *)buf + wb;
- size -= wb;
- off += wb;
- } else if(wb == -1){
- if(errno != EINTR){
- tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);
- return false;
- }
- } else {
- if(size > 0){
- tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);
- return false;
- }
- }
- }
- return true;
-}
-
-
-/* Seek and read data from a file.
- `hdb' specifies the hash database object.
- `off' specifies the offset of the region to seek.
- `buf' specifies the buffer to store into.
- `size' specifies the size of the buffer.
- The return value is true if successful, else, it is false. */
-static bool tcseekread(TCHDB *hdb, off_t off, void *buf, size_t size){
- assert(hdb && off >= 0 && buf && size >= 0);
- while(true){
- int rb = pread(hdb->fd, buf, size, off);
- if(rb >= size){
- break;
- } else if(rb > 0){
- buf = (char *)buf + rb;
- size -= rb;
- off += rb;
- } else if(rb == -1){
- if(errno != EINTR){
- tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- } else {
- if(size > 0){
- tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- }
- }
- return true;
-}
-
-
-/* Serialize meta data into a buffer.
- `hdb' specifies the hash database object.
- `hbuf' specifies the buffer. */
-static void tcdumpmeta(TCHDB *hdb, char *hbuf){
- memset(hbuf, 0, HDBHEADSIZ);
- sprintf(hbuf, "%s\n%s:%d\n", HDBMAGICDATA, _TC_FORMATVER, _TC_LIBVER);
- memcpy(hbuf + HDBTYPEOFF, &(hdb->type), sizeof(hdb->type));
- memcpy(hbuf + HDBFLAGSOFF, &(hdb->flags), sizeof(hdb->flags));
- memcpy(hbuf + HDBAPOWOFF, &(hdb->apow), sizeof(hdb->apow));
- memcpy(hbuf + HDBFPOWOFF, &(hdb->fpow), sizeof(hdb->fpow));
- memcpy(hbuf + HDBOPTSOFF, &(hdb->opts), sizeof(hdb->opts));
- uint64_t llnum;
- llnum = hdb->bnum;
- llnum = TCHTOILL(llnum);
- memcpy(hbuf + HDBBNUMOFF, &llnum, sizeof(llnum));
- llnum = hdb->rnum;
- llnum = TCHTOILL(llnum);
- memcpy(hbuf + HDBRNUMOFF, &llnum, sizeof(llnum));
- llnum = hdb->fsiz;
- llnum = TCHTOILL(llnum);
- memcpy(hbuf + HDBFSIZOFF, &llnum, sizeof(llnum));
- llnum = hdb->frec;
- llnum = TCHTOILL(llnum);
- memcpy(hbuf + HDBFRECOFF, &llnum, sizeof(llnum));
-}
-
-
-/* Deserialize meta data from a buffer.
- `hdb' specifies the hash database object.
- `hbuf' specifies the buffer. */
-static void tcloadmeta(TCHDB *hdb, const char *hbuf){
- memcpy(&(hdb->type), hbuf + HDBTYPEOFF, sizeof(hdb->type));
- memcpy(&(hdb->flags), hbuf + HDBFLAGSOFF, sizeof(hdb->flags));
- memcpy(&(hdb->apow), hbuf + HDBAPOWOFF, sizeof(hdb->apow));
- memcpy(&(hdb->fpow), hbuf + HDBFPOWOFF, sizeof(hdb->fpow));
- memcpy(&(hdb->opts), hbuf + HDBOPTSOFF, sizeof(hdb->opts));
- uint64_t llnum;
- memcpy(&llnum, hbuf + HDBBNUMOFF, sizeof(llnum));
- hdb->bnum = TCITOHLL(llnum);
- memcpy(&llnum, hbuf + HDBRNUMOFF, sizeof(llnum));
- hdb->rnum = TCITOHLL(llnum);
- memcpy(&llnum, hbuf + HDBFSIZOFF, sizeof(llnum));
- hdb->fsiz = TCITOHLL(llnum);
- memcpy(&llnum, hbuf + HDBFRECOFF, sizeof(llnum));
- hdb->frec = TCITOHLL(llnum);
-}
-
-
-/* Get a natural prime number not less than a floor number.
- `num' specified the floor number.
- The return value is a prime number not less than the floor number. */
-static uint64_t tcgetprime(uint64_t num){
- uint64_t primes[] = {
- 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 43, 47, 53, 59, 61, 71, 79, 83,
- 89, 103, 109, 113, 127, 139, 157, 173, 191, 199, 223, 239, 251, 283, 317, 349,
- 383, 409, 443, 479, 509, 571, 631, 701, 761, 829, 887, 953, 1021, 1151, 1279,
- 1399, 1531, 1663, 1789, 1913, 2039, 2297, 2557, 2803, 3067, 3323, 3583, 3833,
- 4093, 4603, 5119, 5623, 6143, 6653, 7159, 7673, 8191, 9209, 10223, 11261,
- 12281, 13309, 14327, 15359, 16381, 18427, 20479, 22511, 24571, 26597, 28669,
- 30713, 32749, 36857, 40949, 45053, 49139, 53239, 57331, 61417, 65521, 73727,
- 81919, 90107, 98299, 106487, 114679, 122869, 131071, 147451, 163819, 180221,
- 196597, 212987, 229373, 245759, 262139, 294911, 327673, 360439, 393209, 425977,
- 458747, 491503, 524287, 589811, 655357, 720887, 786431, 851957, 917503, 982981,
- 1048573, 1179641, 1310719, 1441771, 1572853, 1703903, 1835003, 1966079,
- 2097143, 2359267, 2621431, 2883577, 3145721, 3407857, 3670013, 3932153,
- 4194301, 4718579, 5242877, 5767129, 6291449, 6815741, 7340009, 7864301,
- 8388593, 9437179, 10485751, 11534329, 12582893, 13631477, 14680063, 15728611,
- 16777213, 18874367, 20971507, 23068667, 25165813, 27262931, 29360087, 31457269,
- 33554393, 37748717, 41943023, 46137319, 50331599, 54525917, 58720253, 62914549,
- 67108859, 75497467, 83886053, 92274671, 100663291, 109051903, 117440509,
- 125829103, 134217689, 150994939, 167772107, 184549373, 201326557, 218103799,
- 234881011, 251658227, 268435399, 301989881, 335544301, 369098707, 402653171,
- 436207613, 469762043, 503316469, 536870909, 603979769, 671088637, 738197503,
- 805306357, 872415211, 939524087, 1006632947, 1073741789, 1207959503,
- 1342177237, 1476394991, 1610612711, 1744830457, 1879048183, 2013265907,
- 2576980349, 3092376431, 3710851741, 4718021527, 6133428047, 7973456459,
- 10365493393, 13475141413, 17517683831, 22772988923, 29604885677, 38486351381,
- 50032256819, 65041933867, 84554514043, 109920868241, 0
- };
- int i;
- for(i = 0; primes[i] > 0; i++){
- if(num <= primes[i]) return primes[i];
- }
- return primes[i-1];
-}
-
-
-/* Clear all members.
- `hdb' specifies the hash database object. */
-static void tchdbclear(TCHDB *hdb){
- assert(hdb);
- hdb->mmtx = NULL;
- hdb->dmtx = NULL;
- hdb->eckey = NULL;
- hdb->type = HDBTHASH;
- hdb->flags = 0;
- hdb->bnum = HDBDEFBNUM;
- hdb->apow = HDBDEFAPOW;
- hdb->fpow = HDBDEFFPOW;
- hdb->opts = 0;
- hdb->path = NULL;
- hdb->fd = -1;
- hdb->omode = 0;
- hdb->rnum = 0;
- hdb->fsiz = 0;
- hdb->frec = 0;
- hdb->iter = 0;
- hdb->map = NULL;
- hdb->msiz = 0;
- hdb->ba32 = NULL;
- hdb->ba64 = NULL;
- hdb->align = 0;
- hdb->runit = 0;
- hdb->zmode = false;
- hdb->fbpmax = 0;
- hdb->fbpsiz = 0;
- hdb->fbpool = NULL;
- hdb->fbpnum = 0;
- hdb->fbpmis = 0;
- hdb->async = false;
- hdb->drpool = NULL;
- hdb->drpdef = NULL;
- hdb->drpoff = 0;
- hdb->recc = NULL;
- hdb->rcnum = 0;
- hdb->ecode = TCESUCCESS;
- hdb->fatal = false;
- hdb->dbgfd = -1;
- hdb->cnt_writerec = -1;
- hdb->cnt_reuserec = -1;
- hdb->cnt_moverec = -1;
- hdb->cnt_readrec = -1;
- hdb->cnt_searchfbp = -1;
- hdb->cnt_insertfbp = -1;
- hdb->cnt_splicefbp = -1;
- hdb->cnt_dividefbp = -1;
- hdb->cnt_mergefbp = -1;
- hdb->cnt_reducefbp = -1;
- hdb->cnt_appenddrp = -1;
- hdb->cnt_deferdrp = -1;
- hdb->cnt_flushdrp = -1;
- hdb->cnt_adjrecc = -1;
- TCDODEBUG(hdb->cnt_writerec = 0);
- TCDODEBUG(hdb->cnt_reuserec = 0);
- TCDODEBUG(hdb->cnt_moverec = 0);
- TCDODEBUG(hdb->cnt_readrec = 0);
- TCDODEBUG(hdb->cnt_searchfbp = 0);
- TCDODEBUG(hdb->cnt_insertfbp = 0);
- TCDODEBUG(hdb->cnt_splicefbp = 0);
- TCDODEBUG(hdb->cnt_dividefbp = 0);
- TCDODEBUG(hdb->cnt_mergefbp = 0);
- TCDODEBUG(hdb->cnt_reducefbp = 0);
- TCDODEBUG(hdb->cnt_appenddrp = 0);
- TCDODEBUG(hdb->cnt_deferdrp = 0);
- TCDODEBUG(hdb->cnt_flushdrp = 0);
- TCDODEBUG(hdb->cnt_adjrecc = 0);
-}
-
-
-/* Get the padding size to record alignment.
- `hdb' specifies the hash database object.
- The return value is the padding size. */
-static int32_t tchdbpadsize(TCHDB *hdb){
- assert(hdb);
- int32_t diff = hdb->fsiz & (hdb->align - 1);
- return diff > 0 ? hdb->align - diff : 0;
-}
-
-
-/* Set the open flag.
- `hdb' specifies the hash database object.
- `flag' specifies the flag value.
- `sign' specifies the sign. */
-static void tchdbsetflag(TCHDB *hdb, int flag, bool sign){
- assert(hdb);
- char *fp = (char *)hdb->map + HDBFLAGSOFF;
- if(sign){
- *fp |= (uint8_t)flag;
- } else {
- *fp &= ~(uint8_t)flag;
- }
- hdb->flags = *fp;
-}
-
-
-/* Get the bucket index of a record.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `hp' specifies the pointer to the variable into which the second hash value is assigned.
- The return value is the bucket index. */
-static uint64_t tchdbbidx(TCHDB *hdb, const char *kbuf, int ksiz, uint8_t *hp){
- assert(hdb && kbuf && ksiz >= 0 && hp);
- uint64_t idx = 19780211;
- uint32_t hash = 751;
- const char *rp = kbuf + ksiz;
- while(ksiz--){
- idx = (idx << 5) + (idx << 2) + idx + *(uint8_t *)kbuf++;
- hash = ((hash << 5) - hash) ^ *(uint8_t *)--rp;
- }
- *hp = hash;
- return idx % hdb->bnum;
-}
-
-
-/* Get the offset of the record of a bucket element.
- `hdb' specifies the hash database object.
- `bidx' specifies the index of the bucket.
- The return value is the offset of the record. */
-static off_t tchdbgetbucket(TCHDB *hdb, uint64_t bidx){
- assert(hdb && bidx >= 0);
- if(hdb->ba64){
- uint64_t llnum = hdb->ba64[bidx];
- return TCITOHLL(llnum) << hdb->apow;
- }
- uint32_t lnum = hdb->ba32[bidx];
- return (off_t)TCITOHL(lnum) << hdb->apow;
-}
-
-
-/* Get the offset of the record of a bucket element.
- `hdb' specifies the hash database object.
- `bidx' specifies the index of the record.
- `off' specifies the offset of the record. */
-static void tchdbsetbucket(TCHDB *hdb, uint64_t bidx, uint64_t off){
- assert(hdb && bidx >= 0);
- if(hdb->ba64){
- uint64_t llnum = off >> hdb->apow;
- hdb->ba64[bidx] = TCHTOILL(llnum);
- } else {
- uint32_t lnum = off >> hdb->apow;
- hdb->ba32[bidx] = TCHTOIL(lnum);
- }
-}
-
-
-/* Load the free block pool from the file.
- The return value is true if successful, else, it is false. */
-static bool tchdbsavefbp(TCHDB *hdb){
- assert(hdb);
- if(hdb->fbpnum > (hdb->fbpmax >> 1)){
- tchdbfbpmerge(hdb);
- } else if(hdb->fbpnum > 1){
- tcfbpsortbyoff(hdb->fbpool, hdb->fbpnum);
- }
- int bsiz = hdb->fbpsiz;
- char *buf;
- TCMALLOC(buf, bsiz);
- char *wp = buf;
- HDBFB *cur = hdb->fbpool;
- HDBFB *end = cur + hdb->fbpnum;
- uint64_t base = 0;
- bsiz -= sizeof(HDBFB) + sizeof(uint8_t) + sizeof(uint8_t);
- while(cur < end && bsiz > 0){
- uint64_t noff = cur->off >> hdb->apow;
- int step;
- uint64_t llnum = noff - base;
- TCSETVNUMBUF64(step, wp, llnum);
- wp += step;
- bsiz -= step;
- uint32_t lnum = cur->rsiz >> hdb->apow;
- TCSETVNUMBUF(step, wp, lnum);
- wp += step;
- bsiz -= step;
- base = noff;
- cur++;
- }
- *(wp++) = '\0';
- *(wp++) = '\0';
- if(!tcseekwrite(hdb, hdb->msiz, buf, wp - buf)){
- free(buf);
- return false;
- }
- free(buf);
- return true;
-}
-
-
-/* Save the free block pool into the file.
- The return value is true if successful, else, it is false. */
-static bool tchdbloadfbp(TCHDB *hdb){
- int bsiz = hdb->fbpsiz;
- char *buf;
- TCMALLOC(buf, bsiz);
- if(!tcseekread(hdb, hdb->msiz, buf, bsiz)){
- free(buf);
- return false;
- }
- const char *rp = buf;
- HDBFB *cur = hdb->fbpool;
- HDBFB *end = cur + hdb->fbpmax;
- uint64_t base = 0;
- while(cur < end && *rp != '\0'){
- int step;
- uint64_t llnum;
- TCREADVNUMBUF64(rp, llnum, step);
- base += llnum << hdb->apow;
- cur->off = base;
- rp += step;
- uint32_t lnum;
- TCREADVNUMBUF(rp, lnum, step);
- cur->rsiz = lnum << hdb->apow;
- rp += step;
- cur++;
- }
- hdb->fbpnum = cur - (HDBFB *)hdb->fbpool;
- free(buf);
- return true;
-}
-
-
-/* Sort the free block pool by offset.
- `fbpool' specifies the free block pool.
- `fbpnum' specifies the number of blocks. */
-static void tcfbpsortbyoff(HDBFB *fbpool, int fbpnum){
- assert(fbpool && fbpnum >= 0);
- fbpnum--;
- int bottom = fbpnum / 2 + 1;
- int top = fbpnum;
- while(bottom > 0){
- bottom--;
- int mybot = bottom;
- int i = 2 * mybot;
- while(i <= top){
- if(i < top && fbpool[i+1].off > fbpool[i].off) i++;
- if(fbpool[mybot].off >= fbpool[i].off) break;
- HDBFB swap = fbpool[mybot];
- fbpool[mybot] = fbpool[i];
- fbpool[i] = swap;
- mybot = i;
- i = 2 * mybot;
- }
- }
- while(top > 0){
- HDBFB swap = fbpool[0];
- fbpool[0] = fbpool[top];
- fbpool[top] = swap;
- top--;
- int mybot = bottom;
- int i = 2 * mybot;
- while(i <= top){
- if(i < top && fbpool[i+1].off > fbpool[i].off) i++;
- if(fbpool[mybot].off >= fbpool[i].off) break;
- swap = fbpool[mybot];
- fbpool[mybot] = fbpool[i];
- fbpool[i] = swap;
- mybot = i;
- i = 2 * mybot;
- }
- }
-}
-
-
-/* Sort the free block pool by record size.
- `fbpool' specifies the free block pool.
- `fbpnum' specifies the number of blocks. */
-static void tcfbpsortbyrsiz(HDBFB *fbpool, int fbpnum){
- assert(fbpool && fbpnum >= 0);
- fbpnum--;
- int bottom = fbpnum / 2 + 1;
- int top = fbpnum;
- while(bottom > 0){
- bottom--;
- int mybot = bottom;
- int i = 2 * mybot;
- while(i <= top){
- if(i < top && fbpool[i+1].rsiz > fbpool[i].rsiz) i++;
- if(fbpool[mybot].rsiz >= fbpool[i].rsiz) break;
- HDBFB swap = fbpool[mybot];
- fbpool[mybot] = fbpool[i];
- fbpool[i] = swap;
- mybot = i;
- i = 2 * mybot;
- }
- }
- while(top > 0){
- HDBFB swap = fbpool[0];
- fbpool[0] = fbpool[top];
- fbpool[top] = swap;
- top--;
- int mybot = bottom;
- int i = 2 * mybot;
- while(i <= top){
- if(i < top && fbpool[i+1].rsiz > fbpool[i].rsiz) i++;
- if(fbpool[mybot].rsiz >= fbpool[i].rsiz) break;
- swap = fbpool[mybot];
- fbpool[mybot] = fbpool[i];
- fbpool[i] = swap;
- mybot = i;
- i = 2 * mybot;
- }
- }
-}
-
-
-/* Merge successive records in the free block pool.
- `hdb' specifies the hash database object. */
-static void tchdbfbpmerge(TCHDB *hdb){
- assert(hdb);
- TCDODEBUG(hdb->cnt_mergefbp++);
- int32_t onum = hdb->fbpnum;
- tcfbpsortbyoff(hdb->fbpool, hdb->fbpnum);
- HDBFB *wp = hdb->fbpool;;
- HDBFB *cur = wp;
- HDBFB *end = wp + hdb->fbpnum - 1;
- while(cur < end){
- if(cur->off > 0){
- HDBFB *next = cur + 1;
- if(cur->off + cur->rsiz == next->off){
- if(hdb->iter == next->off) hdb->iter += next->rsiz;
- cur->rsiz += next->rsiz;
- next->off = 0;
- }
- *(wp++) = *cur;
- }
- cur++;
- }
- if(end->off > 0) *(wp++) = *end;
- hdb->fbpnum = wp - (HDBFB *)hdb->fbpool;
- hdb->fbpmis = (hdb->fbpnum < onum) ? 0 : hdb->fbpnum * -2;
-}
-
-
-/* Insert a block into the free block pool.
- `hdb' specifies the hash database object.
- `off' specifies the offset of the block.
- `rsiz' specifies the size of the block. */
-static void tchdbfbpinsert(TCHDB *hdb, uint64_t off, uint32_t rsiz){
- assert(hdb && off > 0 && rsiz > 0);
- TCDODEBUG(hdb->cnt_insertfbp++);
- if(hdb->fpow < 1) return;
- HDBFB *pv = hdb->fbpool;
- if(hdb->fbpnum >= hdb->fbpmax){
- tchdbfbpmerge(hdb);
- tcfbpsortbyrsiz(hdb->fbpool, hdb->fbpnum);
- if(hdb->fbpnum >= hdb->fbpmax){
- TCDODEBUG(hdb->cnt_reducefbp++);
- int32_t dnum = (hdb->fbpmax >> 2) + 1;
- memmove(pv, pv + dnum, (hdb->fbpnum - dnum) * sizeof(*pv));
- hdb->fbpnum -= dnum;
- }
- hdb->fbpmis = 0;
- }
- pv = pv + hdb->fbpnum;
- pv->off = off;
- pv->rsiz = rsiz;
- hdb->fbpnum++;
-}
-
-
-/* Search the free block pool for the minimum region.
- `hdb' specifies the hash database object.
- `rec' specifies the record object to be stored.
- The return value is true if successful, else, it is false. */
-static bool tchdbfbpsearch(TCHDB *hdb, TCHREC *rec){
- assert(hdb && rec);
- TCDODEBUG(hdb->cnt_searchfbp++);
- if(hdb->fbpnum < 1){
- rec->off = hdb->fsiz;
- rec->rsiz = 0;
- return true;
- }
- uint32_t rsiz = rec->rsiz;
- HDBFB *pv = hdb->fbpool;
- HDBFB *ep = pv + hdb->fbpnum;
- while(pv < ep){
- if(pv->rsiz > rsiz){
- if(pv->rsiz > (rsiz << 1)){
- uint64_t fsiz = hdb->fsiz;
- hdb->fsiz = pv->off + rsiz;
- uint32_t psiz = tchdbpadsize(hdb);
- hdb->fsiz = fsiz;
- uint64_t noff = pv->off + rsiz + psiz;
- if(pv->rsiz >= ((noff - pv->off) << 1)){
- TCDODEBUG(hdb->cnt_dividefbp++);
- rec->off = pv->off;
- rec->rsiz = noff - pv->off;
- pv->off = noff;
- pv->rsiz -= rec->rsiz;
- return tchdbwritefb(hdb, pv->off, pv->rsiz);
- }
- }
- rec->off = pv->off;
- rec->rsiz = pv->rsiz;
- ep--;
- pv->off = ep->off;
- pv->rsiz = ep->rsiz;
- hdb->fbpnum--;
- return true;
- }
- pv++;
- }
- rec->off = hdb->fsiz;
- rec->rsiz = 0;
- hdb->fbpmis++;
- if(hdb->fbpmis >= HDBFBPMGFREQ){
- tchdbfbpmerge(hdb);
- tcfbpsortbyrsiz(hdb->fbpool, hdb->fbpnum);
- }
- return true;
-}
-
-
-/* Splice the trailing free block
- `hdb' specifies the hash database object.
- `rec' specifies the record object to be stored.
- `nsiz' specifies the needed size.
- The return value is whether splicing succeeded or not. */
-static bool tchdbfbpsplice(TCHDB *hdb, TCHREC *rec, uint32_t nsiz){
- assert(hdb && rec && nsiz > 0);
- if(hdb->fbpnum < 1) return false;
- uint64_t off = rec->off + rec->rsiz;
- uint32_t rsiz = rec->rsiz;
- HDBFB *pv = hdb->fbpool;
- HDBFB *ep = pv + hdb->fbpnum;
- while(pv < ep){
- if(pv->off == off && rsiz + pv->rsiz >= nsiz){
- if(hdb->iter == pv->off) hdb->iter += pv->rsiz;
- rec->rsiz += pv->rsiz;
- ep--;
- pv->off = ep->off;
- pv->rsiz = ep->rsiz;
- hdb->fbpnum--;
- return true;
- }
- pv++;
- }
- return false;
-}
-
-
-/* Write a free block into the file.
- `hdb' specifies the hash database object.
- `off' specifies the offset of the block.
- `rsiz' specifies the size of the block.
- The return value is true if successful, else, it is false. */
-static bool tchdbwritefb(TCHDB *hdb, uint64_t off, uint32_t rsiz){
- assert(hdb && off > 0 && rsiz > 0);
- char rbuf[HDBMAXHSIZ];
- char *wp = rbuf;
- *(uint8_t *)(wp++) = HDBMAGICFB;
- uint32_t lnum = TCHTOIL(rsiz);
- memcpy(wp, &lnum, sizeof(lnum));
- wp += sizeof(lnum);
- if(!tcseekwrite(hdb, off, rbuf, wp - rbuf)) return false;
- return true;
-}
-
-
-/* Write a record into the file.
- `hdb' specifies the hash database object.
- `rec' specifies the record object.
- `bidx' specifies the index of the bucket.
- `entoff' specifies the offset of the tree entry.
- The return value is true if successful, else, it is false. */
-static bool tchdbwriterec(TCHDB *hdb, TCHREC *rec, uint64_t bidx, off_t entoff){
- assert(hdb && rec);
- TCDODEBUG(hdb->cnt_writerec++);
- uint64_t ofsiz = hdb->fsiz;
- char stack[HDBIOBUFSIZ];
- int bsiz = rec->rsiz > 0 ? rec->rsiz : HDBMAXHSIZ + rec->ksiz + rec->vsiz + hdb->align;
- char *rbuf;
- if(bsiz <= HDBIOBUFSIZ){
- rbuf = stack;
- } else {
- TCMALLOC(rbuf, bsiz);
- }
- char *wp = rbuf;
- *(uint8_t *)(wp++) = HDBMAGICREC;
- *(uint8_t *)(wp++) = rec->hash;
- if(hdb->ba64){
- uint64_t llnum;
- llnum = rec->left >> hdb->apow;
- llnum = TCHTOILL(llnum);
- memcpy(wp, &llnum, sizeof(llnum));
- wp += sizeof(llnum);
- llnum = rec->right >> hdb->apow;
- llnum = TCHTOILL(llnum);
- memcpy(wp, &llnum, sizeof(llnum));
- wp += sizeof(llnum);
- } else {
- uint32_t lnum;
- lnum = rec->left >> hdb->apow;
- lnum = TCHTOIL(lnum);
- memcpy(wp, &lnum, sizeof(lnum));
- wp += sizeof(lnum);
- lnum = rec->right >> hdb->apow;
- lnum = TCHTOIL(lnum);
- memcpy(wp, &lnum, sizeof(lnum));
- wp += sizeof(lnum);
- }
- uint16_t snum;
- char *pwp = wp;
- wp += sizeof(snum);
- int step;
- TCSETVNUMBUF(step, wp, rec->ksiz);
- wp += step;
- TCSETVNUMBUF(step, wp, rec->vsiz);
- wp += step;
- int32_t hsiz = wp - rbuf;
- int32_t rsiz = hsiz + rec->ksiz + rec->vsiz;
- if(rec->rsiz < 1){
- hdb->fsiz += rsiz;
- uint16_t psiz = tchdbpadsize(hdb);
- rec->rsiz = rsiz + psiz;
- rec->psiz = psiz;
- hdb->fsiz += psiz;
- } else if(rsiz > rec->rsiz){
- if(rbuf != stack) free(rbuf);
- if(tchdbfbpsplice(hdb, rec, rsiz)){
- TCDODEBUG(hdb->cnt_splicefbp++);
- return tchdbwriterec(hdb, rec, bidx, entoff);
- }
- TCDODEBUG(hdb->cnt_moverec++);
- if(!tchdbwritefb(hdb, rec->off, rec->rsiz)) return false;
- tchdbfbpinsert(hdb, rec->off, rec->rsiz);
- rec->rsiz = rsiz;
- if(!tchdbfbpsearch(hdb, rec)) return false;
- return tchdbwriterec(hdb, rec, bidx, entoff);
- } else {
- TCDODEBUG(hdb->cnt_reuserec++);
- uint32_t psiz = rec->rsiz - rsiz;
- if(psiz > UINT16_MAX){
- TCDODEBUG(hdb->cnt_dividefbp++);
- uint64_t fsiz = hdb->fsiz;
- hdb->fsiz = rec->off + rsiz;
- psiz = tchdbpadsize(hdb);
- hdb->fsiz = fsiz;
- uint64_t noff = rec->off + rsiz + psiz;
- uint32_t nsiz = rec->rsiz - rsiz - psiz;
- rec->rsiz = noff - rec->off;
- rec->psiz = psiz;
- if(!tchdbwritefb(hdb, noff, nsiz)) return false;
- tchdbfbpinsert(hdb, noff, nsiz);
- }
- rec->psiz = psiz;
- }
- snum = rec->psiz;
- snum = TCHTOIS(snum);
- memcpy(pwp, &snum, sizeof(snum));
- rsiz = rec->rsiz;
- rsiz -= hsiz;
- memcpy(wp, rec->kbuf, rec->ksiz);
- wp += rec->ksiz;
- rsiz -= rec->ksiz;
- memcpy(wp, rec->vbuf, rec->vsiz);
- wp += rec->vsiz;
- rsiz -= rec->vsiz;
- memset(wp, 0, rsiz);
- if(!tcseekwrite(hdb, rec->off, rbuf, rec->rsiz)){
- if(rbuf != stack) free(rbuf);
- hdb->fsiz = ofsiz;
- return false;
- }
- if(hdb->fsiz != ofsiz){
- uint64_t llnum = hdb->fsiz;
- llnum = TCHTOILL(llnum);
- memcpy(hdb->map + HDBFSIZOFF, &llnum, sizeof(llnum));
- }
- if(rbuf != stack) free(rbuf);
- if(entoff > 0){
- if(hdb->ba64){
- uint64_t llnum = rec->off >> hdb->apow;
- llnum = TCHTOILL(llnum);
- if(!tcseekwrite(hdb, entoff, &llnum, sizeof(uint64_t))) return false;
- } else {
- uint32_t lnum = rec->off >> hdb->apow;
- lnum = TCHTOIL(lnum);
- if(!tcseekwrite(hdb, entoff, &lnum, sizeof(uint32_t))) return false;
- }
- } else {
- tchdbsetbucket(hdb, bidx, rec->off);
- }
- return true;
-}
-
-
-/* Read a record from the file.
- `hdb' specifies the hash database object.
- `rec' specifies the record object.
- `rbuf' specifies the buffer for reading.
- The return value is true if successful, else, it is false. */
-static bool tchdbreadrec(TCHDB *hdb, TCHREC *rec, char *rbuf){
- assert(hdb && rec && rbuf);
- TCDODEBUG(hdb->cnt_readrec++);
- off_t rsiz = hdb->fsiz - rec->off;
- if(rsiz > hdb->runit){
- rsiz = hdb->runit;
- } else if(rsiz < (sizeof(uint8_t) + sizeof(uint32_t))){
- tchdbsetecode(hdb, TCERHEAD, __FILE__, __LINE__, __func__);
- return false;
- }
- if(!tcseekread(hdb, rec->off, rbuf, rsiz)) return false;
- const char *rp = rbuf;
- rec->magic = *(uint8_t *)(rp++);
- if(rec->magic == HDBMAGICFB){
- uint32_t lnum;
- memcpy(&lnum, rp, sizeof(lnum));
- rec->rsiz = TCITOHL(lnum);
- return true;
- } else if(rec->magic != HDBMAGICREC){
- tchdbsetecode(hdb, TCERHEAD, __FILE__, __LINE__, __func__);
- return false;
- }
- rec->hash = *(uint8_t *)(rp++);
- if(hdb->ba64){
- uint64_t llnum;
- memcpy(&llnum, rp, sizeof(llnum));
- rec->left = TCITOHLL(llnum) << hdb->apow;
- rp += sizeof(llnum);
- memcpy(&llnum, rp, sizeof(llnum));
- rec->right = TCITOHLL(llnum) << hdb->apow;
- rp += sizeof(llnum);
- } else {
- uint32_t lnum;
- memcpy(&lnum, rp, sizeof(lnum));
- rec->left = (uint64_t)TCITOHL(lnum) << hdb->apow;
- rp += sizeof(lnum);
- memcpy(&lnum, rp, sizeof(lnum));
- rec->right = (uint64_t)TCITOHL(lnum) << hdb->apow;
- rp += sizeof(lnum);
- }
- uint16_t snum;
- memcpy(&snum, rp, sizeof(snum));
- rec->psiz = TCITOHS(snum);
- rp += sizeof(snum);
- uint32_t lnum;
- int step;
- TCREADVNUMBUF(rp, lnum, step);
- rec->ksiz = lnum;
- rp += step;
- TCREADVNUMBUF(rp, lnum, step);
- rec->vsiz = lnum;
- rp += step;
- int32_t hsiz = rp - rbuf;
- rec->rsiz = hsiz + rec->ksiz + rec->vsiz + rec->psiz;
- rec->kbuf = NULL;
- rec->vbuf = NULL;
- rec->boff = rec->off + hsiz;
- rec->bbuf = NULL;
- rsiz -= hsiz;
- if(rsiz >= rec->ksiz){
- rec->kbuf = rp;
- rsiz -= rec->ksiz;
- rp += rec->ksiz;
- if(rsiz >= rec->vsiz) rec->vbuf = rp;
- }
- return true;
-}
-
-
-/* Read the body of a record from the file.
- `hdb' specifies the hash database object.
- `rec' specifies the record object.
- The return value is true if successful, else, it is false. */
-static bool tchdbreadrecbody(TCHDB *hdb, TCHREC *rec){
- assert(hdb && rec);
- int32_t bsiz = rec->ksiz + rec->vsiz;
- TCMALLOC(rec->bbuf, bsiz + 1);
- if(!tcseekread(hdb, rec->boff, rec->bbuf, bsiz)) return false;
- rec->kbuf = rec->bbuf;
- rec->vbuf = rec->bbuf + rec->ksiz;
- return true;
-}
-
-
-/* Compare keys of two records.
- `abuf' specifies the pointer to the region of the former.
- `asiz' specifies the size of the region.
- `bbuf' specifies the pointer to the region of the latter.
- `bsiz' specifies the size of the region.
- The return value is 0 if two equals, positive if the formar is big, else, negative. */
-static int tcreckeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){
- assert(abuf && asiz >= 0 && bbuf && bsiz >= 0);
- if(asiz > bsiz) return 1;
- if(asiz < bsiz) return -1;
- return memcmp(abuf, bbuf, asiz);
-}
-
-
-/* Flush the delayed record pool.
- `hdb' specifies the hash database object.
- The return value is true if successful, else, it is false. */
-static bool tchdbflushdrp(TCHDB *hdb){
- assert(hdb);
- if(!HDBLOCKDRP(hdb)) return false;
- if(!hdb->drpool){
- HDBUNLOCKDRP(hdb);
- return true;
- }
- TCDODEBUG(hdb->cnt_flushdrp++);
- if(!tcseekwrite(hdb, hdb->drpoff, TCXSTRPTR(hdb->drpool), TCXSTRSIZE(hdb->drpool))){
- HDBUNLOCKDRP(hdb);
- return false;
- }
- const char *rp = TCXSTRPTR(hdb->drpdef);
- int size = TCXSTRSIZE(hdb->drpdef);
- while(size > 0){
- int ksiz, vsiz;
- memcpy(&ksiz, rp, sizeof(int));
- rp += sizeof(int);
- memcpy(&vsiz, rp, sizeof(int));
- rp += sizeof(int);
- const char *kbuf = rp;
- rp += ksiz;
- const char *vbuf = rp;
- rp += vsiz;
- if(!tchdbputimpl(hdb, kbuf, ksiz, vbuf, vsiz, HDBPDOVER)){
- tcxstrdel(hdb->drpdef);
- tcxstrdel(hdb->drpool);
- hdb->drpool = NULL;
- hdb->drpdef = NULL;
- hdb->drpoff = 0;
- HDBUNLOCKDRP(hdb);
- return false;
- }
- size -= sizeof(int) * 2 + ksiz + vsiz;
- }
- tcxstrdel(hdb->drpdef);
- tcxstrdel(hdb->drpool);
- hdb->drpool = NULL;
- hdb->drpdef = NULL;
- hdb->drpoff = 0;
- uint64_t llnum;
- llnum = hdb->rnum;
- llnum = TCHTOILL(llnum);
- memcpy(hdb->map + HDBRNUMOFF, &llnum, sizeof(llnum));
- llnum = hdb->fsiz;
- llnum = TCHTOILL(llnum);
- memcpy(hdb->map + HDBFSIZOFF, &llnum, sizeof(llnum));
- HDBUNLOCKDRP(hdb);
- return true;
-}
-
-
-/* Adjust the caches for leaves and nodes.
- `hdb' specifies the hash tree database object. */
-static void tchdbcacheadjust(TCHDB *hdb){
- assert(hdb);
- TCDODEBUG(hdb->cnt_adjrecc++);
- tcmdbcutfront(hdb->recc, HDBCACHEOUT);
-}
-
-
-/* Open a database file and connect a hash database object.
- `hdb' specifies the hash database object.
- `path' specifies the path of the database file.
- `omode' specifies the connection mode.
- If successful, the return value is true, else, it is false. */
-static bool tchdbopenimpl(TCHDB *hdb, const char *path, int omode){
- assert(hdb && path);
- int mode = O_RDONLY;
- if(omode & HDBOWRITER){
- mode = O_RDWR;
- if(omode & HDBOCREAT) mode |= O_CREAT;
- }
- int fd = open(path, mode, HDBFILEMODE);
- if(fd < 0){
- int ecode = TCEOPEN;
- switch(errno){
- case EACCES: ecode = TCENOPERM; break;
- case ENOENT: ecode = TCENOFILE; break;
- }
- tchdbsetecode(hdb, ecode, __FILE__, __LINE__, __func__);
- return false;
- }
- if(!(omode & HDBONOLCK)){
- if(!tclock(fd, omode & HDBOWRITER, omode & HDBOLCKNB)){
- tchdbsetecode(hdb, TCELOCK, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- }
- if((omode & HDBOWRITER) && (omode & HDBOTRUNC)){
- if(ftruncate(fd, 0) == -1){
- tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- }
- struct stat sbuf;
- if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){
- tchdbsetecode(hdb, TCESTAT, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- char hbuf[HDBHEADSIZ];
- if((omode & HDBOWRITER) && sbuf.st_size < 1){
- hdb->rnum = 0;
- uint32_t fbpmax = 1 << hdb->fpow;
- uint32_t fbpsiz = HDBFBPBSIZ + fbpmax * HDBFBPESIZ;
- int besiz = (hdb->opts & HDBTLARGE) ? sizeof(int64_t) : sizeof(int32_t);
- hdb->align = 1 << hdb->apow;
- hdb->fsiz = HDBHEADSIZ + besiz * hdb->bnum + fbpsiz;
- uint64_t psiz = tchdbpadsize(hdb);
- hdb->fsiz += psiz;
- hdb->frec = hdb->fsiz;
- tcdumpmeta(hdb, hbuf);
- psiz += besiz * hdb->bnum + fbpsiz;
- char pbuf[HDBIOBUFSIZ];
- memset(pbuf, 0, HDBIOBUFSIZ);
- bool err = false;
- if(!tcwrite(fd, hbuf, HDBHEADSIZ)) err = true;
- while(psiz > 0){
- if(psiz > HDBIOBUFSIZ){
- if(!tcwrite(fd, pbuf, HDBIOBUFSIZ)) err = true;
- psiz -= HDBIOBUFSIZ;
- } else {
- if(!tcwrite(fd, pbuf, psiz)) err = true;
- psiz = 0;
- }
- }
- if(err){
- tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- sbuf.st_size = hdb->fsiz;
- }
- if(lseek(fd, 0, SEEK_SET) == -1){
- tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- if(!tcread(fd, hbuf, HDBHEADSIZ)){
- tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- int type = hdb->type;
- tcloadmeta(hdb, hbuf);
- uint32_t fbpmax = 1 << hdb->fpow;
- uint32_t fbpsiz = HDBFBPBSIZ + fbpmax * HDBFBPESIZ;
- if(!(omode & HDBONOLCK)){
- if(memcmp(hbuf, HDBMAGICDATA, strlen(HDBMAGICDATA)) || hdb->type != type ||
- hdb->frec < HDBHEADSIZ + fbpsiz || hdb->frec > hdb->fsiz || sbuf.st_size < hdb->fsiz){
- tchdbsetecode(hdb, TCEMETA, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- if(sbuf.st_size > hdb->fsiz) hdb->fsiz = sbuf.st_size;
- }
- if((hdb->opts & HDBTDEFLATE) && !_tc_deflate){
- tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- int besiz = (hdb->opts & HDBTLARGE) ? sizeof(int64_t) : sizeof(int32_t);
- size_t msiz = HDBHEADSIZ + hdb->bnum * besiz;
- void *map = mmap(0, msiz, PROT_READ | ((omode & HDBOWRITER) ? PROT_WRITE : 0),
- MAP_SHARED, fd, 0);
- if(map == MAP_FAILED){
- tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
- close(fd);
- return false;
- }
- hdb->fbpmax = fbpmax;
- hdb->fbpsiz = fbpsiz;
- if(omode & HDBOWRITER){
- TCMALLOC(hdb->fbpool, fbpmax * sizeof(HDBFB));
- } else {
- hdb->fbpool = NULL;
- }
- hdb->fbpnum = 0;
- hdb->fbpmis = 0;
- hdb->async = false;
- hdb->drpool = NULL;
- hdb->drpdef = NULL;
- hdb->drpoff = 0;
- hdb->recc = (hdb->rcnum > 0) ? tcmdbnew2(hdb->rcnum * 2 + 1) : NULL;
- hdb->path = tcstrdup(path);
- hdb->omode = omode;
- hdb->iter = 0;
- hdb->map = map;
- hdb->msiz = msiz;
- if(hdb->opts & HDBTLARGE){
- hdb->ba32 = NULL;
- hdb->ba64 = (uint64_t *)((char *)map + HDBHEADSIZ);
- } else {
- hdb->ba32 = (uint32_t *)((char *)map + HDBHEADSIZ);
- hdb->ba64 = NULL;
- }
- hdb->align = 1 << hdb->apow;
- hdb->runit = tclmin(tclmax(hdb->align, HDBMINRUNIT), HDBIOBUFSIZ);
- hdb->zmode = (hdb->opts & HDBTDEFLATE) || (hdb->opts & HDBTTCBS);
- hdb->ecode = TCESUCCESS;
- hdb->fatal = false;
- hdb->fd = fd;
- if(hdb->omode & HDBOWRITER){
- bool err = false;
- if(!(hdb->flags & HDBFOPEN) && !tchdbloadfbp(hdb)) err = true;
- memset(hbuf, 0, 2);
- if(!tcseekwrite(hdb, hdb->msiz, hbuf, 2)) err = true;
- if(err){
- free(hdb->path);
- free(hdb->fbpool);
- munmap(hdb->map, hdb->msiz);
- close(fd);
- hdb->fd = -1;
- return false;
- }
- tchdbsetflag(hdb, HDBFOPEN, true);
- }
- hdb->inode = (uint64_t)sbuf.st_ino;
- hdb->mtime = sbuf.st_mtime;
- return true;
-}
-
-
-/* Close a hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is true, else, it is false. */
-static bool tchdbcloseimpl(TCHDB *hdb){
- assert(hdb);
- bool err = false;
- if(hdb->recc){
- tcmdbdel(hdb->recc);
- hdb->recc = NULL;
- }
- if(hdb->omode & HDBOWRITER){
- if(!tchdbflushdrp(hdb)) err = true;
- if(!tchdbsavefbp(hdb)) err = true;
- free(hdb->fbpool);
- tchdbsetflag(hdb, HDBFOPEN, false);
- }
- free(hdb->path);
- if((hdb->omode & HDBOWRITER) && !tchdbmemsync(hdb, false)) err = true;
- if(munmap(hdb->map, hdb->msiz) == -1){
- tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(close(hdb->fd) == -1){
- tchdbsetecode(hdb, TCECLOSE, __FILE__, __LINE__, __func__);
- err = true;
- }
- hdb->path = NULL;
- hdb->fd = -1;
- return !err;
-}
-
-
-/* Store a record.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- `dmode' specifies behavior when the key overlaps.
- If successful, the return value is true, else, it is false. */
-static bool tchdbputimpl(TCHDB *hdb, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- int dmode){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(hdb->recc) tcmdbout(hdb->recc, kbuf, ksiz);
- uint8_t hash;
- uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
- off_t off = tchdbgetbucket(hdb, bidx);
- off_t entoff = 0;
- TCHREC rec;
- char rbuf[HDBIOBUFSIZ];
- while(off > 0){
- rec.off = off;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return false;
- if(hash > rec.hash){
- off = rec.left;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t));
- } else if(hash < rec.hash){
- off = rec.right;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t)) +
- (hdb->ba64 ? sizeof(uint64_t) : sizeof(uint32_t));
- } else {
- if(!rec.kbuf && !tchdbreadrecbody(hdb, &rec)) return false;
- int kcmp = tcreckeycmp(kbuf, ksiz, rec.kbuf, rec.ksiz);
- if(kcmp > 0){
- off = rec.left;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t));
- } else if(kcmp < 0){
- off = rec.right;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t)) +
- (hdb->ba64 ? sizeof(uint64_t) : sizeof(uint32_t));
- } else {
- switch(dmode){
- case HDBPDKEEP:
- free(rec.bbuf);
- tchdbsetecode(hdb, TCEKEEP, __FILE__, __LINE__, __func__);
- return false;
- case HDBPDCAT:
- if(vsiz < 1){
- free(rec.bbuf);
- return true;
- }
- if(!rec.vbuf && !tchdbreadrecbody(hdb, &rec)) return false;
- int nvsiz = rec.vsiz + vsiz;
- if(rec.bbuf){
- TCREALLOC(rec.bbuf, rec.bbuf, rec.ksiz + nvsiz);
- memcpy(rec.bbuf + rec.ksiz + rec.vsiz, vbuf, vsiz);
- rec.kbuf = rec.bbuf;
- rec.vbuf = rec.kbuf + rec.ksiz;
- rec.vsiz = nvsiz;
- } else {
- TCMALLOC(rec.bbuf, nvsiz);
- memcpy(rec.bbuf, rec.vbuf, rec.vsiz);
- memcpy(rec.bbuf + rec.vsiz, vbuf, vsiz);
- rec.vbuf = rec.bbuf;
- rec.vsiz = nvsiz;
- }
- bool rv = tchdbwriterec(hdb, &rec, bidx, entoff);
- free(rec.bbuf);
- return rv;
- default:
- break;
- }
- free(rec.bbuf);
- rec.ksiz = ksiz;
- rec.vsiz = vsiz;
- rec.kbuf = kbuf;
- rec.vbuf = vbuf;
- return tchdbwriterec(hdb, &rec, bidx, entoff);
- }
- }
- }
- rec.rsiz = HDBMAXHSIZ + ksiz + vsiz;
- if(!tchdbfbpsearch(hdb, &rec)) return false;
- rec.hash = hash;
- rec.left = 0;
- rec.right = 0;
- rec.ksiz = ksiz;
- rec.vsiz = vsiz;
- rec.psiz = 0;
- rec.kbuf = kbuf;
- rec.vbuf = vbuf;
- if(!tchdbwriterec(hdb, &rec, bidx, entoff)) return false;
- hdb->rnum++;
- uint64_t llnum = hdb->rnum;
- llnum = TCHTOILL(llnum);
- memcpy(hdb->map + HDBRNUMOFF, &llnum, sizeof(llnum));
- return true;
-}
-
-
-/* Append a record to the delayed record pool.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- `hash' specifies the second hash value. */
-static void tchdbdrpappend(TCHDB *hdb, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- uint8_t hash){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- TCDODEBUG(hdb->cnt_appenddrp++);
- char rbuf[HDBIOBUFSIZ];
- char *wp = rbuf;
- *(uint8_t *)(wp++) = HDBMAGICREC;
- *(uint8_t *)(wp++) = hash;
- if(hdb->ba64){
- memset(wp, 0, sizeof(uint64_t) * 2);
- wp += sizeof(uint64_t) * 2;
- } else {
- memset(wp, 0, sizeof(uint32_t) * 2);
- wp += sizeof(uint32_t) * 2;
- }
- uint16_t snum;
- char *pwp = wp;
- wp += sizeof(snum);
- int step;
- TCSETVNUMBUF(step, wp, ksiz);
- wp += step;
- TCSETVNUMBUF(step, wp, vsiz);
- wp += step;
- int32_t hsiz = wp - rbuf;
- int32_t rsiz = hsiz + ksiz + vsiz;
- hdb->fsiz += rsiz;
- uint16_t psiz = tchdbpadsize(hdb);
- hdb->fsiz += psiz;
- snum = TCHTOIS(psiz);
- memcpy(pwp, &snum, sizeof(snum));
- TCXSTR *drpool = hdb->drpool;
- TCXSTRCAT(drpool, rbuf, hsiz);
- TCXSTRCAT(drpool, kbuf, ksiz);
- TCXSTRCAT(drpool, vbuf, vsiz);
- if(psiz > 0){
- char pbuf[psiz];
- memset(pbuf, 0, psiz);
- TCXSTRCAT(drpool, pbuf, psiz);
- }
-}
-
-
-/* Store a record in asynchronus fashion.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false. */
-static bool tchdbputasyncimpl(TCHDB *hdb, const char *kbuf, int ksiz, const char *vbuf, int vsiz){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- if(hdb->recc) tcmdbout(hdb->recc, kbuf, ksiz);
- if(!hdb->drpool){
- hdb->drpool = tcxstrnew3(HDBDRPUNIT + HDBDRPLAT);
- hdb->drpdef = tcxstrnew3(HDBDRPUNIT);
- hdb->drpoff = hdb->fsiz;
- }
- uint8_t hash;
- uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
- off_t off = tchdbgetbucket(hdb, bidx);
- off_t entoff = 0;
- TCHREC rec;
- char rbuf[HDBIOBUFSIZ];
- while(off > 0){
- if(off >= hdb->drpoff - hdb->runit){
- TCDODEBUG(hdb->cnt_deferdrp++);
- TCXSTR *drpdef = hdb->drpdef;
- TCXSTRCAT(drpdef, &ksiz, sizeof(ksiz));
- TCXSTRCAT(drpdef, &vsiz, sizeof(vsiz));
- TCXSTRCAT(drpdef, kbuf, ksiz);
- TCXSTRCAT(drpdef, vbuf, vsiz);
- if(TCXSTRSIZE(hdb->drpdef) > HDBDRPUNIT && !tchdbflushdrp(hdb)) return false;
- return true;
- }
- rec.off = off;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return false;
- if(hash > rec.hash){
- off = rec.left;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t));
- } else if(hash < rec.hash){
- off = rec.right;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t)) +
- (hdb->ba64 ? sizeof(uint64_t) : sizeof(uint32_t));
- } else {
- TCDODEBUG(hdb->cnt_deferdrp++);
- TCXSTR *drpdef = hdb->drpdef;
- TCXSTRCAT(drpdef, &ksiz, sizeof(ksiz));
- TCXSTRCAT(drpdef, &vsiz, sizeof(vsiz));
- TCXSTRCAT(drpdef, kbuf, ksiz);
- TCXSTRCAT(drpdef, vbuf, vsiz);
- if(TCXSTRSIZE(hdb->drpdef) > HDBDRPUNIT && !tchdbflushdrp(hdb)) return false;
- return true;
- }
- }
- if(entoff > 0){
- if(hdb->ba64){
- uint64_t llnum = hdb->fsiz >> hdb->apow;
- llnum = TCHTOILL(llnum);
- if(!tcseekwrite(hdb, entoff, &llnum, sizeof(uint64_t))) return false;
- } else {
- uint32_t lnum = hdb->fsiz >> hdb->apow;
- lnum = TCHTOIL(lnum);
- if(!tcseekwrite(hdb, entoff, &lnum, sizeof(uint32_t))) return false;
- }
- } else {
- tchdbsetbucket(hdb, bidx, hdb->fsiz);
- }
- tchdbdrpappend(hdb, kbuf, ksiz, vbuf, vsiz, hash);
- hdb->rnum++;
- if(TCXSTRSIZE(hdb->drpool) > HDBDRPUNIT && !tchdbflushdrp(hdb)) return false;
- return true;
-}
-
-
-/* Remove a record of a hash database object.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false. */
-static bool tchdboutimpl(TCHDB *hdb, const char *kbuf, int ksiz){
- assert(hdb && kbuf && ksiz >= 0);
- if(hdb->recc) tcmdbout(hdb->recc, kbuf, ksiz);
- uint8_t hash;
- uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
- off_t off = tchdbgetbucket(hdb, bidx);
- off_t entoff = 0;
- TCHREC rec;
- char rbuf[HDBIOBUFSIZ];
- while(off > 0){
- rec.off = off;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return false;
- if(hash > rec.hash){
- off = rec.left;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t));
- } else if(hash < rec.hash){
- off = rec.right;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t)) +
- (hdb->ba64 ? sizeof(uint64_t) : sizeof(uint32_t));
- } else {
- if(!rec.kbuf && !tchdbreadrecbody(hdb, &rec)) return false;
- int kcmp = tcreckeycmp(kbuf, ksiz, rec.kbuf, rec.ksiz);
- if(kcmp > 0){
- off = rec.left;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t));
- } else if(kcmp < 0){
- off = rec.right;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- entoff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t)) +
- (hdb->ba64 ? sizeof(uint64_t) : sizeof(uint32_t));
- } else {
- free(rec.bbuf);
- rec.bbuf = NULL;
- if(!tchdbwritefb(hdb, rec.off, rec.rsiz)) return false;
- tchdbfbpinsert(hdb, rec.off, rec.rsiz);
- uint64_t child;
- if(rec.left > 0 && rec.right < 1){
- child = rec.left;
- } else if(rec.left < 1 && rec.right > 0){
- child = rec.right;
- } else if(rec.left < 1 && rec.left < 1){
- child = 0;
- } else {
- child = rec.left;
- uint64_t right = rec.right;
- rec.right = child;
- while(rec.right > 0){
- rec.off = rec.right;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return false;
- }
- if(hdb->ba64){
- off_t toff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint64_t));
- uint64_t llnum = right >> hdb->apow;
- llnum = TCHTOILL(llnum);
- if(!tcseekwrite(hdb, toff, &llnum, sizeof(uint64_t))) return false;
- } else {
- off_t toff = rec.off + (sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t));
- uint32_t lnum = right >> hdb->apow;
- lnum = TCHTOIL(lnum);
- if(!tcseekwrite(hdb, toff, &lnum, sizeof(uint32_t))) return false;
- }
- }
- if(entoff > 0){
- if(hdb->ba64){
- uint64_t llnum = child >> hdb->apow;
- llnum = TCHTOILL(llnum);
- if(!tcseekwrite(hdb, entoff, &llnum, sizeof(uint64_t))) return false;
- } else {
- uint32_t lnum = child >> hdb->apow;
- lnum = TCHTOIL(lnum);
- if(!tcseekwrite(hdb, entoff, &lnum, sizeof(uint32_t))) return false;
- }
- } else {
- tchdbsetbucket(hdb, bidx, child);
- }
- hdb->rnum--;
- uint64_t llnum = hdb->rnum;
- llnum = TCHTOILL(llnum);
- memcpy(hdb->map + HDBRNUMOFF, &llnum, sizeof(llnum));
- return true;
- }
- }
- }
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
-}
-
-
-/* Retrieve a record in a hash database object.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the corresponding
- record. */
-static char *tchdbgetimpl(TCHDB *hdb, const char *kbuf, int ksiz, int *sp){
- assert(hdb && kbuf && ksiz >= 0 && sp);
- if(hdb->recc){
- int tvsiz;
- char *tvbuf = tcmdbget(hdb->recc, kbuf, ksiz, &tvsiz);
- if(tvbuf){
- if(*tvbuf == '*'){
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- free(tvbuf);
- return NULL;
- }
- *sp = tvsiz - 1;
- memmove(tvbuf, tvbuf + 1, tvsiz);
- return tvbuf;
- }
- }
- uint8_t hash;
- uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
- off_t off = tchdbgetbucket(hdb, bidx);
- TCHREC rec;
- char rbuf[HDBIOBUFSIZ];
- while(off > 0){
- rec.off = off;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return NULL;
- if(hash > rec.hash){
- off = rec.left;
- } else if(hash < rec.hash){
- off = rec.right;
- } else {
- if(!rec.kbuf && !tchdbreadrecbody(hdb, &rec)) return NULL;
- int kcmp = tcreckeycmp(kbuf, ksiz, rec.kbuf, rec.ksiz);
- if(kcmp > 0){
- off = rec.left;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- } else if(kcmp < 0){
- off = rec.right;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- } else {
- if(!rec.vbuf && !tchdbreadrecbody(hdb, &rec)) return NULL;
- if(hdb->zmode){
- int zsiz;
- char *zbuf;
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_inflate(rec.vbuf, rec.vsiz, &zsiz, _TCZMRAW);
- } else {
- zbuf = tcbsdecode(rec.vbuf, rec.vsiz, &zsiz);
- }
- free(rec.bbuf);
- if(!zbuf){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- return NULL;
- }
- if(hdb->recc){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput3(hdb->recc, kbuf, ksiz, "=", 1, zbuf, zsiz);
- }
- *sp = zsiz;
- return zbuf;
- }
- if(rec.bbuf){
- memmove(rec.bbuf, rec.vbuf, rec.vsiz);
- rec.bbuf[rec.vsiz] = '\0';
- *sp = rec.vsiz;
- return rec.bbuf;
- }
- if(hdb->recc){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput3(hdb->recc, kbuf, ksiz, "=", 1, rec.vbuf, rec.vsiz);
- }
- *sp = rec.vsiz;
- char *rv;
- TCMEMDUP(rv, rec.vbuf, rec.vsiz);
- return rv;
- }
- }
- }
- if(hdb->recc){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput(hdb->recc, kbuf, ksiz, "*", 1);
- }
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- return NULL;
-}
-
-
-/* Retrieve a record in a hash database object and write the value into a buffer.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the buffer into which the value of the corresponding record is
- written.
- `max' specifies the size of the buffer.
- If successful, the return value is the size of the written data, else, it is -1. */
-static int tchdbgetintobuf(TCHDB *hdb, const char *kbuf, int ksiz, char *vbuf, int max){
- assert(hdb && kbuf && ksiz >= 0 && vbuf && max >= 0);
- if(hdb->recc){
- int tvsiz;
- char *tvbuf = tcmdbget(hdb->recc, kbuf, ksiz, &tvsiz);
- if(tvbuf){
- if(*tvbuf == '*'){
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- free(tvbuf);
- return -1;
- }
- tvsiz = tclmin(tvsiz - 1, max);
- memcpy(vbuf, tvbuf + 1, tvsiz);
- free(tvbuf);
- return tvsiz;
- }
- }
- uint8_t hash;
- uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
- off_t off = tchdbgetbucket(hdb, bidx);
- TCHREC rec;
- char rbuf[HDBIOBUFSIZ];
- while(off > 0){
- rec.off = off;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return -1;
- if(hash > rec.hash){
- off = rec.left;
- } else if(hash < rec.hash){
- off = rec.right;
- } else {
- if(!rec.kbuf && !tchdbreadrecbody(hdb, &rec)) return -1;
- int kcmp = tcreckeycmp(kbuf, ksiz, rec.kbuf, rec.ksiz);
- if(kcmp > 0){
- off = rec.left;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- } else if(kcmp < 0){
- off = rec.right;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- } else {
- if(!rec.vbuf && !tchdbreadrecbody(hdb, &rec)) return -1;
- if(hdb->zmode){
- int zsiz;
- char *zbuf;
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_inflate(rec.vbuf, rec.vsiz, &zsiz, _TCZMRAW);
- } else {
- zbuf = tcbsdecode(rec.vbuf, rec.vsiz, &zsiz);
- }
- free(rec.bbuf);
- if(!zbuf){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- return -1;
- }
- if(hdb->recc){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput3(hdb->recc, kbuf, ksiz, "=", 1, zbuf, zsiz);
- }
- zsiz = tclmin(zsiz, max);
- memcpy(vbuf, zbuf, zsiz);
- free(zbuf);
- return zsiz;
- }
- if(hdb->recc){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput3(hdb->recc, kbuf, ksiz, "=", 1, rec.vbuf, rec.vsiz);
- }
- int vsiz = tclmin(rec.vsiz, max);
- memcpy(vbuf, rec.vbuf, vsiz);
- free(rec.bbuf);
- return vsiz;
- }
- }
- }
- if(hdb->recc){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput(hdb->recc, kbuf, ksiz, "*", 1);
- }
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- return -1;
-}
-
-
-/* Get the size of the value of a record in a hash database object.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1. */
-static int tchdbvsizimpl(TCHDB *hdb, const char *kbuf, int ksiz){
- assert(hdb && kbuf && ksiz >= 0);
- if(hdb->recc){
- int tvsiz;
- char *tvbuf = tcmdbget(hdb->recc, kbuf, ksiz, &tvsiz);
- if(tvbuf){
- if(*tvbuf == '*'){
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- free(tvbuf);
- return -1;
- }
- free(tvbuf);
- return tvsiz - 1;
- }
- }
- uint8_t hash;
- uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);
- off_t off = tchdbgetbucket(hdb, bidx);
- TCHREC rec;
- char rbuf[HDBIOBUFSIZ];
- while(off > 0){
- rec.off = off;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return -1;
- if(hash > rec.hash){
- off = rec.left;
- } else if(hash < rec.hash){
- off = rec.right;
- } else {
- if(!rec.kbuf && !tchdbreadrecbody(hdb, &rec)) return -1;
- int kcmp = tcreckeycmp(kbuf, ksiz, rec.kbuf, rec.ksiz);
- if(kcmp > 0){
- off = rec.left;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- } else if(kcmp < 0){
- off = rec.right;
- free(rec.bbuf);
- rec.kbuf = NULL;
- rec.bbuf = NULL;
- } else {
- if(hdb->zmode){
- if(!rec.vbuf && !tchdbreadrecbody(hdb, &rec)) return -1;
- int zsiz;
- char *zbuf;
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_inflate(rec.vbuf, rec.vsiz, &zsiz, _TCZMRAW);
- } else {
- zbuf = tcbsdecode(rec.vbuf, rec.vsiz, &zsiz);
- }
- free(rec.bbuf);
- if(!zbuf){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- return -1;
- }
- if(hdb->recc){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput3(hdb->recc, kbuf, ksiz, "=", 1, zbuf, zsiz);
- }
- free(zbuf);
- return zsiz;
- }
- if(hdb->recc && rec.vbuf){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput3(hdb->recc, kbuf, ksiz, "=", 1, rec.vbuf, rec.vsiz);
- }
- free(rec.bbuf);
- return rec.vsiz;
- }
- }
- }
- if(hdb->recc){
- if(tcmdbrnum(hdb->recc) >= hdb->rcnum) tchdbcacheadjust(hdb);
- tcmdbput(hdb->recc, kbuf, ksiz, "*", 1);
- }
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- return -1;
-}
-
-
-/* Initialize the iterator of a hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is true, else, it is false. */
-static bool tchdbiterinitimpl(TCHDB *hdb){
- assert(hdb);
- hdb->iter = hdb->frec;
- return true;
-}
-
-
-/* Get the next key of the iterator of a hash database object.
- `hdb' specifies the hash database object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the next key, else, it is
- `NULL'. */
-static char *tchdbiternextimpl(TCHDB *hdb, int *sp){
- assert(hdb && sp);
- TCHREC rec;
- char rbuf[HDBIOBUFSIZ];
- while(hdb->iter < hdb->fsiz){
- rec.off = hdb->iter;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return NULL;
- hdb->iter += rec.rsiz;
- if(rec.magic == HDBMAGICREC){
- if(rec.kbuf){
- *sp = rec.ksiz;
- char *rv;
- TCMEMDUP(rv, rec.kbuf, rec.ksiz);
- return rv;
- }
- if(!tchdbreadrecbody(hdb, &rec)) return NULL;
- rec.bbuf[rec.ksiz] = '\0';
- *sp = rec.ksiz;
- return rec.bbuf;
- }
- }
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- return NULL;
-}
-
-
-/* Get the next extensible objects of the iterator of a hash database object. */
-static bool tchdbiternextintoxstr(TCHDB *hdb, TCXSTR *kxstr, TCXSTR *vxstr){
- assert(hdb && kxstr && vxstr);
- TCHREC rec;
- char rbuf[HDBIOBUFSIZ];
- while(hdb->iter < hdb->fsiz){
- rec.off = hdb->iter;
- if(!tchdbreadrec(hdb, &rec, rbuf)) return false;
- hdb->iter += rec.rsiz;
- if(rec.magic == HDBMAGICREC){
- if(!rec.vbuf && !tchdbreadrecbody(hdb, &rec)) return false;
- tcxstrclear(kxstr);
- TCXSTRCAT(kxstr, rec.kbuf, rec.ksiz);
- tcxstrclear(vxstr);
- if(hdb->zmode){
- int zsiz;
- char *zbuf;
- if(hdb->opts & HDBTDEFLATE){
- zbuf = _tc_inflate(rec.vbuf, rec.vsiz, &zsiz, _TCZMRAW);
- } else {
- zbuf = tcbsdecode(rec.vbuf, rec.vsiz, &zsiz);
- }
- if(!zbuf){
- tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);
- free(rec.bbuf);
- return false;
- }
- TCXSTRCAT(vxstr, zbuf, zsiz);
- free(zbuf);
- } else {
- TCXSTRCAT(vxstr, rec.vbuf, rec.vsiz);
- }
- free(rec.bbuf);
- return true;
- }
- }
- tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__);
- return false;
-}
-
-
-/* Optimize the file of a hash database object.
- `hdb' specifies the hash database object.
- `bnum' specifies the number of elements of the bucket array.
- `apow' specifies the size of record alignment by power of 2.
- `fpow' specifies the maximum number of elements of the free block pool by power of 2.
- `opts' specifies options by bitwise or.
- If successful, the return value is true, else, it is false. */
-static bool tchdboptimizeimpl(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){
- assert(hdb);
- if(bnum < 1){
- bnum = hdb->rnum * 2 + 1;
- if(bnum < HDBDEFBNUM) bnum = HDBDEFBNUM;
- }
- if(apow < 0) apow = hdb->apow;
- if(fpow < 0) fpow = hdb->fpow;
- if(opts == UINT8_MAX) opts = hdb->opts;
- char *tpath = tcsprintf("%s%ctmp%c%llu", hdb->path, MYEXTCHR, MYEXTCHR, hdb->inode);
- TCHDB *thdb = tchdbnew();
- tchdbtune(thdb, bnum, apow, fpow, opts);
- if(!tchdbopen(thdb, tpath, HDBOWRITER | HDBOCREAT | HDBOTRUNC)){
- tchdbsetecode(hdb, thdb->ecode, __FILE__, __LINE__, __func__);
- tchdbdel(thdb);
- free(tpath);
- return false;
- }
- bool err = false;
- if(!tchdbiterinitimpl(hdb)) err = true;
- TCXSTR *key = tcxstrnew();
- TCXSTR *val = tcxstrnew();
- while(!err && tchdbiternextintoxstr(hdb, key, val)){
- if(!tchdbputkeep(thdb, TCXSTRPTR(key), TCXSTRSIZE(key), TCXSTRPTR(val), TCXSTRSIZE(val))){
- tchdbsetecode(hdb, thdb->ecode, __FILE__, __LINE__, __func__);
- err = true;
- }
- }
- tcxstrdel(val);
- tcxstrdel(key);
- if(!tchdbclose(thdb)){
- tchdbsetecode(hdb, thdb->ecode, __FILE__, __LINE__, __func__);
- err = true;
- }
- tchdbdel(thdb);
- if(unlink(hdb->path) == -1){
- tchdbsetecode(hdb, TCEUNLINK, __FILE__, __LINE__, __func__);
- err = true;
- }
- if(rename(tpath, hdb->path) == -1){
- tchdbsetecode(hdb, TCERENAME, __FILE__, __LINE__, __func__);
- err = true;
- }
- free(tpath);
- if(err) return false;
- tpath = tcstrdup(hdb->path);
- int omode = (hdb->omode & ~HDBOCREAT) & ~HDBOTRUNC;
- if(!tchdbcloseimpl(hdb)){
- free(tpath);
- return false;
- }
- bool rv = tchdbopenimpl(hdb, tpath, omode);
- free(tpath);
- return rv;
-}
-
-
-/* Remove all records of a hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is true, else, it is false. */
-static bool tchdbvanishimpl(TCHDB *hdb){
- assert(hdb);
- char *path = tcstrdup(hdb->path);
- int omode = hdb->omode;
- bool err = false;
- if(!tchdbcloseimpl(hdb)) err = true;
- if(!tchdbopenimpl(hdb, path, HDBOTRUNC | omode)) err = true;
- free(path);
- return !err;
-}
-
-
-/* Lock a method of the hash database object.
- `hdb' specifies the hash database object.
- `wr' specifies whether the lock is writer or not.
- If successful, the return value is true, else, it is false. */
-static bool tchdblockmethod(TCHDB *hdb, bool wr){
- assert(hdb);
- if(wr ? pthread_rwlock_wrlock(hdb->mmtx) != 0 : pthread_rwlock_rdlock(hdb->mmtx) != 0){
- tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Unlock a method of the hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is true, else, it is false. */
-static bool tchdbunlockmethod(TCHDB *hdb){
- assert(hdb);
- if(pthread_rwlock_unlock(hdb->mmtx) != 0){
- tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Lock the delayed record pool of the hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is true, else, it is false. */
-static bool tchdblockdrp(TCHDB *hdb){
- assert(hdb);
- if(pthread_mutex_lock(hdb->dmtx) != 0){
- tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-/* Unlock the delayed record pool of the hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is true, else, it is false. */
-static bool tchdbunlockdrp(TCHDB *hdb){
- assert(hdb);
- if(pthread_mutex_unlock(hdb->dmtx) != 0){
- tchdbsetecode(hdb, TCETHREAD, __FILE__, __LINE__, __func__);
- return false;
- }
- TCTESTYIELD();
- return true;
-}
-
-
-
-/*************************************************************************************************
- * debugging functions
- *************************************************************************************************/
-
-
-/* Print meta data of the header into the debugging output.
- `hdb' specifies the hash database object. */
-void tchdbprintmeta(TCHDB *hdb){
- assert(hdb);
- if(hdb->dbgfd < 0) return;
- char buf[HDBIOBUFSIZ];
- char *wp = buf;
- wp += sprintf(wp, "META:");
- wp += sprintf(wp, " mmtx=%p", (void *)hdb->mmtx);
- wp += sprintf(wp, " dmtx=%p", (void *)hdb->dmtx);
- wp += sprintf(wp, " eckey=%p", (void *)hdb->eckey);
- wp += sprintf(wp, " type=%02X", hdb->type);
- wp += sprintf(wp, " flags=%02X", hdb->flags);
- wp += sprintf(wp, " bnum=%llu", (unsigned long long)hdb->bnum);
- wp += sprintf(wp, " apow=%u", hdb->apow);
- wp += sprintf(wp, " fpow=%u", hdb->fpow);
- wp += sprintf(wp, " opts=%u", hdb->opts);
- wp += sprintf(wp, " path=%s", hdb->path ? hdb->path : "-");
- wp += sprintf(wp, " fd=%u", hdb->fd);
- wp += sprintf(wp, " omode=%u", hdb->omode);
- wp += sprintf(wp, " rnum=%llu", (unsigned long long)hdb->rnum);
- wp += sprintf(wp, " fsiz=%llu", (unsigned long long)hdb->fsiz);
- wp += sprintf(wp, " frec=%llu", (unsigned long long)hdb->frec);
- wp += sprintf(wp, " iter=%llu", (unsigned long long)hdb->iter);
- wp += sprintf(wp, " map=%p", (void *)hdb->map);
- wp += sprintf(wp, " msiz=%llu", (unsigned long long)hdb->msiz);
- wp += sprintf(wp, " ba32=%p", (void *)hdb->ba32);
- wp += sprintf(wp, " ba64=%p", (void *)hdb->ba64);
- wp += sprintf(wp, " align=%u", hdb->align);
- wp += sprintf(wp, " runit=%u", hdb->runit);
- wp += sprintf(wp, " zmode=%u", hdb->zmode);
- wp += sprintf(wp, " fbpmax=%d", hdb->fbpmax);
- wp += sprintf(wp, " fbpsiz=%d", hdb->fbpsiz);
- wp += sprintf(wp, " fbpool=%p", (void *)hdb->fbpool);
- wp += sprintf(wp, " fbpnum=%d", hdb->fbpnum);
- wp += sprintf(wp, " fbpmis=%d", hdb->fbpmis);
- wp += sprintf(wp, " drpool=%p", (void *)hdb->drpool);
- wp += sprintf(wp, " drpdef=%p", (void *)hdb->drpdef);
- wp += sprintf(wp, " drpoff=%llu", (unsigned long long)hdb->drpoff);
- wp += sprintf(wp, " recc=%p", (void *)hdb->recc);
- wp += sprintf(wp, " rcnum=%u", hdb->rcnum);
- wp += sprintf(wp, " ecode=%d", hdb->ecode);
- wp += sprintf(wp, " fatal=%u", hdb->fatal);
- wp += sprintf(wp, " inode=%llu", (unsigned long long)(uint64_t)hdb->inode);
- wp += sprintf(wp, " mtime=%llu", (unsigned long long)(uint64_t)hdb->mtime);
- wp += sprintf(wp, " dbgfd=%d", hdb->dbgfd);
- wp += sprintf(wp, " cnt_writerec=%lld", (long long)hdb->cnt_writerec);
- wp += sprintf(wp, " cnt_reuserec=%lld", (long long)hdb->cnt_reuserec);
- wp += sprintf(wp, " cnt_moverec=%lld", (long long)hdb->cnt_moverec);
- wp += sprintf(wp, " cnt_readrec=%lld", (long long)hdb->cnt_readrec);
- wp += sprintf(wp, " cnt_searchfbp=%lld", (long long)hdb->cnt_searchfbp);
- wp += sprintf(wp, " cnt_insertfbp=%lld", (long long)hdb->cnt_insertfbp);
- wp += sprintf(wp, " cnt_splicefbp=%lld", (long long)hdb->cnt_splicefbp);
- wp += sprintf(wp, " cnt_dividefbp=%lld", (long long)hdb->cnt_dividefbp);
- wp += sprintf(wp, " cnt_mergefbp=%lld", (long long)hdb->cnt_mergefbp);
- wp += sprintf(wp, " cnt_reducefbp=%lld", (long long)hdb->cnt_reducefbp);
- wp += sprintf(wp, " cnt_appenddrp=%lld", (long long)hdb->cnt_appenddrp);
- wp += sprintf(wp, " cnt_deferdrp=%lld", (long long)hdb->cnt_deferdrp);
- wp += sprintf(wp, " cnt_flushdrp=%lld", (long long)hdb->cnt_flushdrp);
- wp += sprintf(wp, " cnt_adjrecc=%lld", (long long)hdb->cnt_adjrecc);
- *(wp++) = '\n';
- tcwrite(hdb->dbgfd, buf, wp - buf);
-}
-
-
-/* Print a record information into the debugging output.
- `hdb' specifies the hash database object.
- `rec' specifies the record. */
-void tchdbprintrec(TCHDB *hdb, TCHREC *rec){
- assert(hdb && rec);
- if(hdb->dbgfd < 0) return;
- char buf[HDBIOBUFSIZ];
- char *wp = buf;
- wp += sprintf(wp, "REC:");
- wp += sprintf(wp, " off=%llu", (unsigned long long)rec->off);
- wp += sprintf(wp, " rsiz=%u", rec->rsiz);
- wp += sprintf(wp, " magic=%02X", rec->magic);
- wp += sprintf(wp, " hash=%02X", rec->hash);
- wp += sprintf(wp, " left=%llu", (unsigned long long)rec->left);
- wp += sprintf(wp, " right=%llu", (unsigned long long)rec->right);
- wp += sprintf(wp, " ksiz=%u", rec->ksiz);
- wp += sprintf(wp, " vsiz=%u", rec->vsiz);
- wp += sprintf(wp, " psiz=%u", rec->psiz);
- wp += sprintf(wp, " kbuf=%p", (void *)rec->kbuf);
- wp += sprintf(wp, " vbuf=%p", (void *)rec->vbuf);
- wp += sprintf(wp, " boff=%llu", (unsigned long long)rec->boff);
- wp += sprintf(wp, " bbuf=%p", (void *)rec->bbuf);
- *(wp++) = '\n';
- tcwrite(hdb->dbgfd, buf, wp - buf);
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The hash database API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#ifndef _TCHDB_H /* duplication check */
-#define _TCHDB_H
-
-#if defined(__cplusplus)
-#define __TCHDB_CLINKAGEBEGIN extern "C" {
-#define __TCHDB_CLINKAGEEND }
-#else
-#define __TCHDB_CLINKAGEBEGIN
-#define __TCHDB_CLINKAGEEND
-#endif
-__TCHDB_CLINKAGEBEGIN
-
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <time.h>
-#include <tcutil.h>
-
-
-
-/*************************************************************************************************
- * API
- *************************************************************************************************/
-
-
-typedef struct { /* type of structure for a hash database */
- void *mmtx; /* mutex for method */
- void *dmtx; /* mutex for DRP */
- void *eckey; /* key for thread specific error code */
- uint8_t type; /* database type */
- uint8_t flags; /* additional flags */
- uint64_t bnum; /* number of the bucket array */
- uint8_t apow; /* power of record alignment */
- uint8_t fpow; /* power of free block pool number */
- uint8_t opts; /* options */
- char *path; /* path of the database file */
- int fd; /* file descriptor of the database file */
- uint32_t omode; /* connection mode */
- uint64_t rnum; /* number of the records */
- uint64_t fsiz; /* size of the database file */
- uint64_t frec; /* offset of the first record */
- uint64_t lrec; /* offset of the last record */
- uint64_t iter; /* offset of the iterator */
- char *map; /* pointer to the mapped memory */
- uint64_t msiz; /* size of the mapped memory */
- uint32_t *ba32; /* 32-bit bucket array */
- uint64_t *ba64; /* 64-bit bucket array */
- uint32_t align; /* record alignment */
- uint32_t runit; /* record reading unit */
- bool zmode; /* whether compression is used */
- int32_t fbpmax; /* maximum number of the free block pool */
- int32_t fbpsiz; /* size of the free block pool */
- void *fbpool; /* free block pool */
- int32_t fbpnum; /* number of the free block pool */
- int32_t fbpmis; /* number of missing retrieval of the free block pool */
- bool async; /* whether asynchronous storing is called */
- TCXSTR *drpool; /* delayed record pool */
- TCXSTR *drpdef; /* deferred records of the delayed record pool */
- uint64_t drpoff; /* offset of the delayed record pool */
- TCMDB *recc; /* cache for records */
- uint32_t rcnum; /* max number of cached records */
- int ecode; /* last happened error code */
- bool fatal; /* whether a fatal error occured */
- uint64_t inode; /* inode number */
- time_t mtime; /* modification time */
- int dbgfd; /* file descriptor for debugging */
- int64_t cnt_writerec; /* tesing counter for record write times */
- int64_t cnt_reuserec; /* tesing counter for record reuse times */
- int64_t cnt_moverec; /* tesing counter for record move times */
- int64_t cnt_readrec; /* tesing counter for record read times */
- int64_t cnt_searchfbp; /* tesing counter for FBP search times */
- int64_t cnt_insertfbp; /* tesing counter for FBP insert times */
- int64_t cnt_splicefbp; /* tesing counter for FBP splice times */
- int64_t cnt_dividefbp; /* tesing counter for FBP divide times */
- int64_t cnt_mergefbp; /* tesing counter for FBP merge times */
- int64_t cnt_reducefbp; /* tesing counter for FBP reduce times */
- int64_t cnt_appenddrp; /* tesing counter for DRP append times */
- int64_t cnt_deferdrp; /* tesing counter for DRP defer times */
- int64_t cnt_flushdrp; /* tesing counter for DRP flush times */
- int64_t cnt_adjrecc; /* tesing counter for record cache adjust times */
-} TCHDB;
-
-enum { /* enumeration for error codes */
- TCESUCCESS, /* success */
- TCETHREAD, /* threading error */
- TCEINVALID, /* invalid operation */
- TCENOFILE, /* file not found */
- TCENOPERM, /* no permission */
- TCEMETA, /* invalid meta data */
- TCERHEAD, /* invalid record header */
- TCEOPEN, /* open error */
- TCECLOSE, /* close error */
- TCETRUNC, /* trunc error */
- TCESYNC, /* sync error */
- TCESTAT, /* stat error */
- TCESEEK, /* seek error */
- TCEREAD, /* read error */
- TCEWRITE, /* write error */
- TCEMMAP, /* mmap error */
- TCELOCK, /* lock error */
- TCEUNLINK, /* unlink error */
- TCERENAME, /* rename error */
- TCEMKDIR, /* mkdir error */
- TCERMDIR, /* rmdir error */
- TCEKEEP, /* existing record */
- TCENOREC, /* no record found */
- TCEMISC = 9999 /* miscellaneous error */
-};
-
-enum { /* enumeration for database type */
- HDBTHASH, /* hash table */
- HDBTBTREE /* B+ tree */
-};
-
-enum { /* enumeration for additional flags */
- HDBFOPEN = 1 << 0, /* whether opened */
- HDBFFATAL = 1 << 1 /* whetehr with fatal error */
-};
-
-enum { /* enumeration for tuning options */
- HDBTLARGE = 1 << 0, /* use 64-bit bucket array */
- HDBTDEFLATE = 1 << 1, /* compress each record with Deflate */
- HDBTTCBS = 1 << 2 /* compress each record with TCBS */
-};
-
-enum { /* enumeration for open modes */
- HDBOREADER = 1 << 0, /* open as a reader */
- HDBOWRITER = 1 << 1, /* open as a writer */
- HDBOCREAT = 1 << 2, /* writer creating */
- HDBOTRUNC = 1 << 3, /* writer truncating */
- HDBONOLCK = 1 << 4, /* open without locking */
- HDBOLCKNB = 1 << 5 /* lock without blocking */
-};
-
-
-/* Get the message string corresponding to an error code.
- `ecode' specifies the error code.
- The return value is the message string of the error code. */
-const char *tchdberrmsg(int ecode);
-
-
-/* Create a hash database object.
- The return value is the new hash database object. */
-TCHDB *tchdbnew(void);
-
-
-/* Delete a hash database object.
- `hdb' specifies the hash database object.
- If the database is not closed, it is closed implicitly. Note that the deleted object and its
- derivatives can not be used anymore. */
-void tchdbdel(TCHDB *hdb);
-
-
-/* Get the last happened error code of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the last happened error code.
- The following error code is defined: `TCESUCCESS' for success, `TCETHREAD' for threading
- error, `TCEINVALID' for invalid operation, `TCENOFILE' for file not found, `TCENOPERM' for no
- permission, `TCEMETA' for invalid meta data, `TCERHEAD' for invalid record header, `TCEOPEN'
- for open error, `TCECLOSE' for close error, `TCETRUNC' for trunc error, `TCESYNC' for sync
- error, `TCESTAT' for stat error, `TCESEEK' for seek error, `TCEREAD' for read error,
- `TCEWRITE' for write error, `TCEMMAP' for mmap error, `TCELOCK' for lock error, `TCEUNLINK'
- for unlink error, `TCERENAME' for rename error, `TCEMKDIR' for mkdir error, `TCERMDIR' for
- rmdir error, `TCEKEEP' for existing record, `TCENOREC' for no record found, and `TCEMISC' for
- miscellaneous error. */
-int tchdbecode(TCHDB *hdb);
-
-
-/* Set mutual exclusion control of a hash database object for threading.
- `hdb' specifies the hash database object which is not opened.
- If successful, the return value is true, else, it is false.
- Note that the mutual exclusion control is needed if the object is shared by plural threads and
- this function should should be called before the database is opened. */
-bool tchdbsetmutex(TCHDB *hdb);
-
-
-/* Set the tuning parameters of a hash database object.
- `hdb' specifies the hash database object which is not opened.
- `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the
- default value is specified. The default value is 16381. Suggested size of the bucket array
- is about from 0.5 to 4 times of the number of all records to be stored.
- `apow' specifies the size of record alignment by power of 2. If it is negative, the default
- value is specified. The default value is 4 standing for 2^4=16.
- `fpow' specifies the maximum number of elements of the free block pool by power of 2. If it
- is negative, the default value is specified. The default value is 10 standing for 2^10=1024.
- `opts' specifies options by bitwise or: `HDBTLARGE' specifies that the size of the database
- can be larger than 2GB by using 64-bit bucket array, `HDBTDEFLATE' specifies that each record
- is compressed with Deflate encoding, `HDBTTCBS' specifies that each record is compressed with
- TCBS encoding.
- If successful, the return value is true, else, it is false.
- Note that the tuning parameters should be set before the database is opened. */
-bool tchdbtune(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
-
-
-/* Set the caching parameters of a hash database object.
- `hdb' specifies the hash database object which is not opened.
- `rcnum' specifies the maximum number of records to be cached. If it is not more than 0, the
- record cache is disabled. It is disabled by default.
- If successful, the return value is true, else, it is false.
- Note that the caching parameters should be set before the database is opened. */
-bool tchdbsetcache(TCHDB *hdb, int32_t rcnum);
-
-
-/* Open a database file and connect a hash database object.
- `hdb' specifies the hash database object which is not opened.
- `path' specifies the path of the database file.
- `omode' specifies the connection mode: `HDBOWRITER' as a writer, `HDBOREADER' as a reader.
- If the mode is `HDBOWRITER', the following may be added by bitwise or: `HDBOCREAT', which
- means it creates a new database if not exist, `HDBOTRUNC', which means it creates a new
- database regardless if one exists. Both of `HDBOREADER' and `HDBOWRITER' can be added to by
- bitwise or: `HDBONOLCK', which means it opens the database file without file locking, or
- `HDBOLCKNB', which means locking is performed without blocking.
- If successful, the return value is true, else, it is false. */
-bool tchdbopen(TCHDB *hdb, const char *path, int omode);
-
-
-/* Close a hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is true, else, it is false.
- Update of a database is assured to be written when the database is closed. If a writer opens
- a database but does not close it appropriately, the database will be broken. */
-bool tchdbclose(TCHDB *hdb);
-
-
-/* Store a record into a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, it is overwritten. */
-bool tchdbput(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a string record into a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, it is overwritten. */
-bool tchdbput2(TCHDB *hdb, const char *kstr, const char *vstr);
-
-
-/* Store a new record into a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tchdbputkeep(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a new string record into a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tchdbputkeep2(TCHDB *hdb, const char *kstr, const char *vstr);
-
-
-/* Concatenate a value at the end of the existing record in a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If there is no corresponding record, a new record is created. */
-bool tchdbputcat(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Concatenate a string value at the end of the existing record in a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If there is no corresponding record, a new record is created. */
-bool tchdbputcat2(TCHDB *hdb, const char *kstr, const char *vstr);
-
-
-/* Store a record into a hash database object in asynchronous fashion.
- `hdb' specifies the hash database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, it is overwritten. Records passed to
- this function are accumulated into the inner buffer and wrote into the file at a blast. */
-bool tchdbputasync(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a string record into a hash database object in asynchronous fashion.
- `hdb' specifies the hash database object connected as a writer.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, it is overwritten. Records passed to
- this function are accumulated into the inner buffer and wrote into the file at a blast. */
-bool tchdbputasync2(TCHDB *hdb, const char *kstr, const char *vstr);
-
-
-/* Remove a record of a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true, else, it is false. */
-bool tchdbout(TCHDB *hdb, const void *kbuf, int ksiz);
-
-
-/* Remove a string record of a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `kstr' specifies the string of the key.
- If successful, the return value is true, else, it is false. */
-bool tchdbout2(TCHDB *hdb, const char *kstr);
-
-
-/* Retrieve a record in a hash database object.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the corresponding
- record. `NULL' is returned if no record corresponds.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-void *tchdbget(TCHDB *hdb, const void *kbuf, int ksiz, int *sp);
-
-
-/* Retrieve a string record in a hash database object.
- `hdb' specifies the hash database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the string of the value of the corresponding record.
- `NULL' is returned if no record corresponds.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tchdbget2(TCHDB *hdb, const char *kstr);
-
-
-/* Retrieve a record in a hash database object and write the value into a buffer.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the buffer into which the value of the corresponding record is
- written.
- `max' specifies the size of the buffer.
- If successful, the return value is the size of the written data, else, it is -1. -1 is
- returned if no record corresponds to the specified key.
- Note that an additional zero code is not appended at the end of the region of the writing
- buffer. */
-int tchdbget3(TCHDB *hdb, const void *kbuf, int ksiz, void *vbuf, int max);
-
-
-/* Get the size of the value of a record in a hash database object.
- `hdb' specifies the hash database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1. */
-int tchdbvsiz(TCHDB *hdb, const void *kbuf, int ksiz);
-
-
-/* Get the size of the value of a string record in a hash database object.
- `hdb' specifies the hash database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1. */
-int tchdbvsiz2(TCHDB *hdb, const char *kstr);
-
-
-/* Initialize the iterator of a hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is true, else, it is false.
- The iterator is used in order to access the key of every record stored in a database. */
-bool tchdbiterinit(TCHDB *hdb);
-
-
-/* Get the next key of the iterator of a hash database object.
- `hdb' specifies the hash database object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the next key, else, it is
- `NULL'. `NULL' is returned when no record is to be get out of the iterator.
- Because an additional zero code is appended at the end of the region of the return value, the
- return value can be treated as a character string. Because the region of the return value is
- allocated with the `malloc' call, it should be released with the `free' call when it is no
- longer in use. It is possible to access every record by iteration of calling this function.
- It is allowed to update or remove records whose keys are fetched while the iteration.
- However, it is not assured if updating the database is occurred while the iteration. Besides,
- the order of this traversal access method is arbitrary, so it is not assured that the order of
- storing matches the one of the traversal access. */
-void *tchdbiternext(TCHDB *hdb, int *sp);
-
-
-/* Get the next key string of the iterator of a hash database object.
- `hdb' specifies the hash database object.
- If successful, the return value is the string of the next key, else, it is `NULL'. `NULL' is
- returned when no record is to be get out of the iterator.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. It is possible to access every
- record by iteration of calling this function. However, it is not assured if updating the
- database is occurred while the iteration. Besides, the order of this traversal access method
- is arbitrary, so it is not assured that the order of storing matches the one of the traversal
- access. */
-char *tchdbiternext2(TCHDB *hdb);
-
-
-/* Get the next extensible objects of the iterator of a hash database object.
- `hdb' specifies the hash database object.
- `kxstr' specifies the object into which the next key is wrote down.
- `vxstr' specifies the object into which the next value is wrote down.
- If successful, the return value is true, else, it is false. False is returned when no record
- is to be get out of the iterator. */
-bool tchdbiternext3(TCHDB *hdb, TCXSTR *kxstr, TCXSTR *vxstr);
-
-
-/* Get forward matching keys in a hash database object.
- `hdb' specifies the hash database object.
- `pbuf' specifies the pointer to the region of the prefix.
- `psiz' specifies the size of the region of the prefix.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the corresponding keys. This function does never fail
- and return an empty list even if no key corresponds.
- Because the object of the return value is created with the function `tclistnew', it should be
- deleted with the function `tclistdel' when it is no longer in use. Note that this function
- may be very slow because every key in the database is scanned. */
-TCLIST *tchdbfwmkeys(TCHDB *hdb, const void *pbuf, int psiz, int max);
-
-
-/* Get forward matching string keys in a hash database object.
- `hdb' specifies the hash database object.
- `pstr' specifies the string of the prefix.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the corresponding keys. This function does never fail
- and return an empty list even if no key corresponds.
- Because the object of the return value is created with the function `tclistnew', it should be
- deleted with the function `tclistdel' when it is no longer in use. Note that this function
- may be very slow because every key in the database is scanned. */
-TCLIST *tchdbfwmkeys2(TCHDB *hdb, const char *pstr, int max);
-
-
-/* Synchronize updated contents of a hash database object with the file and the device.
- `hdb' specifies the hash database object connected as a writer.
- If successful, the return value is true, else, it is false.
- This function is useful when another process connects the same database file. */
-bool tchdbsync(TCHDB *hdb);
-
-
-/* Optimize the file of a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the
- default value is specified. The default value is two times of the number of records.
- `apow' specifies the size of record alignment by power of 2. If it is negative, the current
- setting is not changed.
- `fpow' specifies the maximum number of elements of the free block pool by power of 2. If it
- is negative, the current setting is not changed.
- `opts' specifies options by bitwise or: `HDBTLARGE' specifies that the size of the database
- can be larger than 2GB by using 64-bit bucket array, `HDBTDEFLATE' specifies that each record
- is compressed with Deflate encoding, `HDBTTCBS' specifies that each record is compressed with
- TCBS encoding. If it is `UINT8_MAX', the current setting is not changed.
- If successful, the return value is true, else, it is false.
- This function is useful to reduce the size of the database file with data fragmentation by
- successive updating. */
-bool tchdboptimize(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts);
-
-
-/* Remove all records of a hash database object.
- `hdb' specifies the hash database object connected as a writer.
- If successful, the return value is true, else, it is false. */
-bool tchdbvanish(TCHDB *hdb);
-
-
-/* Copy the database file of a hash database object.
- `hdb' specifies the hash database object.
- `path' specifies the path of the destination file. If it begins with `@', the trailing
- substring is executed as a command line.
- If successful, the return value is true, else, it is false. False is returned if the executed
- command returns non-zero code.
- The database file is assured to be kept synchronized and not modified while the copying or
- executing operation is in progress. So, this function is useful to create a backup file of
- the database file. */
-bool tchdbcopy(TCHDB *hdb, const char *path);
-
-
-/* Get the file path of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the path of the database file or `NULL' if the object does not connect to
- any database file. */
-const char *tchdbpath(TCHDB *hdb);
-
-
-/* Get the number of records of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the number of records or 0 if the object does not connect to any database
- file. */
-uint64_t tchdbrnum(TCHDB *hdb);
-
-
-/* Get the size of the database file of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the size of the database file or 0 if the object does not connect to any
- database file. */
-uint64_t tchdbfsiz(TCHDB *hdb);
-
-
-
-/*************************************************************************************************
- * features for experts
- *************************************************************************************************/
-
-
-/* Set the error code of a hash database object.
- `hdb' specifies the hash database object.
- `ecode' specifies the error code.
- `file' specifies the file name of the code.
- `line' specifies the line number of the code.
- `func' specifies the function name of the code. */
-void tchdbsetecode(TCHDB *hdb, int ecode, const char *filename, int line, const char *func);
-
-
-/* Set the type of a hash database object.
- `hdb' specifies the hash database object.
- `type' specifies the database type. */
-void tchdbsettype(TCHDB *hdb, uint8_t type);
-
-
-/* Set the file descriptor for debugging output.
- `hdb' specifies the hash database object.
- `fd' specifies the file descriptor for debugging output. */
-void tchdbsetdbgfd(TCHDB *hdb, int fd);
-
-
-/* Get the file descriptor for debugging output.
- `hdb' specifies the hash database object.
- The return value is the file descriptor for debugging output. */
-int tchdbdbgfd(TCHDB *hdb);
-
-
-/* Synchronize updating contents on memory.
- `hdb' specifies the hash database object connected as a writer.
- `phys' specifies whether to synchronize physically.
- If successful, the return value is true, else, it is false. */
-bool tchdbmemsync(TCHDB *hdb, bool phys);
-
-
-/* Get the number of elements of the bucket array of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the number of elements of the bucket array or 0 if the object does not
- connect to any database file. */
-uint64_t tchdbbnum(TCHDB *hdb);
-
-
-/* Get the record alignment of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the record alignment or 0 if the object does not connect to any database
- file. */
-uint32_t tchdbalign(TCHDB *hdb);
-
-
-/* Get the maximum number of the free block pool of a a hash database object.
- `hdb' specifies the hash database object.
- The return value is the maximum number of the free block pool or 0 if the object does not
- connect to any database file. */
-uint32_t tchdbfbpmax(TCHDB *hdb);
-
-
-/* Get the inode number of the database file of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the inode number of the database file or 0 the object does not connect to
- any database file. */
-uint64_t tchdbinode(TCHDB *hdb);
-
-
-/* Get the modification time of the database file of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the inode number of the database file or 0 the object does not connect to
- any database file. */
-time_t tchdbmtime(TCHDB *hdb);
-
-
-/* Get the connection mode of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the connection mode. */
-int tchdbomode(TCHDB *hdb);
-
-
-/* Get the database type of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the database type. */
-uint8_t tchdbtype(TCHDB *hdb);
-
-
-/* Get the additional flags of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the additional flags. */
-uint8_t tchdbflags(TCHDB *hdb);
-
-
-/* Get the options of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the options. */
-uint8_t tchdbopts(TCHDB *hdb);
-
-
-/* Get the pointer to the opaque field of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the pointer to the opaque field whose size is 128 bytes. */
-char *tchdbopaque(TCHDB *hdb);
-
-
-/* Get the number of used elements of the bucket array of a hash database object.
- `hdb' specifies the hash database object.
- The return value is the number of used elements of the bucket array or 0 if the object does not
- connect to any database file. */
-uint64_t tchdbbnumused(TCHDB *hdb);
-
-
-
-__TCHDB_CLINKAGEEND
-#endif /* duplication check */
-
-
-/* END OF FILE */
+++ /dev/null
-/*************************************************************************************************
- * The command line utility of the hash database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include <tchdb.h>
-#include "myconf.h"
-
-
-/* global variables */
-const char *g_progname; // program name
-int g_dbgfd; // debugging output
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void printerr(TCHDB *hdb);
-static int printdata(const char *ptr, int size, bool px);
-static char *hextoobj(const char *str, int *sp);
-static char *mygetline(FILE *ifp);
-static int runcreate(int argc, char **argv);
-static int runinform(int argc, char **argv);
-static int runput(int argc, char **argv);
-static int runout(int argc, char **argv);
-static int runget(int argc, char **argv);
-static int runlist(int argc, char **argv);
-static int runoptimize(int argc, char **argv);
-static int runimporttsv(int argc, char **argv);
-static int runversion(int argc, char **argv);
-static int proccreate(const char *path, int bnum, int apow, int fpow, int opts);
-static int procinform(const char *path, int omode);
-static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- int omode, int dmode);
-static int procout(const char *path, const char *kbuf, int ksiz, int omode);
-static int procget(const char *path, const char *kbuf, int ksiz, int omode, bool px, bool pz);
-static int proclist(const char *path, int omode, int max, bool pv, bool px, const char *fmstr);
-static int procoptimize(const char *path, int bnum, int apow, int fpow, int opts, int omode);
-static int procimporttsv(const char *path, const char *file, int omode, bool sc);
-static int procversion(void);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- g_dbgfd = -1;
- const char *ebuf = getenv("TCDBGFD");
- if(ebuf) g_dbgfd = atoi(ebuf);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "create")){
- rv = runcreate(argc, argv);
- } else if(!strcmp(argv[1], "inform")){
- rv = runinform(argc, argv);
- } else if(!strcmp(argv[1], "put")){
- rv = runput(argc, argv);
- } else if(!strcmp(argv[1], "out")){
- rv = runout(argc, argv);
- } else if(!strcmp(argv[1], "get")){
- rv = runget(argc, argv);
- } else if(!strcmp(argv[1], "list")){
- rv = runlist(argc, argv);
- } else if(!strcmp(argv[1], "optimize")){
- rv = runoptimize(argc, argv);
- } else if(!strcmp(argv[1], "importtsv")){
- rv = runimporttsv(argc, argv);
- } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){
- rv = runversion(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: the command line utility of the hash database API\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s create [-tl] [-td|-tb] path [bnum [apow [fpow]]]\n", g_progname);
- fprintf(stderr, " %s inform [-nl|-nb] path\n", g_progname);
- fprintf(stderr, " %s put [-nl|-nb] [-sx] [-dk|-dc] path key value\n", g_progname);
- fprintf(stderr, " %s out [-nl|-nb] [-sx] path key\n", g_progname);
- fprintf(stderr, " %s get [-nl|-nb] [-sx] [-px] [-pz] path key\n", g_progname);
- fprintf(stderr, " %s list [-nl|-nb] [-m num] [-pv] [-px] [-fm str] path\n", g_progname);
- fprintf(stderr, " %s optimize [-tl] [-td|-tb] [-tz] [-nl|-nb] path [bnum [apow [fpow]]]\n",
- g_progname);
- fprintf(stderr, " %s importtsv [-nl|-nb] [-sc] path [file]\n", g_progname);
- fprintf(stderr, " %s version\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print error information */
-static void printerr(TCHDB *hdb){
- const char *path = tchdbpath(hdb);
- int ecode = tchdbecode(hdb);
- fprintf(stderr, "%s: %s: %d: %s\n", g_progname, path ? path : "-", ecode, tchdberrmsg(ecode));
-}
-
-
-/* print record data */
-static int printdata(const char *ptr, int size, bool px){
- int len = 0;
- while(size-- > 0){
- if(px){
- if(len > 0) putchar(' ');
- len += printf("%02X", *(unsigned char *)ptr);
- } else {
- putchar(*ptr);
- len++;
- }
- ptr++;
- }
- return len;
-}
-
-
-/* create a binary object from a hexadecimal string */
-static char *hextoobj(const char *str, int *sp){
- int len = strlen(str);
- char *buf = tcmalloc(len + 1);
- int j = 0;
- for(int i = 0; i < len; i += 2){
- while(strchr(" \n\r\t\f\v", str[i])){
- i++;
- }
- char mbuf[3];
- if((mbuf[0] = str[i]) == '\0') break;
- if((mbuf[1] = str[i+1]) == '\0') break;
- mbuf[2] = '\0';
- buf[j++] = (char)strtol(mbuf, NULL, 16);
- }
- buf[j] = '\0';
- *sp = j;
- return buf;
-}
-
-
-/* read a line from a file descriptor */
-static char *mygetline(FILE *ifp){
- char *buf;
- int c, len, blen;
- buf = NULL;
- len = 0;
- blen = 256;
- while((c = fgetc(ifp)) != EOF){
- if(blen <= len) blen *= 2;
- buf = tcrealloc(buf, blen + 1);
- if(c == '\n' || c == '\r') c = '\0';
- buf[len++] = c;
- if(c == '\0') break;
- }
- if(!buf) return NULL;
- buf[len] = '\0';
- return buf;
-}
-
-
-/* parse arguments of create command */
-static int runcreate(int argc, char **argv){
- char *path = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- int opts = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-tl")){
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= HDBTTCBS;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = proccreate(path, bnum, apow, fpow, opts);
- return rv;
-}
-
-
-/* parse arguments of inform command */
-static int runinform(int argc, char **argv){
- char *path = NULL;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = procinform(path, omode);
- return rv;
-}
-
-
-/* parse arguments of put command */
-static int runput(int argc, char **argv){
- char *path = NULL;
- char *key = NULL;
- char *value = NULL;
- int omode = 0;
- int dmode = 0;
- bool sx = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-dk")){
- dmode = -1;
- } else if(!strcmp(argv[i], "-dc")){
- dmode = 1;
- } else if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!key){
- key = argv[i];
- } else if(!value){
- value = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !key || !value) usage();
- int ksiz, vsiz;
- char *kbuf, *vbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- vbuf = hextoobj(value, &vsiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- vsiz = strlen(value);
- vbuf = tcmemdup(value, vsiz);
- }
- int rv = procput(path, kbuf, ksiz, vbuf, vsiz, omode, dmode);
- free(vbuf);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of out command */
-static int runout(int argc, char **argv){
- char *path = NULL;
- char *key = NULL;
- int omode = 0;
- bool sx = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!key){
- key = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !key) usage();
- int ksiz;
- char *kbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- }
- int rv = procout(path, kbuf, ksiz, omode);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of get command */
-static int runget(int argc, char **argv){
- char *path = NULL;
- char *key = NULL;
- int omode = 0;
- bool sx = false;
- bool px = false;
- bool pz = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-sx")){
- sx = true;
- } else if(!strcmp(argv[i], "-px")){
- px = true;
- } else if(!strcmp(argv[i], "-pz")){
- pz = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!key){
- key = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !key) usage();
- int ksiz;
- char *kbuf;
- if(sx){
- kbuf = hextoobj(key, &ksiz);
- } else {
- ksiz = strlen(key);
- kbuf = tcmemdup(key, ksiz);
- }
- int rv = procget(path, kbuf, ksiz, omode, px, pz);
- free(kbuf);
- return rv;
-}
-
-
-/* parse arguments of list command */
-static int runlist(int argc, char **argv){
- char *path = NULL;
- int omode = 0;
- int max = -1;
- bool pv = false;
- bool px = false;
- char *fmstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-m")){
- if(++i >= argc) usage();
- max = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-pv")){
- pv = true;
- } else if(!strcmp(argv[i], "-px")){
- px = true;
- } else if(!strcmp(argv[i], "-fm")){
- if(++i >= argc) usage();
- fmstr = argv[i];
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = proclist(path, omode, max, pv, px, fmstr);
- return rv;
-}
-
-
-/* parse arguments of optimize command */
-static int runoptimize(int argc, char **argv){
- char *path = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- int opts = UINT8_MAX;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-tl")){
- if(opts == UINT8_MAX) opts = 0;
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- if(opts == UINT8_MAX) opts = 0;
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- if(opts == UINT8_MAX) opts = 0;
- opts |= HDBTTCBS;
- } else if(!strcmp(argv[i], "-tz")){
- if(opts == UINT8_MAX) opts = 0;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procoptimize(path, bnum, apow, fpow, opts, omode);
- return rv;
-}
-
-
-/* parse arguments of importtsv command */
-static int runimporttsv(int argc, char **argv){
- char *path = NULL;
- char *file = NULL;
- int omode = 0;
- bool sc = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-sc")){
- sc = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!file){
- file = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = procimporttsv(path, file, omode, sc);
- return rv;
-}
-
-
-/* parse arguments of version command */
-static int runversion(int argc, char **argv){
- int rv = procversion();
- return rv;
-}
-
-
-/* perform create command */
-static int proccreate(const char *path, int bnum, int apow, int fpow, int opts){
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- bool err = false;
- if(!tchdbclose(hdb)){
- printerr(hdb);
- err = true;
- }
- tchdbdel(hdb);
- return err ? 1 : 0;
-}
-
-
-/* perform inform command */
-static int procinform(const char *path, int omode){
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbopen(hdb, path, HDBOREADER | omode)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- bool err = false;
- const char *npath = tchdbpath(hdb);
- if(!npath) npath = "(unknown)";
- printf("path: %s\n", npath);
- const char *type = "(unknown)";
- switch(tchdbtype(hdb)){
- case HDBTHASH: type = "hash"; break;
- case HDBTBTREE: type = "btree"; break;
- }
- printf("database type: %s\n", type);
- uint8_t flags = tchdbflags(hdb);
- printf("additional flags:");
- if(flags & HDBFOPEN) printf(" open");
- if(flags & HDBFFATAL) printf(" fatal");
- printf("\n");
- printf("bucket number: %llu\n", (unsigned long long)tchdbbnum(hdb));
- if(hdb->cnt_writerec >= 0)
- printf("used bucket number: %lld\n", (long long)tchdbbnumused(hdb));
- printf("alignment: %u\n", tchdbalign(hdb));
- printf("free block pool: %u\n", tchdbfbpmax(hdb));
- printf("inode number: %lld\n", (long long)tchdbinode(hdb));
- char date[48];
- tcdatestrwww(tchdbmtime(hdb), INT_MAX, date);
- printf("modified time: %s\n", date);
- uint8_t opts = tchdbopts(hdb);
- printf("options:");
- if(opts & HDBTLARGE) printf(" large");
- if(opts & HDBTDEFLATE) printf(" deflate");
- if(opts & HDBTTCBS) printf(" tcbs");
- printf("\n");
- printf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- printf("file size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- if(!tchdbclose(hdb)){
- if(!err) printerr(hdb);
- err = true;
- }
- tchdbdel(hdb);
- return err ? 1 : 0;
-}
-
-
-/* perform put command */
-static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
- int omode, int dmode){
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- bool err = false;
- switch(dmode){
- case -1:
- if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz)){
- printerr(hdb);
- err = true;
- }
- break;
- case 1:
- if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
- printerr(hdb);
- err = true;
- }
- break;
- default:
- if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
- printerr(hdb);
- err = true;
- }
- break;
- }
- if(!tchdbclose(hdb)){
- if(!err) printerr(hdb);
- err = true;
- }
- tchdbdel(hdb);
- return err ? 1 : 0;
-}
-
-
-/* perform out command */
-static int procout(const char *path, const char *kbuf, int ksiz, int omode){
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- bool err = false;
- if(!tchdbout(hdb, kbuf, ksiz)){
- printerr(hdb);
- err = true;
- }
- if(!tchdbclose(hdb)){
- if(!err) printerr(hdb);
- err = true;
- }
- tchdbdel(hdb);
- return err ? 1 : 0;
-}
-
-
-/* perform get command */
-static int procget(const char *path, const char *kbuf, int ksiz, int omode, bool px, bool pz){
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbopen(hdb, path, HDBOREADER | omode)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- bool err = false;
- int vsiz;
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(vbuf){
- printdata(vbuf, vsiz, px);
- if(!pz) putchar('\n');
- free(vbuf);
- } else {
- printerr(hdb);
- err = true;
- }
- if(!tchdbclose(hdb)){
- if(!err) printerr(hdb);
- err = true;
- }
- tchdbdel(hdb);
- return err ? 1 : 0;
-}
-
-
-/* perform list command */
-static int proclist(const char *path, int omode, int max, bool pv, bool px, const char *fmstr){
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbopen(hdb, path, HDBOREADER | omode)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- bool err = false;
- if(fmstr){
- TCLIST *keys = tchdbfwmkeys2(hdb, fmstr, max);
- for(int i = 0; i < tclistnum(keys); i++){
- int ksiz;
- const char *kbuf = tclistval(keys, i, &ksiz);
- printdata(kbuf, ksiz, px);
- if(pv){
- int vsiz;
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(vbuf){
- putchar('\t');
- printdata(vbuf, vsiz, px);
- free(vbuf);
- }
- }
- putchar('\n');
- }
- tclistdel(keys);
- } else {
- if(!tchdbiterinit(hdb)){
- printerr(hdb);
- err = true;
- }
- TCXSTR *key = tcxstrnew();
- TCXSTR *val = tcxstrnew();
- int cnt = 0;
- while(tchdbiternext3(hdb, key, val)){
- printdata(tcxstrptr(key), tcxstrsize(key), px);
- if(pv){
- putchar('\t');
- printdata(tcxstrptr(val), tcxstrsize(val), px);
- }
- putchar('\n');
- if(max >= 0 && ++cnt >= max) break;
- }
- tcxstrdel(val);
- tcxstrdel(key);
- }
- if(!tchdbclose(hdb)){
- if(!err) printerr(hdb);
- err = true;
- }
- tchdbdel(hdb);
- return err ? 1 : 0;
-}
-
-
-/* perform optimize command */
-static int procoptimize(const char *path, int bnum, int apow, int fpow, int opts, int omode){
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- bool err = false;
- if(!tchdboptimize(hdb, bnum, apow, fpow, opts)){
- printerr(hdb);
- err = true;
- }
- if(!tchdbclose(hdb)){
- if(!err) printerr(hdb);
- err = true;
- }
- tchdbdel(hdb);
- return err ? 1 : 0;
-}
-
-
-/* perform importtsv command */
-static int procimporttsv(const char *path, const char *file, int omode, bool sc){
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- FILE *ifp = file ? fopen(file, "rb") : stdin;
- if(!ifp){
- fprintf(stderr, "%s: could not open\n", file ? file : "(stdin)");
- tchdbdel(hdb);
- return 1;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | omode)){
- printerr(hdb);
- tchdbdel(hdb);
- return 1;
- }
- bool err = false;
- char *line;
- int cnt = 0;
- while(!err && (line = mygetline(ifp)) != NULL){
- char *pv = strchr(line, '\t');
- if(!pv) continue;
- *pv = '\0';
- if(sc) tcstrtolower(line);
- if(!tchdbput2(hdb, line, pv + 1) && tchdbecode(hdb) != TCEKEEP){
- printerr(hdb);
- err = true;
- }
- free(line);
- if(cnt > 0 && cnt % 100 == 0){
- putchar('.');
- fflush(stdout);
- if(cnt % 5000 == 0) printf(" (%08d)\n", cnt);
- }
- cnt++;
- }
- printf(" (%08d)\n", cnt);
- if(!tchdbclose(hdb)){
- if(!err) printerr(hdb);
- err = true;
- }
- tchdbdel(hdb);
- if(ifp != stdin) fclose(ifp);
- return err ? 1 : 0;
-}
-
-
-/* perform version command */
-static int procversion(void){
- printf("Tokyo Cabinet version %s (%d:%s)\n", tcversion, _TC_LIBVER, _TC_FORMATVER);
- printf("Copyright (C) 2006-2008 Mikio Hirabayashi\n");
- return 0;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The test cases of the hash database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include <tchdb.h>
-#include "myconf.h"
-
-#define RECBUFSIZ 32 // buffer for records
-
-typedef struct { // type of structure for write thread
- TCHDB *hdb;
- int rnum;
- bool as;
- bool rnd;
- int id;
-} TARGWRITE;
-
-typedef struct { // type of structure for read thread
- TCHDB *hdb;
- int rnum;
- bool wb;
- bool rnd;
- int id;
-} TARGREAD;
-
-typedef struct { // type of structure for remove thread
- TCHDB *hdb;
- int rnum;
- bool rnd;
- int id;
-} TARGREMOVE;
-
-typedef struct { // type of structure for wicked thread
- TCHDB *hdb;
- int rnum;
- bool nc;
- int id;
- TCMAP *map;
-} TARGWICKED;
-
-typedef struct { // type of structure for typical thread
- TCHDB *hdb;
- int rnum;
- bool nc;
- int rratio;
- int id;
-} TARGTYPICAL;
-
-
-/* global variables */
-const char *g_progname; // program name
-int g_dbgfd; // debugging output
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void iprintf(const char *format, ...);
-static void eprint(TCHDB *hdb, const char *func);
-static void mprint(TCHDB *hdb);
-static int myrand(int range);
-static int myrandnd(int range);
-static int runwrite(int argc, char **argv);
-static int runread(int argc, char **argv);
-static int runremove(int argc, char **argv);
-static int runwicked(int argc, char **argv);
-static int runtypical(int argc, char **argv);
-static int procwrite(const char *path, int tnum, int rnum, int bnum, int apow, int fpow,
- int opts, int omode, bool as, bool rnd);
-static int procread(const char *path, int tnum, int rcnum, int omode, bool wb, bool rnd);
-static int procremove(const char *path, int tnum, int omode, bool rnd);
-static int procwicked(const char *path, int tnum, int rnum, int opts, int omode, bool nc);
-static int proctypical(const char *path, int tnum, int rnum, int bnum, int apow, int fpow,
- int opts, int rcnum, int omode, bool nc, int rratio);
-static void *threadwrite(void *targ);
-static void *threadread(void *targ);
-static void *threadremove(void *targ);
-static void *threadwicked(void *targ);
-static void *threadtypical(void *targ);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- g_dbgfd = -1;
- const char *ebuf = getenv("TCDBGFD");
- if(ebuf) g_dbgfd = atoi(ebuf);
- srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "write")){
- rv = runwrite(argc, argv);
- } else if(!strcmp(argv[1], "read")){
- rv = runread(argc, argv);
- } else if(!strcmp(argv[1], "remove")){
- rv = runremove(argc, argv);
- } else if(!strcmp(argv[1], "wicked")){
- rv = runwicked(argc, argv);
- } else if(!strcmp(argv[1], "typical")){
- rv = runtypical(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: test cases of the hash database API of Tokyo Cabinet\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s write [-tl] [-td|-tb] [-nl|-nb] [-as] [-rnd] path tnum rnum"
- " [bnum [apow [fpow]]]\n", g_progname);
- fprintf(stderr, " %s read [-rc num] [-nl|-nb] [-wb] [-rnd] path tnum\n", g_progname);
- fprintf(stderr, " %s remove [-nl|-nb] [-wb] [-rnd] path tnum\n", g_progname);
- fprintf(stderr, " %s wicked [-tl] [-td|-tb] [-nl|-nb] [-nc] path tnum rnum\n",
- g_progname);
- fprintf(stderr, " %s typical [-tl] [-td|-tb] [-rc num] [-nl|-nb] [-nc] [-rr num]"
- " path tnum rnum [bnum [apow [fpow]]]\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print formatted information string and flush the buffer */
-static void iprintf(const char *format, ...){
- va_list ap;
- va_start(ap, format);
- vprintf(format, ap);
- fflush(stdout);
- va_end(ap);
-}
-
-
-/* print error message of hash database */
-static void eprint(TCHDB *hdb, const char *func){
- const char *path = tchdbpath(hdb);
- int ecode = tchdbecode(hdb);
- fprintf(stderr, "%s: %s: %s: error: %d: %s\n",
- g_progname, path ? path : "-", func, ecode, tchdberrmsg(ecode));
-}
-
-
-/* print members of hash database */
-static void mprint(TCHDB *hdb){
- if(hdb->cnt_writerec < 0) return;
- iprintf("bucket number: %lld\n", (long long)tchdbbnum(hdb));
- iprintf("used bucket number: %lld\n", (long long)tchdbbnumused(hdb));
- iprintf("cnt_writerec: %lld\n", (long long)hdb->cnt_writerec);
- iprintf("cnt_reuserec: %lld\n", (long long)hdb->cnt_reuserec);
- iprintf("cnt_moverec: %lld\n", (long long)hdb->cnt_moverec);
- iprintf("cnt_readrec: %lld\n", (long long)hdb->cnt_readrec);
- iprintf("cnt_searchfbp: %lld\n", (long long)hdb->cnt_searchfbp);
- iprintf("cnt_insertfbp: %lld\n", (long long)hdb->cnt_insertfbp);
- iprintf("cnt_splicefbp: %lld\n", (long long)hdb->cnt_splicefbp);
- iprintf("cnt_dividefbp: %lld\n", (long long)hdb->cnt_dividefbp);
- iprintf("cnt_mergefbp: %lld\n", (long long)hdb->cnt_mergefbp);
- iprintf("cnt_reducefbp: %lld\n", (long long)hdb->cnt_reducefbp);
- iprintf("cnt_appenddrp: %lld\n", (long long)hdb->cnt_appenddrp);
- iprintf("cnt_deferdrp: %lld\n", (long long)hdb->cnt_deferdrp);
- iprintf("cnt_flushdrp: %lld\n", (long long)hdb->cnt_flushdrp);
- iprintf("cnt_adjrecc: %lld\n", (long long)hdb->cnt_adjrecc);
-}
-
-
-/* get a random number */
-static int myrand(int range){
- return (int)((double)range * rand() / (RAND_MAX + 1.0));
-}
-
-
-/* get a random number based on normal distribution */
-static int myrandnd(int range){
- int num = (int)tcdrandnd(range >> 1, range / 10);
- return (num < 0 || num >= range) ? 0 : num;
-}
-
-
-/* parse arguments of write command */
-static int runwrite(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- char *rstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- int opts = 0;
- int omode = 0;
- bool as = false;
- bool rnd = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-tl")){
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= HDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-as")){
- as = true;
- } else if(!strcmp(argv[i], "-rnd")){
- rnd = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr || !rstr) usage();
- int tnum = atoi(tstr);
- int rnum = atoi(rstr);
- if(tnum < 1 || rnum < 1) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procwrite(path, tnum, rnum, bnum, apow, fpow, opts, omode, as, rnd);
- return rv;
-}
-
-
-/* parse arguments of read command */
-static int runread(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- int rcnum = 0;
- int omode = 0;
- bool wb = false;
- bool rnd = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-rc")){
- if(++i >= argc) usage();
- rcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-wb")){
- wb = true;
- } else if(!strcmp(argv[i], "-rnd")){
- rnd = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr) usage();
- int tnum = atoi(tstr);
- if(tnum < 1) usage();
- int rv = procread(path, tnum, rcnum, omode, wb, rnd);
- return rv;
-}
-
-
-/* parse arguments of remove command */
-static int runremove(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- int omode = 0;
- bool rnd = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-rnd")){
- rnd = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr) usage();
- int tnum = atoi(tstr);
- if(tnum < 1) usage();
- int rv = procremove(path, tnum, omode, rnd);
- return rv;
-}
-
-
-/* parse arguments of wicked command */
-static int runwicked(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- char *rstr = NULL;
- int opts = 0;
- int omode = 0;
- bool nc = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-tl")){
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= HDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-nc")){
- nc = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr || !rstr) usage();
- int tnum = atoi(tstr);
- int rnum = atoi(rstr);
- if(tnum < 1 || rnum < 1) usage();
- int rv = procwicked(path, tnum, rnum, opts, omode, nc);
- return rv;
-}
-
-
-/* parse arguments of typical command */
-static int runtypical(int argc, char **argv){
- char *path = NULL;
- char *tstr = NULL;
- char *rstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- int opts = 0;
- int rcnum = 0;
- int omode = 0;
- int rratio = -1;
- bool nc = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-tl")){
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= HDBTTCBS;
- } else if(!strcmp(argv[i], "-rc")){
- if(++i >= argc) usage();
- rcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-nc")){
- nc = true;
- } else if(!strcmp(argv[i], "-rr")){
- if(++i >= argc) usage();
- rratio = atoi(argv[i]);
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!tstr){
- tstr = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !tstr || !rstr) usage();
- int tnum = atoi(tstr);
- int rnum = atoi(rstr);
- if(tnum < 1 || rnum < 1) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = proctypical(path, tnum, rnum, bnum, apow, fpow, opts, rcnum, omode, nc, rratio);
- return rv;
-}
-
-
-/* perform write command */
-static int procwrite(const char *path, int tnum, int rnum, int bnum, int apow, int fpow,
- int opts, int omode, bool as, bool rnd){
- iprintf("<Writing Test>\n path=%s tnum=%d rnum=%d bnum=%d apow=%d fpow=%d"
- " opts=%d omode=%d as=%d rnd=%d\n\n",
- path, tnum, rnum, bnum, apow, fpow, opts, omode, as, rnd);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
- eprint(hdb, "tchdbtune");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- TARGWRITE targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].hdb = hdb;
- targs[0].rnum = rnum;
- targs[0].as = as;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadwrite(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].hdb = hdb;
- targs[i].rnum = rnum;
- targs[i].as = as;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadwrite, targs + i) != 0){
- eprint(hdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(hdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform read command */
-static int procread(const char *path, int tnum, int rcnum, int omode, bool wb, bool rnd){
- iprintf("<Reading Test>\n path=%s tnum=%d rcnum=%d omode=%d wb=%d rnd=%d\n\n",
- path, tnum, rcnum, omode, wb, rnd);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbsetcache(hdb, rcnum)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOREADER | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- int rnum = tchdbrnum(hdb) / tnum;
- TARGREAD targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].hdb = hdb;
- targs[0].rnum = rnum;
- targs[0].wb = wb;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadread(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].hdb = hdb;
- targs[i].rnum = rnum;
- targs[i].wb = wb;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadread, targs + i) != 0){
- eprint(hdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(hdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform remove command */
-static int procremove(const char *path, int tnum, int omode, bool rnd){
- iprintf("<Removing Test>\n path=%s tnum=%d omode=%d rnd=%d\n\n", path, tnum, omode, rnd);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- int rnum = tchdbrnum(hdb) / tnum;
- TARGREMOVE targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].hdb = hdb;
- targs[0].rnum = rnum;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadremove(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].hdb = hdb;
- targs[i].rnum = rnum;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadremove, targs + i) != 0){
- eprint(hdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(hdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform wicked command */
-static int procwicked(const char *path, int tnum, int rnum, int opts, int omode, bool nc){
- iprintf("<Writing Test>\n path=%s tnum=%d rnum=%d opts=%d omode=%d nc=%d\n\n",
- path, tnum, rnum, opts, omode, nc);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbtune(hdb, rnum / 50, 2, -1, opts)){
- eprint(hdb, "tchdbtune");
- err = true;
- }
- if(!tchdbsetcache(hdb, rnum / 2)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- if(!tchdbiterinit(hdb)){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- TARGWICKED targs[tnum];
- pthread_t threads[tnum];
- TCMAP *map = tcmapnew();
- if(tnum == 1){
- targs[0].hdb = hdb;
- targs[0].rnum = rnum;
- targs[0].nc = nc;
- targs[0].id = 0;
- targs[0].map = map;
- if(threadwicked(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].hdb = hdb;
- targs[i].rnum = rnum;
- targs[i].nc = nc;
- targs[i].id = i;
- targs[i].map = map;
- targs[i].map = map;
- if(pthread_create(threads + i, NULL, threadwicked, targs + i) != 0){
- eprint(hdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(hdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- if(!nc){
- if(!tchdbsync(hdb)){
- eprint(hdb, "tchdbsync");
- err = true;
- }
- if(tchdbrnum(hdb) != tcmaprnum(map)){
- eprint(hdb, "(validation)");
- err = true;
- }
- int end = rnum * tnum;
- for(int i = 1; i <= end && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", i - 1);
- int vsiz;
- const char *vbuf = tcmapget(map, kbuf, ksiz, &vsiz);
- int rsiz;
- char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
- if(vbuf){
- putchar('.');
- if(!rbuf){
- eprint(hdb, "tchdbget");
- err = true;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(hdb, "(validation)");
- err = true;
- }
- } else {
- putchar('*');
- if(rbuf || tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "(validation)");
- err = true;
- }
- }
- free(rbuf);
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- }
- tcmapdel(map);
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform typical command */
-static int proctypical(const char *path, int tnum, int rnum, int bnum, int apow, int fpow,
- int opts, int rcnum, int omode, bool nc, int rratio){
- iprintf("<Typical Access Test>\n path=%s tnum=%d rnum=%d bnum=%d apow=%d fpow=%d"
- " opts=%d rcnum=%d omode=%d nc=%d rratio=%d\n\n",
- path, tnum, rnum, bnum, apow, fpow, opts, rcnum, omode, nc, rratio);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(!tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
- eprint(hdb, "tchdbtune");
- err = true;
- }
- if(!tchdbsetcache(hdb, rcnum)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- TARGTYPICAL targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].hdb = hdb;
- targs[0].rnum = rnum;
- targs[0].nc = nc;
- targs[0].rratio = rratio;
- targs[0].id = 0;
- if(threadtypical(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].hdb = hdb;
- targs[i].rnum = rnum;
- targs[i].nc = nc;
- targs[i].rratio= rratio;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadtypical, targs + i) != 0){
- eprint(hdb, "pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint(hdb, "pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* thread the write function */
-static void *threadwrite(void *targ){
- TCHDB *hdb = ((TARGWRITE *)targ)->hdb;
- int rnum = ((TARGWRITE *)targ)->rnum;
- bool as = ((TARGWRITE *)targ)->as;
- bool rnd = ((TARGWRITE *)targ)->rnd;
- int id = ((TARGWRITE *)targ)->id;
- bool err = false;
- int base = id * rnum;
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", base + (rnd ? myrand(i) : i));
- if(as){
- if(!tchdbputasync(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbput");
- err = true;
- break;
- }
- } else {
- if(!tchdbput(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbput");
- err = true;
- break;
- }
- }
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- return err ? "error" : NULL;
-}
-
-
-/* thread the read function */
-static void *threadread(void *targ){
- TCHDB *hdb = ((TARGREAD *)targ)->hdb;
- int rnum = ((TARGREAD *)targ)->rnum;
- bool wb = ((TARGREAD *)targ)->wb;
- bool rnd = ((TARGREAD *)targ)->rnd;
- int id = ((TARGREAD *)targ)->id;
- bool err = false;
- int base = id * rnum;
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", base + (rnd ? myrandnd(i) : i));
- int vsiz;
- if(wb){
- char vbuf[RECBUFSIZ];
- int vsiz = tchdbget3(hdb, kbuf, ksiz, vbuf, RECBUFSIZ);
- if(vsiz < 0 && (!rnd || tchdbecode(hdb) != TCENOREC)){
- eprint(hdb, "tchdbget3");
- err = true;
- }
- } else {
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(!vbuf && (!rnd || tchdbecode(hdb) != TCENOREC)){
- eprint(hdb, "tchdbget");
- err = true;
- }
- free(vbuf);
- }
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- return err ? "error" : NULL;
-}
-
-
-/* thread the remove function */
-static void *threadremove(void *targ){
- TCHDB *hdb = ((TARGREMOVE *)targ)->hdb;
- int rnum = ((TARGREMOVE *)targ)->rnum;
- bool rnd = ((TARGREMOVE *)targ)->rnd;
- int id = ((TARGREMOVE *)targ)->id;
- bool err = false;
- int base = id * rnum;
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", base + (rnd ? myrand(i + 1) : i));
- if(!tchdbout(hdb, kbuf, ksiz) && (!rnd || tchdbecode(hdb) != TCENOREC)){
- eprint(hdb, "tchdbout");
- err = true;
- break;
- }
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- return err ? "error" : NULL;
-}
-
-
-/* thread the wicked function */
-static void *threadwicked(void *targ){
- TCHDB *hdb = ((TARGWICKED *)targ)->hdb;
- int rnum = ((TARGWICKED *)targ)->rnum;
- bool nc = ((TARGWICKED *)targ)->nc;
- int id = ((TARGWICKED *)targ)->id;
- TCMAP *map = ((TARGWICKED *)targ)->map;
- bool err = false;
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum * (id + 1)));
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '*', vsiz);
- vbuf[vsiz] = '\0';
- char *rbuf;
- if(!nc) tcglobalmutexlock();
- switch(myrand(16)){
- case 0:
- if(id == 0) putchar('0');
- if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbput");
- err = true;
- }
- if(!nc) tcmapput(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 1:
- if(id == 0) putchar('1');
- if(!tchdbput2(hdb, kbuf, vbuf)){
- eprint(hdb, "tchdbput2");
- err = true;
- }
- if(!nc) tcmapput2(map, kbuf, vbuf);
- break;
- case 2:
- if(id == 0) putchar('2');
- if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz) && tchdbecode(hdb) != TCEKEEP){
- eprint(hdb, "tchdbputkeep");
- err = true;
- }
- if(!nc) tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 3:
- if(id == 0) putchar('3');
- if(!tchdbputkeep2(hdb, kbuf, vbuf) && tchdbecode(hdb) != TCEKEEP){
- eprint(hdb, "tchdbputkeep2");
- err = true;
- }
- if(!nc) tcmapputkeep2(map, kbuf, vbuf);
- break;
- case 4:
- if(id == 0) putchar('4');
- if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputcat");
- err = true;
- }
- if(!nc) tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 5:
- if(id == 0) putchar('5');
- if(!tchdbputcat2(hdb, kbuf, vbuf)){
- eprint(hdb, "tchdbputcat2");
- err = true;
- }
- if(!nc) tcmapputcat2(map, kbuf, vbuf);
- break;
- case 6:
- if(id == 0) putchar('6');
- if(i > rnum / 4 * 3){
- if(!tchdbputasync(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputasync");
- err = true;
- }
- } else {
- if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbput");
- err = true;
- }
- }
- if(!nc) tcmapput(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 7:
- if(id == 0) putchar('7');
- if(i > rnum / 4 * 3){
- if(!tchdbputasync2(hdb, kbuf, vbuf)){
- eprint(hdb, "tchdbputasync2");
- err = true;
- }
- } else {
- if(!tchdbput2(hdb, kbuf, vbuf)){
- eprint(hdb, "tchdbput2");
- err = true;
- }
- }
- if(!nc) tcmapput2(map, kbuf, vbuf);
- break;
- case 8:
- if(id == 0) putchar('8');
- if(myrand(10) == 0){
- if(!tchdbout(hdb, kbuf, ksiz) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbout");
- err = true;
- }
- if(!nc) tcmapout(map, kbuf, ksiz);
- }
- break;
- case 9:
- if(id == 0) putchar('9');
- if(myrand(10) == 0){
- if(!tchdbout2(hdb, kbuf) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbout2");
- err = true;
- }
- if(!nc) tcmapout2(map, kbuf);
- }
- break;
- case 10:
- if(id == 0) putchar('A');
- if(!(rbuf = tchdbget(hdb, kbuf, ksiz, &vsiz))){
- if(tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget");
- err = true;
- }
- rbuf = tcsprintf("[%d]", myrand(i + 1));
- vsiz = strlen(rbuf);
- }
- vsiz += myrand(vsiz);
- if(myrand(3) == 0) vsiz += PATH_MAX;
- rbuf = tcrealloc(rbuf, vsiz + 1);
- for(int j = 0; j < vsiz; j++){
- rbuf[j] = myrand(0x100);
- }
- if(!tchdbput(hdb, kbuf, ksiz, rbuf, vsiz)){
- eprint(hdb, "tchdbput");
- err = true;
- }
- if(!nc) tcmapput(map, kbuf, ksiz, rbuf, vsiz);
- free(rbuf);
- break;
- case 11:
- if(id == 0) putchar('B');
- if(!(rbuf = tchdbget(hdb, kbuf, ksiz, &vsiz)) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget");
- err = true;
- }
- free(rbuf);
- break;
- case 12:
- if(id == 0) putchar('C');
- if(!(rbuf = tchdbget2(hdb, kbuf)) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget");
- err = true;
- }
- free(rbuf);
- break;
- case 13:
- if(id == 0) putchar('D');
- if(myrand(1) == 0) vsiz = 1;
- if((vsiz = tchdbget3(hdb, kbuf, ksiz, vbuf, vsiz)) < 0 && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget3");
- err = true;
- }
- break;
- case 14:
- if(id == 0) putchar('E');
- if(myrand(rnum / 50) == 0){
- if(!tchdbiterinit(hdb)){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- }
- TCXSTR *ikey = tcxstrnew();
- TCXSTR *ival = tcxstrnew();
- for(int j = myrand(rnum) / 1000 + 1; j >= 0; j--){
- if(j % 3 == 0){
- if(!tchdbiternext3(hdb, ikey, ival)){
- int ecode = tchdbecode(hdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(hdb, "tchdbiternext3");
- err = true;
- }
- }
- } else {
- int iksiz;
- char *ikbuf = tchdbiternext(hdb, &iksiz);
- if(ikbuf){
- free(ikbuf);
- } else {
- int ecode = tchdbecode(hdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(hdb, "tchdbiternext");
- err = true;
- }
- }
- }
- }
- tcxstrdel(ival);
- tcxstrdel(ikey);
- break;
- default:
- if(id == 0) putchar('@');
- if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- break;
- }
- if(!nc) tcglobalmutexunlock();
- if(id == 0){
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- if(id == 0 && i == rnum / 4){
- if(!tchdboptimize(hdb, rnum / 50, -1, -1, -1)){
- eprint(hdb, "tchdboptimize");
- err = true;
- }
- if(!tchdbiterinit(hdb)){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- }
- }
- }
- return err ? "error" : NULL;
-}
-
-
-/* thread the typical function */
-static void *threadtypical(void *targ){
- TCHDB *hdb = ((TARGTYPICAL *)targ)->hdb;
- int rnum = ((TARGTYPICAL *)targ)->rnum;
- bool nc = ((TARGTYPICAL *)targ)->nc;
- int rratio = ((TARGTYPICAL *)targ)->rratio;
- int id = ((TARGTYPICAL *)targ)->id;
- bool err = false;
- TCMAP *map = (!nc && id == 0) ? tcmapnew2(rnum + 1) : NULL;
- int base = id * rnum;
- int mrange = tclmax(50 + rratio, 100);
- for(int i = 1; !err && i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", base + myrandnd(i));
- int rnd = myrand(mrange);
- if(rnd < 10){
- if(!tchdbput(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbput");
- err = true;
- }
- if(map) tcmapput(map, buf, len, buf, len);
- } else if(rnd < 15){
- if(!tchdbputkeep(hdb, buf, len, buf, len) && tchdbecode(hdb) != TCEKEEP){
- eprint(hdb, "tchdbputkeep");
- err = true;
- }
- if(map) tcmapputkeep(map, buf, len, buf, len);
- } else if(rnd < 20){
- if(!tchdbputcat(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbputcat");
- err = true;
- }
- if(map) tcmapputcat(map, buf, len, buf, len);
- } else if(rnd < 25){
- if(i > rnum / 10 * 9){
- if(!tchdbputasync(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbputasync");
- err = true;
- }
- } else {
- if(!tchdbput(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbput");
- err = true;
- }
- }
- if(map) tcmapput(map, buf, len, buf, len);
- } else if(rnd < 30){
- if(!tchdbout(hdb, buf, len) && tchdbecode(hdb) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbout");
- err = true;
- }
- if(map) tcmapout(map, buf, len);
- } else if(rnd < 31){
- if(myrand(10) == 0 && !tchdbiterinit(hdb) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- for(int j = 0; !err && j < 10; j++){
- int ksiz;
- char *kbuf = tchdbiternext(hdb, &ksiz);
- if(kbuf){
- free(kbuf);
- } else if(tchdbecode(hdb) != TCEINVALID && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbiternext");
- err = true;
- }
- }
- } else {
- int vsiz;
- char *vbuf = tchdbget(hdb, buf, len, &vsiz);
- if(vbuf){
- if(map){
- int msiz;
- const char *mbuf = tcmapget(map, buf, len, &msiz);
- if(msiz != vsiz || memcmp(mbuf, vbuf, vsiz)){
- eprint(hdb, "(validation)");
- err = true;
- }
- }
- free(vbuf);
- } else {
- if(tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget");
- err = true;
- }
- if(map && tcmapget(map, buf, len, &vsiz)){
- eprint(hdb, "(validation)");
- err = true;
- }
- }
- }
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(map){
- tcmapiterinit(map);
- int ksiz;
- const char *kbuf;
- while(!err && (kbuf = tcmapiternext(map, &ksiz)) != NULL){
- int vsiz;
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(vbuf){
- int msiz;
- const char *mbuf = tcmapget(map, kbuf, ksiz, &msiz);
- if(!mbuf || msiz != vsiz || memcmp(mbuf, vbuf, vsiz)){
- eprint(hdb, "(validation)");
- err = true;
- }
- free(vbuf);
- } else {
- eprint(hdb, "(validation)");
- err = true;
- }
- }
- tcmapdel(map);
- }
- return err ? "error" : NULL;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The test cases of the hash database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include <tchdb.h>
-#include "myconf.h"
-
-#define RECBUFSIZ 32 // buffer for records
-
-
-/* global variables */
-const char *g_progname; // program name
-int g_dbgfd; // debugging output
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void iprintf(const char *format, ...);
-static void eprint(TCHDB *hdb, const char *func);
-static void mprint(TCHDB *hdb);
-static int myrand(int range);
-static int runwrite(int argc, char **argv);
-static int runread(int argc, char **argv);
-static int runremove(int argc, char **argv);
-static int runrcat(int argc, char **argv);
-static int runmisc(int argc, char **argv);
-static int runwicked(int argc, char **argv);
-static int procwrite(const char *path, int rnum, int bnum, int apow, int fpow,
- bool mt, int opts, int rcnum, int omode, bool as);
-static int procread(const char *path, bool mt, int rcnum, int omode, bool wb);
-static int procremove(const char *path, bool mt, int rcnum, int omode);
-static int procrcat(const char *path, int rnum, int bnum, int apow, int fpow,
- bool mt, int opts, int rcnum, int omode, int pnum, bool rl);
-static int procmisc(const char *path, int rnum, bool mt, int opts, int omode);
-static int procwicked(const char *path, int rnum, bool mt, int opts, int omode);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- g_dbgfd = -1;
- const char *ebuf = getenv("TCDBGFD");
- if(ebuf) g_dbgfd = atoi(ebuf);
- srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "write")){
- rv = runwrite(argc, argv);
- } else if(!strcmp(argv[1], "read")){
- rv = runread(argc, argv);
- } else if(!strcmp(argv[1], "remove")){
- rv = runremove(argc, argv);
- } else if(!strcmp(argv[1], "rcat")){
- rv = runrcat(argc, argv);
- } else if(!strcmp(argv[1], "misc")){
- rv = runmisc(argc, argv);
- } else if(!strcmp(argv[1], "wicked")){
- rv = runwicked(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: test cases of the hash database API of Tokyo Cabinet\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s write [-mt] [-tl] [-td|-tb] [-rc num] [-nl|-nb] [-as] path rnum"
- " [bnum [apow [fpow]]]\n", g_progname);
- fprintf(stderr, " %s read [-mt] [-rc num] [-nl|-nb] [-wb] path\n", g_progname);
- fprintf(stderr, " %s remove [-mt] [-rc num] [-nl|-nb] path\n", g_progname);
- fprintf(stderr, " %s rcat [-mt] [-rc num] [-tl] [-td|-tb] [-nl|-nb] [-pn num] [-rl]"
- " path rnum [bnum [apow [fpow]]]\n", g_progname);
- fprintf(stderr, " %s misc [-mt] [-tl] [-td|-tb] [-nl|-nb] path rnum\n", g_progname);
- fprintf(stderr, " %s wicked [-mt] [-tl] [-td|-tb] [-nl|-nb] path rnum\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print formatted information string and flush the buffer */
-static void iprintf(const char *format, ...){
- va_list ap;
- va_start(ap, format);
- vprintf(format, ap);
- fflush(stdout);
- va_end(ap);
-}
-
-
-/* print error message of hash database */
-static void eprint(TCHDB *hdb, const char *func){
- const char *path = tchdbpath(hdb);
- int ecode = tchdbecode(hdb);
- fprintf(stderr, "%s: %s: %s: error: %d: %s\n",
- g_progname, path ? path : "-", func, ecode, tchdberrmsg(ecode));
-}
-
-
-/* print members of hash database */
-static void mprint(TCHDB *hdb){
- if(hdb->cnt_writerec < 0) return;
- iprintf("bucket number: %lld\n", (long long)tchdbbnum(hdb));
- iprintf("used bucket number: %lld\n", (long long)tchdbbnumused(hdb));
- iprintf("cnt_writerec: %lld\n", (long long)hdb->cnt_writerec);
- iprintf("cnt_reuserec: %lld\n", (long long)hdb->cnt_reuserec);
- iprintf("cnt_moverec: %lld\n", (long long)hdb->cnt_moverec);
- iprintf("cnt_readrec: %lld\n", (long long)hdb->cnt_readrec);
- iprintf("cnt_searchfbp: %lld\n", (long long)hdb->cnt_searchfbp);
- iprintf("cnt_insertfbp: %lld\n", (long long)hdb->cnt_insertfbp);
- iprintf("cnt_splicefbp: %lld\n", (long long)hdb->cnt_splicefbp);
- iprintf("cnt_dividefbp: %lld\n", (long long)hdb->cnt_dividefbp);
- iprintf("cnt_mergefbp: %lld\n", (long long)hdb->cnt_mergefbp);
- iprintf("cnt_reducefbp: %lld\n", (long long)hdb->cnt_reducefbp);
- iprintf("cnt_appenddrp: %lld\n", (long long)hdb->cnt_appenddrp);
- iprintf("cnt_deferdrp: %lld\n", (long long)hdb->cnt_deferdrp);
- iprintf("cnt_flushdrp: %lld\n", (long long)hdb->cnt_flushdrp);
- iprintf("cnt_adjrecc: %lld\n", (long long)hdb->cnt_adjrecc);
-}
-
-
-/* get a random number */
-static int myrand(int range){
- return (int)((double)range * rand() / (RAND_MAX + 1.0));
-}
-
-
-/* parse arguments of write command */
-static int runwrite(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- bool mt = false;
- int opts = 0;
- int rcnum = 0;
- int omode = 0;
- bool as = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= HDBTTCBS;
- } else if(!strcmp(argv[i], "-rc")){
- if(++i >= argc) usage();
- rcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-as")){
- as = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procwrite(path, rnum, bnum, apow, fpow, mt, opts, rcnum, omode, as);
- return rv;
-}
-
-
-/* parse arguments of read command */
-static int runread(int argc, char **argv){
- char *path = NULL;
- bool mt = false;
- int rcnum = 0;
- int omode = 0;
- bool wb = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-rc")){
- if(++i >= argc) usage();
- rcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-wb")){
- wb = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = procread(path, mt, rcnum, omode, wb);
- return rv;
-}
-
-
-/* parse arguments of remove command */
-static int runremove(int argc, char **argv){
- char *path = NULL;
- bool mt = false;
- int rcnum = 0;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-rc")){
- if(++i >= argc) usage();
- rcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- if(!path) usage();
- int rv = procremove(path, mt, rcnum, omode);
- return rv;
-}
-
-
-/* parse arguments of rcat command */
-static int runrcat(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- char *bstr = NULL;
- char *astr = NULL;
- char *fstr = NULL;
- bool mt = false;
- int opts = 0;
- int rcnum = 0;
- int omode = 0;
- int pnum = 0;
- bool rl = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= HDBTTCBS;
- } else if(!strcmp(argv[i], "-rc")){
- if(++i >= argc) usage();
- rcnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else if(!strcmp(argv[i], "-pn")){
- if(++i >= argc) usage();
- pnum = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-rl")){
- rl = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else if(!fstr){
- fstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int apow = astr ? atoi(astr) : -1;
- int fpow = fstr ? atoi(fstr) : -1;
- int rv = procrcat(path, rnum, bnum, apow, fpow, mt, opts, rcnum, omode, pnum, rl);
- return rv;
-}
-
-
-/* parse arguments of misc command */
-static int runmisc(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- bool mt = false;
- int opts = 0;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= HDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procmisc(path, rnum, mt, opts, omode);
- return rv;
-}
-
-
-/* parse arguments of wicked command */
-static int runwicked(int argc, char **argv){
- char *path = NULL;
- char *rstr = NULL;
- bool mt = false;
- int opts = 0;
- int omode = 0;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-mt")){
- mt = true;
- } else if(!strcmp(argv[i], "-tl")){
- opts |= HDBTLARGE;
- } else if(!strcmp(argv[i], "-td")){
- opts |= HDBTDEFLATE;
- } else if(!strcmp(argv[i], "-tb")){
- opts |= HDBTTCBS;
- } else if(!strcmp(argv[i], "-nl")){
- omode |= HDBONOLCK;
- } else if(!strcmp(argv[i], "-nb")){
- omode |= HDBOLCKNB;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!path || !rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procwicked(path, rnum, mt, opts, omode);
- return rv;
-}
-
-
-/* perform write command */
-static int procwrite(const char *path, int rnum, int bnum, int apow, int fpow,
- bool mt, int opts, int rcnum, int omode, bool as){
- iprintf("<Writing Test>\n path=%s rnum=%d bnum=%d apow=%d fpow=%d mt=%d"
- " opts=%d rcnum=%d omode=%d as=%d\n\n",
- path, rnum, bnum, apow, fpow, mt, opts, rcnum, omode, as);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(mt && !tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
- eprint(hdb, "tchdbtune");
- err = true;
- }
- if(!tchdbsetcache(hdb, rcnum)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- if(as){
- if(!tchdbputasync(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbput");
- err = true;
- break;
- }
- } else {
- if(!tchdbput(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbput");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform read command */
-static int procread(const char *path, bool mt, int rcnum, int omode, bool wb){
- iprintf("<Reading Test>\n path=%s mt=%d rcnum=%d omode=%d wb=%d\n",
- path, mt, rcnum, omode, wb);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(mt && !tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbsetcache(hdb, rcnum)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOREADER | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- int rnum = tchdbrnum(hdb);
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- int vsiz;
- if(wb){
- char vbuf[RECBUFSIZ];
- int vsiz = tchdbget3(hdb, kbuf, ksiz, vbuf, RECBUFSIZ);
- if(vsiz < 0){
- eprint(hdb, "tchdbget3");
- err = true;
- break;
- }
- } else {
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(hdb, "tchdbget");
- err = true;
- break;
- }
- free(vbuf);
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform remove command */
-static int procremove(const char *path, bool mt, int rcnum, int omode){
- iprintf("<Removing Test>\n path=%s mt=%d rcnum=%d omode=%d\n", path, mt, rcnum, omode);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(mt && !tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbsetcache(hdb, rcnum)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- int rnum = tchdbrnum(hdb);
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- if(!tchdbout(hdb, kbuf, ksiz)){
- eprint(hdb, "tchdbout");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform rcat command */
-static int procrcat(const char *path, int rnum, int bnum, int apow, int fpow,
- bool mt, int opts, int rcnum, int omode, int pnum, bool rl){
- iprintf("<Random Concatenating Test>\n"
- " path=%s rnum=%d bnum=%d apow=%d fpow=%d mt=%d opts=%d rcnum=%d"
- " omode=%d pnum=%d rl=%d\n\n",
- path, rnum, bnum, apow, fpow, mt, opts, rcnum, omode, pnum, rl);
- if(pnum < 1) pnum = rnum;
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(mt && !tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
- eprint(hdb, "tchdbtune");
- err = true;
- }
- if(!tchdbsetcache(hdb, rcnum)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(pnum));
- if(rl){
- char vbuf[PATH_MAX];
- int vsiz = myrand(PATH_MAX);
- for(int j = 0; j < vsiz; j++){
- vbuf[j] = myrand(0x100);
- }
- if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputcat");
- err = true;
- break;
- }
- } else {
- if(!tchdbputcat(hdb, kbuf, ksiz, kbuf, ksiz)){
- eprint(hdb, "tchdbputcat");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform misc command */
-static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
- iprintf("<Miscellaneous Test>\n path=%s rnum=%d mt=%d opts=%d omode=%d\n\n",
- path, rnum, mt, opts, omode);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(mt && !tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbtune(hdb, rnum / 50, 2, -1, opts)){
- eprint(hdb, "tchdbtune");
- err = true;
- }
- if(!tchdbsetcache(hdb, rnum / 10)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- iprintf("writing:\n");
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- if(i % 3 == 0){
- if(!tchdbputkeep(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbputkeep");
- err = true;
- break;
- }
- } else {
- if(!tchdbputasync(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbputasync");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("reading:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- int vsiz;
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(hdb, "tchdbget");
- err = true;
- break;
- } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
- eprint(hdb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- free(vbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(tchdbrnum(hdb) != rnum){
- eprint(hdb, "(validation)");
- err = true;
- }
- iprintf("random writing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '*', vsiz);
- if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbput");
- err = true;
- break;
- }
- int rsiz;
- char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
- if(!rbuf){
- eprint(hdb, "tchdbget");
- err = true;
- break;
- }
- if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(hdb, "(validation)");
- err = true;
- free(rbuf);
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- free(rbuf);
- }
- iprintf("word writing:\n");
- const char *words[] = {
- "a", "A", "bb", "BB", "ccc", "CCC", "dddd", "DDDD", "eeeee", "EEEEEE",
- "mikio", "hirabayashi", "tokyo", "cabinet", "hyper", "estraier", "19780211", "birth day",
- "one", "first", "two", "second", "three", "third", "four", "fourth", "five", "fifth",
- "_[1]_", "uno", "_[2]_", "dos", "_[3]_", "tres", "_[4]_", "cuatro", "_[5]_", "cinco",
- "[\xe5\xb9\xb3\xe6\x9e\x97\xe5\xb9\xb9\xe9\x9b\x84]", "[\xe9\xa6\xac\xe9\xb9\xbf]", NULL
- };
- for(int i = 0; words[i] != NULL; i += 2){
- const char *kbuf = words[i];
- int ksiz = strlen(kbuf);
- const char *vbuf = words[i+1];
- int vsiz = strlen(vbuf);
- if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputkeep");
- err = true;
- break;
- }
- if(rnum > 250) putchar('.');
- }
- if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
- iprintf("random erasing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- if(!tchdbout(hdb, kbuf, ksiz) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbout");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("writing:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "[%d]", i);
- char vbuf[RECBUFSIZ];
- int vsiz = i % RECBUFSIZ;
- memset(vbuf, '*', vsiz);
- if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputkeep");
- err = true;
- break;
- }
- if(vsiz < 1){
- char tbuf[PATH_MAX];
- for(int j = 0; j < PATH_MAX; j++){
- tbuf[j] = myrand(0x100);
- }
- if(!tchdbput(hdb, kbuf, ksiz, tbuf, PATH_MAX)){
- eprint(hdb, "tchdbput");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("erasing:\n");
- for(int i = 1; i <= rnum; i++){
- if(i % 2 == 1){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "[%d]", i);
- if(!tchdbout(hdb, kbuf, ksiz)){
- eprint(hdb, "tchdbout");
- err = true;
- break;
- }
- if(tchdbout(hdb, kbuf, ksiz) || tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbout");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("random writing and reopening:\n");
- for(int i = 1; i <= rnum; i++){
- if(myrand(10) == 0){
- int ksiz, vsiz;
- char *kbuf, *vbuf;
- ksiz = (myrand(5) == 0) ? myrand(UINT16_MAX) : myrand(RECBUFSIZ);
- kbuf = tcmalloc(ksiz + 1);
- memset(kbuf, '@', ksiz);
- vsiz = (myrand(5) == 0) ? myrand(UINT16_MAX) : myrand(RECBUFSIZ);
- vbuf = tcmalloc(vsiz + 1);
- for(int j = 0; j < vsiz; j++){
- vbuf[j] = myrand(256);
- }
- switch(myrand(4)){
- case 0:
- if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbput");
- err = true;
- }
- break;
- case 1:
- if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputcat");
- err = true;
- }
- break;
- case 2:
- if(!tchdbputasync(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputasync");
- err = true;
- }
- break;
- case 3:
- if(!tchdbout(hdb, kbuf, ksiz) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbout");
- err = true;
- }
- break;
- }
- free(vbuf);
- free(kbuf);
- } else {
- char kbuf[RECBUFSIZ];
- int ksiz = myrand(RECBUFSIZ);
- memset(kbuf, '@', ksiz);
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '@', vsiz);
- if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputcat");
- err = true;
- break;
- }
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- iprintf("checking:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "[%d]", i);
- int vsiz;
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(i % 2 == 0){
- if(!vbuf){
- eprint(hdb, "tchdbget");
- err = true;
- break;
- }
- if(vsiz != i % RECBUFSIZ && vsiz != PATH_MAX){
- eprint(hdb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- } else {
- if(vbuf || tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- }
- free(vbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("writing:\n");
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- if(!tchdbput(hdb, buf, len, buf, len)){
- eprint(hdb, "tchdbput");
- err = true;
- break;
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("reading:\n");
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", i);
- int vsiz;
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(hdb, "tchdbget");
- err = true;
- break;
- } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
- eprint(hdb, "(validation)");
- err = true;
- free(vbuf);
- break;
- }
- free(vbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("word checking:\n");
- for(int i = 0; words[i] != NULL; i += 2){
- const char *kbuf = words[i];
- int ksiz = strlen(kbuf);
- const char *vbuf = words[i+1];
- int vsiz = strlen(vbuf);
- int rsiz;
- char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
- if(!rbuf){
- eprint(hdb, "tchdbget");
- err = true;
- break;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(hdb, "(validation)");
- err = true;
- free(rbuf);
- break;
- }
- free(rbuf);
- if(rnum > 250) putchar('.');
- }
- if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
- iprintf("iterator checking:\n");
- if(!tchdbiterinit(hdb)){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- char *kbuf;
- int ksiz;
- int inum = 0;
- for(int i = 1; (kbuf = tchdbiternext(hdb, &ksiz)) != NULL; i++, inum++){
- int vsiz;
- char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
- if(!vbuf){
- eprint(hdb, "tchdbget");
- err = true;
- free(kbuf);
- break;
- }
- free(vbuf);
- free(kbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(rnum > 250) iprintf(" (%08d)\n", inum);
- if(tchdbecode(hdb) != TCENOREC || inum != tchdbrnum(hdb)){
- eprint(hdb, "(validation)");
- err = true;
- }
- iprintf("iteration updating:\n");
- if(!tchdbiterinit(hdb)){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- inum = 0;
- for(int i = 1; (kbuf = tchdbiternext(hdb, &ksiz)) != NULL; i++, inum++){
- if(myrand(2) == 0){
- if(!tchdbputcat(hdb, kbuf, ksiz, "0123456789", 10)){
- eprint(hdb, "tchdbputcat");
- err = true;
- free(kbuf);
- break;
- }
- } else {
- if(!tchdbout(hdb, kbuf, ksiz)){
- eprint(hdb, "tchdbout");
- err = true;
- free(kbuf);
- break;
- }
- }
- free(kbuf);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(rnum > 250) iprintf(" (%08d)\n", inum);
- if(tchdbecode(hdb) != TCENOREC || inum < tchdbrnum(hdb)){
- eprint(hdb, "(validation)");
- err = true;
- }
- if(!tchdbsync(hdb)){
- eprint(hdb, "tchdbsync");
- err = true;
- }
- if(!tchdbvanish(hdb)){
- eprint(hdb, "tchdbvanish");
- err = true;
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform wicked command */
-static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
- iprintf("<Wicked Writing Test>\n path=%s rnum=%d mt=%d opts=%d omode=%d\n\n",
- path, rnum, mt, opts, omode);
- bool err = false;
- double stime = tctime();
- TCHDB *hdb = tchdbnew();
- if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
- if(mt && !tchdbsetmutex(hdb)){
- eprint(hdb, "tchdbsetmutex");
- err = true;
- }
- if(!tchdbtune(hdb, rnum / 50, 2, -1, opts)){
- eprint(hdb, "tchdbtune");
- err = true;
- }
- if(!tchdbsetcache(hdb, rnum / 10)){
- eprint(hdb, "tchdbsetcache");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- if(!tchdbiterinit(hdb)){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- TCMAP *map = tcmapnew2(rnum / 5);
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(rnum));
- char vbuf[RECBUFSIZ];
- int vsiz = myrand(RECBUFSIZ);
- memset(vbuf, '*', vsiz);
- vbuf[vsiz] = '\0';
- char *rbuf;
- switch(myrand(16)){
- case 0:
- putchar('0');
- if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbput");
- err = true;
- }
- tcmapput(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 1:
- putchar('1');
- if(!tchdbput2(hdb, kbuf, vbuf)){
- eprint(hdb, "tchdbput2");
- err = true;
- }
- tcmapput2(map, kbuf, vbuf);
- break;
- case 2:
- putchar('2');
- if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz) && tchdbecode(hdb) != TCEKEEP){
- eprint(hdb, "tchdbputkeep");
- err = true;
- }
- tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 3:
- putchar('3');
- if(!tchdbputkeep2(hdb, kbuf, vbuf) && tchdbecode(hdb) != TCEKEEP){
- eprint(hdb, "tchdbputkeep2");
- err = true;
- }
- tcmapputkeep2(map, kbuf, vbuf);
- break;
- case 4:
- putchar('4');
- if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputcat");
- err = true;
- }
- tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 5:
- putchar('5');
- if(!tchdbputcat2(hdb, kbuf, vbuf)){
- eprint(hdb, "tchdbputcat2");
- err = true;
- }
- tcmapputcat2(map, kbuf, vbuf);
- break;
- case 6:
- putchar('6');
- if(!tchdbputasync(hdb, kbuf, ksiz, vbuf, vsiz)){
- eprint(hdb, "tchdbputasync");
- err = true;
- }
- tcmapput(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 7:
- putchar('7');
- if(!tchdbputasync2(hdb, kbuf, vbuf)){
- eprint(hdb, "tchdbputasync2");
- err = true;
- }
- tcmapput2(map, kbuf, vbuf);
- break;
- case 8:
- putchar('8');
- if(myrand(10) == 0){
- if(!tchdbout(hdb, kbuf, ksiz) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbout");
- err = true;
- }
- tcmapout(map, kbuf, ksiz);
- }
- break;
- case 9:
- putchar('9');
- if(myrand(10) == 0){
- if(!tchdbout2(hdb, kbuf) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbout2");
- err = true;
- }
- tcmapout2(map, kbuf);
- }
- break;
- case 10:
- putchar('A');
- if(!(rbuf = tchdbget(hdb, kbuf, ksiz, &vsiz))){
- if(tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget");
- err = true;
- }
- rbuf = tcsprintf("[%d]", myrand(i + 1));
- vsiz = strlen(rbuf);
- }
- vsiz += myrand(vsiz);
- if(myrand(3) == 0) vsiz += PATH_MAX;
- rbuf = tcrealloc(rbuf, vsiz + 1);
- for(int j = 0; j < vsiz; j++){
- rbuf[j] = myrand(0x100);
- }
- if(!tchdbput(hdb, kbuf, ksiz, rbuf, vsiz)){
- eprint(hdb, "tchdbput");
- err = true;
- }
- tcmapput(map, kbuf, ksiz, rbuf, vsiz);
- free(rbuf);
- break;
- case 11:
- putchar('B');
- if(!(rbuf = tchdbget(hdb, kbuf, ksiz, &vsiz)) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget");
- err = true;
- }
- free(rbuf);
- break;
- case 12:
- putchar('C');
- if(!(rbuf = tchdbget2(hdb, kbuf)) && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget");
- err = true;
- }
- free(rbuf);
- break;
- case 13:
- putchar('D');
- if(myrand(1) == 0) vsiz = 1;
- if((vsiz = tchdbget3(hdb, kbuf, ksiz, vbuf, vsiz)) < 0 && tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tchdbget");
- err = true;
- }
- break;
- case 14:
- putchar('E');
- if(myrand(rnum / 50) == 0){
- if(!tchdbiterinit(hdb)){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- }
- TCXSTR *ikey = tcxstrnew();
- TCXSTR *ival = tcxstrnew();
- for(int j = myrand(rnum) / 1000 + 1; j >= 0; j--){
- if(j % 3 == 0){
- if(tchdbiternext3(hdb, ikey, ival)){
- if(tcxstrsize(ival) != tchdbvsiz(hdb, tcxstrptr(ikey), tcxstrsize(ikey))){
- eprint(hdb, "(validation)");
- err = true;
- }
- } else {
- int ecode = tchdbecode(hdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(hdb, "tchdbiternext3");
- err = true;
- }
- }
- } else {
- int iksiz;
- char *ikbuf = tchdbiternext(hdb, &iksiz);
- if(ikbuf){
- free(ikbuf);
- } else {
- int ecode = tchdbecode(hdb);
- if(ecode != TCEINVALID && ecode != TCENOREC){
- eprint(hdb, "tchdbiternext");
- err = true;
- }
- }
- }
- }
- tcxstrdel(ival);
- tcxstrdel(ikey);
- break;
- default:
- putchar('@');
- if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(myrand(rnum / 16 + 1) == 0){
- int cnt = myrand(30);
- for(int j = 0; j < rnum && !err; j++){
- ksiz = sprintf(kbuf, "%d", i + j);
- if(tchdbout(hdb, kbuf, ksiz)){
- cnt--;
- } else if(tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "tcbdbout");
- err = true;
- }
- tcmapout(map, kbuf, ksiz);
- if(cnt < 0) break;
- }
- }
- break;
- }
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- if(i == rnum / 2){
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
- eprint(hdb, "tchdbopen");
- err = true;
- }
- } else if(i == rnum / 4){
- char *npath = tcsprintf("%s-tmp", path);
- if(!tchdbcopy(hdb, npath)){
- eprint(hdb, "tchdbcopy");
- err = true;
- }
- TCHDB *nhdb = tchdbnew();
- if(!tchdbopen(nhdb, npath, HDBOREADER | omode)){
- eprint(nhdb, "tchdbopen");
- err = true;
- }
- tchdbdel(nhdb);
- unlink(npath);
- free(npath);
- if(!tchdboptimize(hdb, rnum / 50, -1, -1, -1)){
- eprint(hdb, "tchdboptimize");
- err = true;
- }
- if(!tchdbiterinit(hdb)){
- eprint(hdb, "tchdbiterinit");
- err = true;
- }
- }
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- if(!tchdbsync(hdb)){
- eprint(hdb, "tchdbsync");
- err = true;
- }
- if(tchdbrnum(hdb) != tcmaprnum(map)){
- eprint(hdb, "(validation)");
- err = true;
- }
- for(int i = 1; i <= rnum && !err; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", i - 1);
- int vsiz;
- const char *vbuf = tcmapget(map, kbuf, ksiz, &vsiz);
- int rsiz;
- char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
- if(vbuf){
- putchar('.');
- if(!rbuf){
- eprint(hdb, "tchdbget");
- err = true;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(hdb, "(validation)");
- err = true;
- }
- } else {
- putchar('*');
- if(rbuf || tchdbecode(hdb) != TCENOREC){
- eprint(hdb, "(validation)");
- err = true;
- }
- }
- free(rbuf);
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- tcmapiterinit(map);
- int ksiz;
- const char *kbuf;
- for(int i = 1; (kbuf = tcmapiternext(map, &ksiz)) != NULL; i++){
- putchar('+');
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- int rsiz;
- char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
- if(!rbuf){
- eprint(hdb, "tchdbget");
- err = true;
- } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
- eprint(hdb, "(validation)");
- err = true;
- }
- free(rbuf);
- if(!tchdbout(hdb, kbuf, ksiz)){
- eprint(hdb, "tchdbout");
- err = true;
- }
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- int mrnum = tcmaprnum(map);
- if(mrnum % 50 > 0) iprintf(" (%08d)\n", mrnum);
- if(tchdbrnum(hdb) != 0){
- eprint(hdb, "(validation)");
- err = true;
- }
- iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
- iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
- mprint(hdb);
- tcmapdel(map);
- if(!tchdbclose(hdb)){
- eprint(hdb, "tchdbclose");
- err = true;
- }
- tchdbdel(hdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * Popular encoders and decoders of the utility API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include "myconf.h"
-
-
-/* global variables */
-const char *g_progname; // program name
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void eprintf(const char *format, ...);
-static int runurl(int argc, char **argv);
-static int runbase(int argc, char **argv);
-static int runquote(int argc, char **argv);
-static int runmime(int argc, char **argv);
-static int runpack(int argc, char **argv);
-static int runtcbs(int argc, char **argv);
-static int runzlib(int argc, char **argv);
-static int runxml(int argc, char **argv);
-static int runucs(int argc, char **argv);
-static int rundate(int argc, char **argv);
-static int runconf(int argc, char **argv);
-static int procurl(const char *ibuf, int isiz, bool dec, bool br, const char *base);
-static int procbase(const char *ibuf, int isiz, bool dec);
-static int procquote(const char *ibuf, int isiz, bool dec);
-static int procmime(const char *ibuf, int isiz, bool dec, const char *ename, bool qb, bool on);
-static int procpack(const char *ibuf, int isiz, bool dec, bool bwt);
-static int proctcbs(const char *ibuf, int isiz, bool dec);
-static int proczlib(const char *ibuf, int isiz, bool dec, bool gz);
-static int procxml(const char *ibuf, int isiz, bool dec, bool br);
-static int procucs(const char *ibuf, int isiz, bool dec);
-static int procdate(const char *str, int jl, bool wf, bool rf);
-static int procconf(int mode);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "url")){
- rv = runurl(argc, argv);
- } else if(!strcmp(argv[1], "base")){
- rv = runbase(argc, argv);
- } else if(!strcmp(argv[1], "quote")){
- rv = runquote(argc, argv);
- } else if(!strcmp(argv[1], "mime")){
- rv = runmime(argc, argv);
- } else if(!strcmp(argv[1], "pack")){
- rv = runpack(argc, argv);
- } else if(!strcmp(argv[1], "tcbs")){
- rv = runtcbs(argc, argv);
- } else if(!strcmp(argv[1], "zlib")){
- rv = runzlib(argc, argv);
- } else if(!strcmp(argv[1], "xml")){
- rv = runxml(argc, argv);
- } else if(!strcmp(argv[1], "ucs")){
- rv = runucs(argc, argv);
- } else if(!strcmp(argv[1], "date")){
- rv = rundate(argc, argv);
- } else if(!strcmp(argv[1], "conf")){
- rv = runconf(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: popular encoders and decoders of Tokyo Cabinet\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s url [-d] [-br] [-rs base] [file]\n", g_progname);
- fprintf(stderr, " %s base [-d] [file]\n", g_progname);
- fprintf(stderr, " %s quote [-d] [file]\n", g_progname);
- fprintf(stderr, " %s mime [-d] [-en name] [-q] [file]\n", g_progname);
- fprintf(stderr, " %s pack [-d] [-bwt] [file]\n", g_progname);
- fprintf(stderr, " %s tcbs [-d] [file]\n", g_progname);
- fprintf(stderr, " %s zlib [-d] [-gz] [file]\n", g_progname);
- fprintf(stderr, " %s xml [-d] [-br] [file]\n", g_progname);
- fprintf(stderr, " %s ucs [-d] [file]\n", g_progname);
- fprintf(stderr, " %s date [-ds str] [-jl num] [-wf] [-rf]\n", g_progname);
- fprintf(stderr, " %s conf [-v|-i|-l|-p]\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print formatted error string */
-static void eprintf(const char *format, ...){
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "%s: ", g_progname);
- vfprintf(stderr, format, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-
-/* parse arguments of url command */
-static int runurl(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- bool br = false;
- char *base = NULL;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else if(!strcmp(argv[i], "-br")){
- br = true;
- } else if(!strcmp(argv[i], "-rs")){
- if(++i >= argc) usage();
- base = argv[i];
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- int rv = procurl(ibuf, isiz, dec, br, base);
- if(path && path[0] == '@' && !br) printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of base command */
-static int runbase(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- int rv = procbase(ibuf, isiz, dec);
- if(path && path[0] == '@') printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of quote command */
-static int runquote(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- int rv = procquote(ibuf, isiz, dec);
- if(path && path[0] == '@') printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of mime command */
-static int runmime(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- char *ename = NULL;
- bool qb = false;
- bool on = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else if(!strcmp(argv[i], "-en")){
- if(++i >= argc) usage();
- ename = argv[i];
- } else if(!strcmp(argv[i], "-q")){
- qb = true;
- } else if(!strcmp(argv[i], "-on")){
- on = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- if(!ename) ename = "UTF-8";
- int rv = procmime(ibuf, isiz, dec, ename, qb, on);
- if(path && path[0] == '@') printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of pack command */
-static int runpack(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- bool bwt = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else if(!strcmp(argv[i], "-bwt")){
- bwt = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- int rv = procpack(ibuf, isiz, dec, bwt);
- if(path && path[0] == '@') printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of tcbs command */
-static int runtcbs(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- int rv = proctcbs(ibuf, isiz, dec);
- if(path && path[0] == '@') printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of zlib command */
-static int runzlib(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- bool gz = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else if(!strcmp(argv[i], "-gz")){
- gz = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- int rv = proczlib(ibuf, isiz, dec, gz);
- if(path && path[0] == '@') printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of xml command */
-static int runxml(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- bool br = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else if(!strcmp(argv[i], "-br")){
- br = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- int rv = procxml(ibuf, isiz, dec, br);
- if(path && path[0] == '@') printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of ucs command */
-static int runucs(int argc, char **argv){
- char *path = NULL;
- bool dec = false;
- for(int i = 2; i < argc; i++){
- if(!path && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-d")){
- dec = true;
- } else {
- usage();
- }
- } else if(!path){
- path = argv[i];
- } else {
- usage();
- }
- }
- char *ibuf;
- int isiz;
- if(path && path[0] == '@'){
- isiz = strlen(path) - 1;
- ibuf = tcmemdup(path + 1, isiz);
- } else {
- ibuf = tcreadfile(path, -1, &isiz);
- }
- if(!ibuf){
- eprintf("%s: cannot open", path ? path : "(stdin)");
- return 1;
- }
- int rv = procucs(ibuf, isiz, dec);
- if(path && path[0] == '@') printf("\n");
- free(ibuf);
- return rv;
-}
-
-
-/* parse arguments of date command */
-static int rundate(int argc, char **argv){
- char *str = NULL;
- int jl = INT_MAX;
- bool wf = false;
- bool rf = false;
- for(int i = 2; i < argc; i++){
- if(argv[i][0] == '-'){
- if(!strcmp(argv[i], "-ds")){
- if(++i >= argc) usage();
- str = argv[i];
- } else if(!strcmp(argv[i], "-jl")){
- if(++i >= argc) usage();
- jl = atoi(argv[i]);
- } else if(!strcmp(argv[i], "-wf")){
- wf = true;
- } else if(!strcmp(argv[i], "-rf")){
- rf = true;
- } else {
- usage();
- }
- } else {
- usage();
- }
- }
- int rv = procdate(str, jl, wf, rf);
- return rv;
-}
-
-
-/* parse arguments of conf command */
-static int runconf(int argc, char **argv){
- int mode = 0;
- for(int i = 2; i < argc; i++){
- if(argv[i][0] == '-'){
- if(!strcmp(argv[i], "-v")){
- mode = 'v';
- } else if(!strcmp(argv[i], "-i")){
- mode = 'i';
- } else if(!strcmp(argv[i], "-l")){
- mode = 'l';
- } else if(!strcmp(argv[i], "-p")){
- mode = 'p';
- } else {
- usage();
- }
- } else {
- usage();
- }
- }
- int rv = procconf(mode);
- return rv;
-}
-
-
-/* perform url command */
-static int procurl(const char *ibuf, int isiz, bool dec, bool br, const char *base){
- if(base){
- char *obuf = tcurlresolve(base, ibuf);
- printf("%s", obuf);
- free(obuf);
- } else if(br){
- TCMAP *elems = tcurlbreak(ibuf);
- const char *elem;
- if((elem = tcmapget2(elems, "self")) != NULL) printf("self: %s\n", elem);
- if((elem = tcmapget2(elems, "scheme")) != NULL) printf("scheme: %s\n", elem);
- if((elem = tcmapget2(elems, "host")) != NULL) printf("host: %s\n", elem);
- if((elem = tcmapget2(elems, "port")) != NULL) printf("port: %s\n", elem);
- if((elem = tcmapget2(elems, "authority")) != NULL) printf("authority: %s\n", elem);
- if((elem = tcmapget2(elems, "path")) != NULL) printf("path: %s\n", elem);
- if((elem = tcmapget2(elems, "file")) != NULL) printf("file: %s\n", elem);
- if((elem = tcmapget2(elems, "query")) != NULL) printf("query: %s\n", elem);
- if((elem = tcmapget2(elems, "fragment")) != NULL) printf("fragment: %s\n", elem);
- tcmapdel(elems);
- } else if(dec){
- int osiz;
- char *obuf = tcurldecode(ibuf, &osiz);
- fwrite(obuf, osiz, 1, stdout);
- free(obuf);
- } else {
- char *obuf = tcurlencode(ibuf, isiz);
- fwrite(obuf, strlen(obuf), 1, stdout);
- free(obuf);
- }
- return 0;
-}
-
-
-/* perform base command */
-static int procbase(const char *ibuf, int isiz, bool dec){
- if(dec){
- int osiz;
- char *obuf = tcbasedecode(ibuf, &osiz);
- fwrite(obuf, osiz, 1, stdout);
- free(obuf);
- } else {
- char *obuf = tcbaseencode(ibuf, isiz);
- fwrite(obuf, strlen(obuf), 1, stdout);
- free(obuf);
- }
- return 0;
-}
-
-
-/* perform quote command */
-static int procquote(const char *ibuf, int isiz, bool dec){
- if(dec){
- int osiz;
- char *obuf = tcquotedecode(ibuf, &osiz);
- fwrite(obuf, osiz, 1, stdout);
- free(obuf);
- } else {
- char *obuf = tcquoteencode(ibuf, isiz);
- fwrite(obuf, strlen(obuf), 1, stdout);
- free(obuf);
- }
- return 0;
-}
-
-
-/* perform mime command */
-static int procmime(const char *ibuf, int isiz, bool dec, const char *ename, bool qb, bool on){
- if(dec){
- char ebuf[32];
- char *obuf = tcmimedecode(ibuf, ebuf);
- if(on){
- fwrite(ebuf, strlen(ebuf), 1, stdout);
- } else {
- fwrite(obuf, strlen(obuf), 1, stdout);
- }
- free(obuf);
- } else {
- char *obuf = tcmimeencode(ibuf, ename, !qb);
- fwrite(obuf, strlen(obuf), 1, stdout);
- free(obuf);
- }
- return 0;
-}
-
-
-/* perform pack command */
-static int procpack(const char *ibuf, int isiz, bool dec, bool bwt){
- if(dec){
- int osiz;
- char *obuf = tcpackdecode(ibuf, isiz, &osiz);
- if(bwt && osiz > 0){
- int idx, step;
- TCREADVNUMBUF(obuf, idx, step);
- char *tbuf = tcbwtdecode(obuf + step, osiz - step, idx);
- fwrite(tbuf, osiz - step, 1, stdout);
- free(tbuf);
- } else {
- fwrite(obuf, osiz, 1, stdout);
- }
- free(obuf);
- } else {
- char *tbuf = NULL;
- if(bwt){
- int idx;
- tbuf = tcbwtencode(ibuf, isiz, &idx);
- char vnumbuf[sizeof(int)+1];
- int step;
- TCSETVNUMBUF(step, vnumbuf, idx);
- tbuf = tcrealloc(tbuf, isiz + step + 1);
- memmove(tbuf + step, tbuf, isiz);
- memcpy(tbuf, vnumbuf, step);
- isiz += step;
- ibuf = tbuf;
- }
- int osiz;
- char *obuf = tcpackencode(ibuf, isiz, &osiz);
- fwrite(obuf, osiz, 1, stdout);
- free(obuf);
- free(tbuf);
- }
- return 0;
-}
-
-
-/* perform tcbs command */
-static int proctcbs(const char *ibuf, int isiz, bool dec){
- if(dec){
- int osiz;
- char *obuf = tcbsdecode(ibuf, isiz, &osiz);
- fwrite(obuf, osiz, 1, stdout);
- free(obuf);
- } else {
- int osiz;
- char *obuf = tcbsencode(ibuf, isiz, &osiz);
- fwrite(obuf, osiz, 1, stdout);
- free(obuf);
- }
- return 0;
-}
-
-
-/* perform zlib command */
-static int proczlib(const char *ibuf, int isiz, bool dec, bool gz){
- if(dec){
- int osiz;
- char *obuf = gz ? tcgzipdecode(ibuf, isiz, &osiz) : tcinflate(ibuf, isiz, &osiz);
- if(obuf){
- fwrite(obuf, osiz, 1, stdout);
- free(obuf);
- } else {
- eprintf("inflate failure");
- }
- } else {
- int osiz;
- char *obuf = gz ? tcgzipencode(ibuf, isiz, &osiz) : tcdeflate(ibuf, isiz, &osiz);
- if(obuf){
- fwrite(obuf, osiz, 1, stdout);
- free(obuf);
- } else {
- eprintf("deflate failure");
- }
- }
- return 0;
-}
-
-
-/* perform xml command */
-static int procxml(const char *ibuf, int isiz, bool dec, bool br){
- if(br){
- TCLIST *elems = tcxmlbreak(ibuf);
- for(int i = 0; i < tclistnum(elems); i++){
- int esiz;
- const char *elem = tclistval(elems, i, &esiz);
- char *estr = tcmemdup(elem, esiz);
- tcstrsubchr(estr, "\t\n\r", " ");
- tcstrtrim(estr);
- if(*estr != '\0'){
- if(*elem == '<'){
- if(tcstrfwm(estr, "<!--")){
- printf("COMMENT\t%s\n", estr);
- } else if(tcstrfwm(estr, "<![CDATA[")){
- printf("CDATA\t%s\n", estr);
- } else if(tcstrfwm(estr, "<!")){
- printf("DECL\t%s\n", estr);
- } else if(tcstrfwm(estr, "<?")){
- printf("XMLDECL\t%s\n", estr);
- } else {
- TCMAP *attrs = tcxmlattrs(estr);
- tcmapiterinit(attrs);
- const char *name;
- if((name = tcmapget2(attrs, "")) != NULL){
- if(tcstrfwm(estr, "</")){
- printf("END");
- } else if(tcstrbwm(estr, "/>")){
- printf("EMPTY");
- } else {
- printf("BEGIN");
- }
- printf("\t%s", name);
- while((name = tcmapiternext2(attrs)) != NULL){
- if(*name == '\0') continue;
- printf("\t%s\t%s", name, tcmapiterval2(name));
- }
- printf("\n");
- }
- tcmapdel(attrs);
- }
- } else {
- char *dstr = tcxmlunescape(estr);
- printf("TEXT\t%s\n", dstr);
- free(dstr);
- }
- }
- free(estr);
- }
- tclistdel(elems);
- } else if(dec){
- char *obuf = tcxmlunescape(ibuf);
- fwrite(obuf, strlen(obuf), 1, stdout);
- free(obuf);
- } else {
- char *obuf = tcxmlescape(ibuf);
- fwrite(obuf, strlen(obuf), 1, stdout);
- free(obuf);
- }
- return 0;
-}
-
-
-/* perform ucs command */
-static int procucs(const char *ibuf, int isiz, bool dec){
- if(dec){
- uint16_t *ary = tcmalloc(isiz + 1);
- int anum = 0;
- for(int i = 0; i < isiz; i += 2){
- ary[anum++] = (((unsigned char *)ibuf)[i] << 8) + ((unsigned char *)ibuf)[i+1];
- }
- char *str = tcmalloc(isiz * 3 + 1);
- tcstrucstoutf(ary, anum, str);
- printf("%s", str);
- free(str);
- free(ary);
- } else {
- uint16_t *ary = tcmalloc(isiz * sizeof(uint16_t) + 1);
- int anum;
- tcstrutftoucs(ibuf, ary, &anum);
- for(int i = 0; i < anum; i++){
- int c = ary[i];
- putchar(c >> 8);
- putchar(c & 0xff);
- }
- free(ary);
- }
- return 0;
-}
-
-
-/* perform date command */
-static int procdate(const char *str, int jl, bool wf, bool rf){
- int64_t t = str ? tcstrmktime(str) : time(NULL);
- if(wf){
- char buf[48];
- tcdatestrwww(t, jl, buf);
- printf("%s\n", buf);
- } else if(rf){
- char buf[48];
- tcdatestrhttp(t, jl, buf);
- printf("%s\n", buf);
- } else {
- printf("%lld\n", (long long int)t);
- }
- return 0;
-}
-
-
-/* perform conf command */
-static int procconf(int mode){
- switch(mode){
- case 'v':
- printf("%s\n", tcversion);
- break;
- case 'i':
- printf("%s\n", _TC_APPINC);
- break;
- case 'l':
- printf("%s\n", _TC_APPLIBS);
- break;
- case 'p':
- printf("%s\n", _TC_BINDIR);
- break;
- default:
- printf("myconf(version): %s\n", tcversion);
- printf("myconf(libver): %d\n", _TC_LIBVER);
- printf("myconf(formatver): %s\n", _TC_FORMATVER);
- printf("myconf(prefix): %s\n", _TC_PREFIX);
- printf("myconf(includedir): %s\n", _TC_INCLUDEDIR);
- printf("myconf(libdir): %s\n", _TC_LIBDIR);
- printf("myconf(bindir): %s\n", _TC_BINDIR);
- printf("myconf(libexecdir): %s\n", _TC_LIBEXECDIR);
- printf("myconf(appinc): %s\n", _TC_APPINC);
- printf("myconf(applibs): %s\n", _TC_APPLIBS);
- printf("myconf(bigend): %d\n", TCBIGEND);
- printf("myconf(usezlib): %d\n", TCUSEZLIB);
- printf("sizeof(bool): %d\n", sizeof(bool));
- printf("sizeof(char): %d\n", sizeof(char));
- printf("sizeof(short): %d\n", sizeof(short));
- printf("sizeof(int): %d\n", sizeof(int));
- printf("sizeof(long): %d\n", sizeof(long));
- printf("sizeof(long long): %d\n", sizeof(long long));
- printf("sizeof(float): %d\n", sizeof(float));
- printf("sizeof(double): %d\n", sizeof(double));
- printf("sizeof(long double): %d\n", sizeof(long double));
- printf("sizeof(size_t): %d\n", sizeof(size_t));
- printf("sizeof(time_t): %d\n", sizeof(time_t));
- printf("sizeof(off_t): %d\n", sizeof(off_t));
- printf("sizeof(ino_t): %d\n", sizeof(ino_t));
- printf("sizeof(intptr_t): %d\n", sizeof(intptr_t));
- printf("sizeof(void *): %d\n", sizeof(void *));
- printf("macro(CHAR_MAX): %llu\n", (unsigned long long)CHAR_MAX);
- printf("macro(SHRT_MAX): %llu\n", (unsigned long long)SHRT_MAX);
- printf("macro(INT_MAX): %llu\n", (unsigned long long)INT_MAX);
- printf("macro(LONG_MAX): %llu\n", (unsigned long long)LONG_MAX);
- printf("macro(LLONG_MAX): %llu\n", (unsigned long long)LLONG_MAX);
- printf("macro(PATH_MAX): %llu\n", (unsigned long long)PATH_MAX);
- printf("macro(RAND_MAX): %llu\n", (unsigned long long)RAND_MAX);
- printf("sysconf(_SC_CLK_TCK): %ld\n", sysconf(_SC_CLK_TCK));
- printf("sysconf(_SC_OPEN_MAX): %ld\n", sysconf(_SC_OPEN_MAX));
- printf("sysconf(_SC_PAGESIZE): %ld\n", sysconf(_SC_PAGESIZE));
- struct stat sbuf;
- if(stat(MYCDIRSTR, &sbuf) == 0){
- printf("stat(st_uid): %d\n", (int)sbuf.st_uid);
- printf("stat(st_gid): %d\n", (int)sbuf.st_gid);
- printf("stat(st_blksize): %d\n", (int)sbuf.st_blksize);
- }
- }
- return 0;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The test cases of the on-memory database API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include "myconf.h"
-
-#define RECBUFSIZ 32 // buffer for records
-
-typedef struct { // type of structure for combo thread
- TCMDB *mdb;
- int rnum;
- bool rnd;
- int id;
-} TARGCOMBO;
-
-typedef struct { // type of structure for typical thread
- TCMDB *mdb;
- int rnum;
- bool nc;
- int rratio;
- int id;
-} TARGTYPICAL;
-
-
-/* global variables */
-const char *g_progname; // program name
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void iprintf(const char *format, ...);
-static void eprint(const char *func);
-static int myrand(int range);
-static int myrandnd(int range);
-static int runcombo(int argc, char **argv);
-static int runtypical(int argc, char **argv);
-static int proccombo(int tnum, int rnum, int bnum, bool rnd);
-static int proctypical(int tnum, int rnum, int bnum, bool nc, int rratio);
-static void *threadwrite(void *targ);
-static void *threadread(void *targ);
-static void *threadremove(void *targ);
-static void *threadtypical(void *targ);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "combo")){
- rv = runcombo(argc, argv);
- } else if(!strcmp(argv[1], "typical")){
- rv = runtypical(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: test cases of the on-memory database API of Tokyo Cabinet\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s combo [-rnd] tnum rnum [bnum]\n", g_progname);
- fprintf(stderr, " %s typical [-nc] [-rr num] tnum rnum [bnum]\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print formatted information string and flush the buffer */
-static void iprintf(const char *format, ...){
- va_list ap;
- va_start(ap, format);
- vprintf(format, ap);
- fflush(stdout);
- va_end(ap);
-}
-
-
-/* print error message of on-memory database */
-static void eprint(const char *func){
- fprintf(stderr, "%s: %s: error\n", g_progname, func);
-}
-
-
-/* get a random number */
-static int myrand(int range){
- return (int)((double)range * rand() / (RAND_MAX + 1.0));
-}
-
-
-/* get a random number based on normal distribution */
-static int myrandnd(int range){
- int num = (int)tcdrandnd(range >> 1, range / 10);
- return (num < 0 || num >= range) ? 0 : num;
-}
-
-
-/* parse arguments of combo command */
-static int runcombo(int argc, char **argv){
- char *tstr = NULL;
- char *rstr = NULL;
- char *bstr = NULL;
- bool rnd = false;
- for(int i = 2; i < argc; i++){
- if(!tstr && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-rnd")){
- rnd = true;
- } else {
- usage();
- }
- } else if(!tstr){
- tstr = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else {
- usage();
- }
- }
- if(!tstr || !rstr) usage();
- int tnum = atoi(tstr);
- int rnum = atoi(rstr);
- if(tnum < 1 || rnum < 1) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int rv = proccombo(tnum, rnum, bnum, rnd);
- return rv;
-}
-
-
-/* parse arguments of typical command */
-static int runtypical(int argc, char **argv){
- char *tstr = NULL;
- char *rstr = NULL;
- char *bstr = NULL;
- int rratio = -1;
- bool nc = false;
- for(int i = 2; i < argc; i++){
- if(!tstr && argv[i][0] == '-'){
- if(!strcmp(argv[i], "-nc")){
- nc = true;
- } else if(!strcmp(argv[i], "-rr")){
- if(++i >= argc) usage();
- rratio = atoi(argv[i]);
- } else {
- usage();
- }
- } else if(!tstr){
- tstr = argv[i];
- } else if(!rstr){
- rstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else {
- usage();
- }
- }
- if(!tstr || !rstr) usage();
- int tnum = atoi(tstr);
- int rnum = atoi(rstr);
- if(tnum < 1 || rnum < 1) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int rv = proctypical(tnum, rnum, bnum, nc, rratio);
- return rv;
-}
-
-
-/* perform combo command */
-static int proccombo(int tnum, int rnum, int bnum, bool rnd){
- iprintf("<Combination Test>\n tnum=%d rnum=%d bnum=%d rnd=%d\n\n", tnum, rnum, bnum, rnd);
- bool err = false;
- double stime = tctime();
- TCMDB *mdb = (bnum > 0) ? tcmdbnew2(bnum) : tcmdbnew();
- TARGCOMBO targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].mdb = mdb;
- targs[0].rnum = rnum;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadwrite(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].mdb = mdb;
- targs[i].rnum = rnum;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadwrite, targs + i) != 0){
- eprint("pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint("pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- if(tnum == 1){
- targs[0].mdb = mdb;
- targs[0].rnum = rnum;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadread(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].mdb = mdb;
- targs[i].rnum = rnum;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadread, targs + i) != 0){
- eprint("pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint("pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- if(tnum == 1){
- targs[0].mdb = mdb;
- targs[0].rnum = rnum;
- targs[0].rnd = rnd;
- targs[0].id = 0;
- if(threadremove(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].mdb = mdb;
- targs[i].rnum = rnum;
- targs[i].rnd = rnd;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadremove, targs + i) != 0){
- eprint("pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint("pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcmdbrnum(mdb));
- tcmdbdel(mdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* perform typical command */
-static int proctypical(int tnum, int rnum, int bnum, bool nc, int rratio){
- iprintf("<Typical Access Test>\n tnum=%d rnum=%d bnum=%d nc=%d rratio=%d\n\n",
- tnum, rnum, bnum, nc, rratio);
- bool err = false;
- double stime = tctime();
- TCMDB *mdb = (bnum > 0) ? tcmdbnew2(bnum) : tcmdbnew();
- TARGTYPICAL targs[tnum];
- pthread_t threads[tnum];
- if(tnum == 1){
- targs[0].mdb = mdb;
- targs[0].rnum = rnum;
- targs[0].nc = nc;
- targs[0].rratio = rratio;
- targs[0].id = 0;
- if(threadtypical(targs) != NULL) err = true;
- } else {
- for(int i = 0; i < tnum; i++){
- targs[i].mdb = mdb;
- targs[i].rnum = rnum;
- targs[i].nc = nc;
- targs[i].rratio= rratio;
- targs[i].id = i;
- if(pthread_create(threads + i, NULL, threadtypical, targs + i) != 0){
- eprint("pthread_create");
- targs[i].id = -1;
- err = true;
- }
- }
- for(int i = 0; i < tnum; i++){
- if(targs[i].id == -1) continue;
- void *rv;
- if(pthread_join(threads[i], &rv) != 0){
- eprint("pthread_join");
- err = true;
- } else if(rv){
- err = true;
- }
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcmdbrnum(mdb));
- tcmdbdel(mdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("%s\n\n", err ? "error" : "ok");
- return err ? 1 : 0;
-}
-
-
-/* thread the write function */
-static void *threadwrite(void *targ){
- TCMDB *mdb = ((TARGCOMBO *)targ)->mdb;
- int rnum = ((TARGCOMBO *)targ)->rnum;
- bool rnd = ((TARGCOMBO *)targ)->rnd;
- int id = ((TARGCOMBO *)targ)->id;
- double stime = tctime();
- if(id == 0) iprintf("writing:\n");
- int base = id * rnum;
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", base + (rnd ? myrand(i) : i));
- tcmdbput(mdb, buf, len, buf, len);
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(id == 0) iprintf("time: %.3f\n", tctime() - stime);
- return NULL;
-}
-
-
-/* thread the read function */
-static void *threadread(void *targ){
- TCMDB *mdb = ((TARGCOMBO *)targ)->mdb;
- int rnum = ((TARGCOMBO *)targ)->rnum;
- bool rnd = ((TARGCOMBO *)targ)->rnd;
- int id = ((TARGCOMBO *)targ)->id;
- double stime = tctime();
- if(id == 0) iprintf("reading:\n");
- int base = id * rnum;
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%08d", base + (rnd ? myrand(i) : i));
- int vsiz;
- char *vbuf = tcmdbget(mdb, kbuf, ksiz, &vsiz);
- if(vbuf) free(vbuf);
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(id == 0) iprintf("time: %.3f\n", tctime() - stime);
- return NULL;
-}
-
-
-/* thread the remove function */
-static void *threadremove(void *targ){
- TCMDB *mdb = ((TARGCOMBO *)targ)->mdb;
- int rnum = ((TARGCOMBO *)targ)->rnum;
- bool rnd = ((TARGCOMBO *)targ)->rnd;
- int id = ((TARGCOMBO *)targ)->id;
- double stime = tctime();
- if(id == 0) iprintf("removing:\n");
- int base = id * rnum;
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", base + (rnd ? myrand(i) : i));
- tcmdbout(mdb, buf, len);
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(id == 0) iprintf("time: %.3f\n", tctime() - stime);
- return NULL;
-}
-
-
-/* thread the typical function */
-static void *threadtypical(void *targ){
- TCMDB *mdb = ((TARGTYPICAL *)targ)->mdb;
- int rnum = ((TARGTYPICAL *)targ)->rnum;
- bool nc = ((TARGTYPICAL *)targ)->nc;
- int rratio = ((TARGTYPICAL *)targ)->rratio;
- int id = ((TARGTYPICAL *)targ)->id;
- bool err = false;
- TCMAP *map = (!nc && id == 0) ? tcmapnew2(rnum + 1) : NULL;
- int base = id * rnum;
- int mrange = tclmax(50 + rratio, 100);
- for(int i = 1; !err && i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", base + myrandnd(i));
- int rnd = myrand(mrange);
- if(rnd < 10){
- tcmdbput(mdb, buf, len, buf, len);
- if(map) tcmapput(map, buf, len, buf, len);
- } else if(rnd < 15){
- tcmdbputkeep(mdb, buf, len, buf, len);
- if(map) tcmapputkeep(map, buf, len, buf, len);
- } else if(rnd < 20){
- tcmdbputcat(mdb, buf, len, buf, len);
- if(map) tcmapputcat(map, buf, len, buf, len);
- } else if(rnd < 30){
- tcmdbout(mdb, buf, len);
- if(map) tcmapout(map, buf, len);
- } else if(rnd < 31){
- if(myrand(10) == 0) tcmdbiterinit(mdb);
- for(int j = 0; !err && j < 10; j++){
- int ksiz;
- char *kbuf = tcmdbiternext(mdb, &ksiz);
- if(kbuf) free(kbuf);
- }
- } else {
- int vsiz;
- char *vbuf = tcmdbget(mdb, buf, len, &vsiz);
- if(vbuf){
- if(map){
- int msiz;
- const char *mbuf = tcmapget(map, buf, len, &msiz);
- if(msiz != vsiz || memcmp(mbuf, vbuf, vsiz)){
- eprint("(validation)");
- err = true;
- }
- }
- free(vbuf);
- } else {
- if(map && tcmapget(map, buf, len, &vsiz)){
- eprint("(validation)");
- err = true;
- }
- }
- }
- if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- if(map){
- tcmapiterinit(map);
- int ksiz;
- const char *kbuf;
- while(!err && (kbuf = tcmapiternext(map, &ksiz)) != NULL){
- int vsiz;
- char *vbuf = tcmdbget(mdb, kbuf, ksiz, &vsiz);
- if(vbuf){
- int msiz;
- const char *mbuf = tcmapget(map, kbuf, ksiz, &msiz);
- if(!mbuf || msiz != vsiz || memcmp(mbuf, vbuf, vsiz)){
- eprint("(validation)");
- err = true;
- }
- free(vbuf);
- } else {
- eprint("(validation)");
- err = true;
- }
- }
- tcmapdel(map);
- }
- return err ? "error" : NULL;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The test cases of the utility API
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include <tcutil.h>
-#include "myconf.h"
-
-#define RECBUFSIZ 32 // buffer for records
-
-
-/* global variables */
-const char *g_progname; // program name
-
-
-/* function prototypes */
-int main(int argc, char **argv);
-static void usage(void);
-static void iprintf(const char *format, ...);
-static int myrand(int range);
-static int runxstr(int argc, char **argv);
-static int runlist(int argc, char **argv);
-static int runmap(int argc, char **argv);
-static int runmdb(int argc, char **argv);
-static int runmisc(int argc, char **argv);
-static int runwicked(int argc, char **argv);
-static int procxstr(int rnum);
-static int proclist(int rnum, int anum);
-static int procmap(int rnum, int bnum);
-static int procmdb(int rnum, int bnum);
-static int procmisc(int rnum);
-static int procwicked(int rnum);
-
-
-/* main routine */
-int main(int argc, char **argv){
- g_progname = argv[0];
- srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- if(argc < 2) usage();
- int rv = 0;
- if(!strcmp(argv[1], "xstr")){
- rv = runxstr(argc, argv);
- } else if(!strcmp(argv[1], "list")){
- rv = runlist(argc, argv);
- } else if(!strcmp(argv[1], "map")){
- rv = runmap(argc, argv);
- } else if(!strcmp(argv[1], "mdb")){
- rv = runmdb(argc, argv);
- } else if(!strcmp(argv[1], "misc")){
- rv = runmisc(argc, argv);
- } else if(!strcmp(argv[1], "wicked")){
- rv = runwicked(argc, argv);
- } else {
- usage();
- }
- return rv;
-}
-
-
-/* print the usage and exit */
-static void usage(void){
- fprintf(stderr, "%s: test cases of the utility API of Tokyo Cabinet\n", g_progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "usage:\n");
- fprintf(stderr, " %s xstr rnum\n", g_progname);
- fprintf(stderr, " %s list rnum [anum]\n", g_progname);
- fprintf(stderr, " %s map rnum [bnum]\n", g_progname);
- fprintf(stderr, " %s mdb rnum [bnum]\n", g_progname);
- fprintf(stderr, " %s misc rnum\n", g_progname);
- fprintf(stderr, " %s wicked rnum\n", g_progname);
- fprintf(stderr, "\n");
- exit(1);
-}
-
-
-/* print formatted information string and flush the buffer */
-static void iprintf(const char *format, ...){
- va_list ap;
- va_start(ap, format);
- vprintf(format, ap);
- fflush(stdout);
- va_end(ap);
-}
-
-
-/* get a random number */
-static int myrand(int range){
- return (int)((double)range * rand() / (RAND_MAX + 1.0));
-}
-
-
-/* parse arguments of xstr command */
-static int runxstr(int argc, char **argv){
- char *rstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!rstr && argv[i][0] == '-'){
- usage();
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procxstr(rnum);
- return rv;
-}
-
-
-/* parse arguments of list command */
-static int runlist(int argc, char **argv){
- char *rstr = NULL;
- char *astr = NULL;
- for(int i = 2; i < argc; i++){
- if(!rstr && argv[i][0] == '-'){
- usage();
- } else if(!rstr){
- rstr = argv[i];
- } else if(!astr){
- astr = argv[i];
- } else {
- usage();
- }
- }
- if(!rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int anum = astr ? atoi(astr) : -1;
- int rv = proclist(rnum, anum);
- return rv;
-}
-
-
-/* parse arguments of map command */
-static int runmap(int argc, char **argv){
- char *rstr = NULL;
- char *bstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!rstr && argv[i][0] == '-'){
- usage();
- } else if(!rstr){
- rstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else {
- usage();
- }
- }
- if(!rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int rv = procmap(rnum, bnum);
- return rv;
-}
-
-
-/* parse arguments of mdb command */
-static int runmdb(int argc, char **argv){
- char *rstr = NULL;
- char *bstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!rstr && argv[i][0] == '-'){
- usage();
- } else if(!rstr){
- rstr = argv[i];
- } else if(!bstr){
- bstr = argv[i];
- } else {
- usage();
- }
- }
- if(!rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int bnum = bstr ? atoi(bstr) : -1;
- int rv = procmdb(rnum, bnum);
- return rv;
-}
-
-
-/* parse arguments of misc command */
-static int runmisc(int argc, char **argv){
- char *rstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!rstr && argv[i][0] == '-'){
- usage();
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procmisc(rnum);
- return rv;
-}
-
-
-/* parse arguments of wicked command */
-static int runwicked(int argc, char **argv){
- char *rstr = NULL;
- for(int i = 2; i < argc; i++){
- if(!rstr && argv[i][0] == '-'){
- usage();
- } else if(!rstr){
- rstr = argv[i];
- } else {
- usage();
- }
- }
- if(!rstr) usage();
- int rnum = atoi(rstr);
- if(rnum < 1) usage();
- int rv = procwicked(rnum);
- return rv;
-}
-
-
-/* perform xstr command */
-static int procxstr(int rnum){
- iprintf("<Extensible String Writing Test>\n rnum=%d\n\n", rnum);
- double stime = tctime();
- TCXSTR *xstr = tcxstrnew();
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- tcxstrcat(xstr, buf, len);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- tcxstrdel(xstr);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("ok\n\n");
- return 0;
-}
-
-
-/* perform list command */
-static int proclist(int rnum, int anum){
- iprintf("<List Writing Test>\n rnum=%d anum=%d\n\n", rnum, anum);
- double stime = tctime();
- TCLIST *list = (anum > 0) ? tclistnew2(anum) : tclistnew();
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- tclistpush(list, buf, len);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- tclistdel(list);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("ok\n\n");
- return 0;
-}
-
-
-/* perform map command */
-static int procmap(int rnum, int bnum){
- iprintf("<Map Writing Test>\n rnum=%d\n\n", rnum);
- double stime = tctime();
- TCMAP *map = (bnum > 0) ? tcmapnew2(bnum) : tcmapnew();
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- tcmapput(map, buf, len, buf, len);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- tcmapdel(map);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("ok\n\n");
- return 0;
-}
-
-
-/* perform mdb command */
-static int procmdb(int rnum, int bnum){
- iprintf("<On-memory Database Writing Test>\n rnum=%d\n\n", rnum);
- double stime = tctime();
- TCMDB *mdb = (bnum > 0) ? tcmdbnew2(bnum) : tcmdbnew();
- for(int i = 1; i <= rnum; i++){
- char buf[RECBUFSIZ];
- int len = sprintf(buf, "%08d", i);
- tcmdbput(mdb, buf, len, buf, len);
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("record number: %llu\n", (unsigned long long)tcmdbrnum(mdb));
- iprintf("size: %llu\n", (unsigned long long)tcmdbmsiz(mdb));
- tcmdbdel(mdb);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("ok\n\n");
- return 0;
-}
-
-
-/* perform misc command */
-static int procmisc(int rnum){
- iprintf("<Miscellaneous Test>\n rnum=%d\n\n", rnum);
- double stime = tctime();
- bool err = false;
- for(int i = 1; i <= rnum && !err; i++){
- const char *str = "5%2+3-1=4 \"Yes/No\" <a&b>";
- int slen = strlen(str);
- char *buf, *dec;
- int bsiz, dsiz, jl;
- time_t date, ddate;
- TCXSTR *xstr;
- TCLIST *list;
- TCMAP *map;
- buf = tcmemdup(str, slen);
- xstr = tcxstrfrommalloc(buf, slen);
- buf = tcxstrtomalloc(xstr);
- if(strcmp(buf, str)) err = true;
- free(buf);
- if(tclmax(1, 2) != 2) err = true;
- if(tclmin(1, 2) != 1) err = true;
- tclrand();
- if(tcdrand() >= 1.0) err = true;
- tcdrandnd(50, 10);
- if(tcstricmp("abc", "ABC") != 0) err = true;
- if(!tcstrfwm("abc", "ab") || !tcstrifwm("abc", "AB")) err = true;
- if(!tcstrbwm("abc", "bc") || !tcstribwm("abc", "BC")) err = true;
- if(tcstrdist("abcde", "abdfgh") != 4 || tcstrdist("abdfgh", "abcde") != 4) err = true;
- if(tcstrdistutf("abcde", "abdfgh") != 4 || tcstrdistutf("abdfgh", "abcde") != 4) err = true;
- buf = tcmemdup("abcde", 5);
- tcstrtoupper(buf);
- if(strcmp(buf, "ABCDE")) err = true;
- tcstrtolower(buf);
- if(strcmp(buf, "abcde")) err = true;
- free(buf);
- buf = tcmemdup(" ab cd ", 10);
- tcstrtrim(buf);
- if(strcmp(buf, "ab cd")) err = true;
- tcstrsqzspc(buf);
- if(strcmp(buf, "ab cd")) err = true;
- tcstrsubchr(buf, "cd", "C");
- if(strcmp(buf, "ab C")) err = true;
- if(tcstrcntutf(buf) != 4) err = true;
- tcstrcututf(buf, 2);
- if(strcmp(buf, "ab")) err = true;
- free(buf);
- if(i % 10 == 1){
- int anum = myrand(30);
- uint16_t ary[anum+1];
- for(int j = 0; j < anum; j++){
- ary[j] = myrand(65535) + 1;
- }
- char ustr[anum*3+1];
- tcstrucstoutf(ary, anum, ustr);
- uint16_t dary[anum+1];
- int danum;
- tcstrutftoucs(ustr, dary, &danum);
- if(danum != anum){
- err = true;
- } else {
- for(int j = 0; j < danum; j++){
- if(dary[j] != dary[j]) err = true;
- }
- }
- list = tcstrsplit(",a,b..c,d,", ",.");
- if(tclistnum(list) != 7) err = true;
- buf = tcstrjoin(list, ':');
- if(strcmp(buf, ":a:b::c:d:")) err = true;
- free(buf);
- tclistdel(list);
- if(!tcregexmatch("ABCDEFGHI", "*(b)c[d-f]*g(h)")) err = true;
- buf = tcregexreplace("ABCDEFGHI", "*(b)c[d-f]*g(h)", "[\\1][\\2][&]");
- if(strcmp(buf, "A[B][H][BCDEFGH]I")) err = true;
- free(buf);
- }
- buf = tcmalloc(48);
- date = myrand(INT_MAX - 1000000);
- jl = 3600 * (myrand(23) - 11);
- tcdatestrwww(date, jl, buf);
- ddate = tcstrmktime(buf);
- if(ddate != date) err = true;
- tcdatestrhttp(date, jl, buf);
- ddate = tcstrmktime(buf);
- if(ddate != date) err = true;
- free(buf);
- if(i % 100){
- map = tcmapnew();
- for(int j = 0; j < 10; j++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(10));
- tcmapaddint(map, kbuf, ksiz, 1);
- const char *vbuf = tcmapget2(map, kbuf);
- if(*(int *)vbuf < 1) err = true;
- }
- tcmapdel(map);
- }
- buf = tcurlencode(str, slen);
- if(strcmp(buf, "5%252%2B3-1%3D4%20%22Yes%2FNo%22%20%3Ca%26b%3E")) err = true;
- dec = tcurldecode(buf, &dsiz);
- if(dsiz != slen || strcmp(dec, str)) err = true;
- free(dec);
- free(buf);
- if(i % 10 == 1){
- map = tcurlbreak("http://mikio:oikim@estraier.net:1978/foo/bar/baz.cgi?ab=cd&ef=jkl#quux");
- const char *elem;
- if(!(elem = tcmapget2(map, "self")) ||
- strcmp(elem, "http://mikio:oikim@estraier.net:1978/foo/bar/baz.cgi?ab=cd&ef=jkl#quux"))
- err = true;
- if(!(elem = tcmapget2(map, "scheme")) || strcmp(elem, "http")) err = true;
- if(!(elem = tcmapget2(map, "host")) || strcmp(elem, "estraier.net")) err = true;
- if(!(elem = tcmapget2(map, "port")) || strcmp(elem, "1978")) err = true;
- if(!(elem = tcmapget2(map, "authority")) || strcmp(elem, "mikio:oikim")) err = true;
- if(!(elem = tcmapget2(map, "path")) || strcmp(elem, "/foo/bar/baz.cgi")) err = true;
- if(!(elem = tcmapget2(map, "file")) || strcmp(elem, "baz.cgi")) err = true;
- if(!(elem = tcmapget2(map, "query")) || strcmp(elem, "ab=cd&ef=jkl")) err = true;
- if(!(elem = tcmapget2(map, "fragment")) || strcmp(elem, "quux")) err = true;
- tcmapdel(map);
- buf = tcurlresolve("http://a:b@c.d:1/e/f/g.h?i=j#k", "http://A:B@C.D:1/E/F/G.H?I=J#K");
- if(strcmp(buf, "http://A:B@c.d:1/E/F/G.H?I=J#K")) err = true;
- free(buf);
- buf = tcurlresolve("http://a:b@c.d:1/e/f/g.h?i=j#k", "/E/F/G.H?I=J#K");
- if(strcmp(buf, "http://a:b@c.d:1/E/F/G.H?I=J#K")) err = true;
- free(buf);
- buf = tcurlresolve("http://a:b@c.d:1/e/f/g.h?i=j#k", "G.H?I=J#K");
- if(strcmp(buf, "http://a:b@c.d:1/e/f/G.H?I=J#K")) err = true;
- free(buf);
- buf = tcurlresolve("http://a:b@c.d:1/e/f/g.h?i=j#k", "?I=J#K");
- if(strcmp(buf, "http://a:b@c.d:1/e/f/g.h?I=J#K")) err = true;
- free(buf);
- buf = tcurlresolve("http://a:b@c.d:1/e/f/g.h?i=j#k", "#K");
- if(strcmp(buf, "http://a:b@c.d:1/e/f/g.h?i=j#K")) err = true;
- free(buf);
- }
- buf = tcbaseencode(str, slen);
- if(strcmp(buf, "NSUyKzMtMT00ICJZZXMvTm8iIDxhJmI+")) err = true;
- dec = tcbasedecode(buf, &dsiz);
- if(dsiz != slen || strcmp(dec, str)) err = true;
- free(dec);
- free(buf);
- buf = tcquoteencode(str, slen);
- if(strcmp(buf, "5%2+3-1=3D4 \"Yes/No\" <a&b>")) err = true;
- dec = tcquotedecode(buf, &dsiz);
- if(dsiz != slen || strcmp(dec, str)) err = true;
- free(dec);
- free(buf);
- buf = tcmimeencode(str, "UTF-8", true);
- if(strcmp(buf, "=?UTF-8?B?NSUyKzMtMT00ICJZZXMvTm8iIDxhJmI+?=")) err = true;
- char encname[32];
- dec = tcmimedecode(buf, encname);
- if(strcmp(dec, str) || strcmp(encname, "UTF-8")) err = true;
- free(dec);
- free(buf);
- buf = tcpackencode(str, slen, &bsiz);
- dec = tcpackdecode(buf, bsiz, &dsiz);
- if(dsiz != slen || strcmp(dec, str)) err = true;
- free(dec);
- free(buf);
- buf = tcbsencode(str, slen, &bsiz);
- dec = tcbsdecode(buf, bsiz, &dsiz);
- if(dsiz != slen || strcmp(dec, str)) err = true;
- free(dec);
- free(buf);
- int idx;
- buf = tcbwtencode(str, slen, &idx);
- if(memcmp(buf, "4\"o 5a23s-%+=> 1b/\"<&YNe", slen) || idx != 13) err = true;
- dec = tcbwtdecode(buf, slen, idx);
- if(memcmp(dec, str, slen)) err = true;
- free(dec);
- free(buf);
- if(_tc_deflate){
- if((buf = tcdeflate(str, slen, &bsiz)) != NULL){
- if((dec = tcinflate(buf, bsiz, &dsiz)) != NULL){
- if(slen != dsiz || memcmp(str, dec, dsiz)) err = true;
- free(dec);
- } else {
- err = true;
- }
- free(buf);
- } else {
- err = true;
- }
- if((buf = tcgzipencode(str, slen, &bsiz)) != NULL){
- if((dec = tcgzipdecode(buf, bsiz, &dsiz)) != NULL){
- if(slen != dsiz || memcmp(str, dec, dsiz)) err = true;
- free(dec);
- } else {
- err = true;
- }
- free(buf);
- } else {
- err = true;
- }
- if(tcgetcrc("hoge", 4) % 10000 != 7034) err = true;
- }
- int anum = myrand(50)+1;
- unsigned int ary[anum];
- for(int j = 0; j < anum; j++){
- ary[j] = myrand(INT_MAX);
- }
- buf = tcberencode(ary, anum, &bsiz);
- int dnum;
- unsigned int *dary = tcberdecode(buf, bsiz, &dnum);
- if(anum != dnum || memcmp(ary, dary, sizeof(*dary) * dnum)) err = true;
- free(dary);
- free(buf);
- buf = tcxmlescape(str);
- if(strcmp(buf, "5%2+3-1=4 "Yes/No" <a&b>")) err = true;
- dec = tcxmlunescape(buf);
- if(strcmp(dec, str)) err = true;
- free(dec);
- free(buf);
- if(i % 10 == 1){
- list = tcxmlbreak("<abc de=\"foo&\" gh='<bar>'>xyz<br>\na<!--<mikio>--></abc>");
- for(int j = 0; j < tclistnum(list); j++){
- const char *elem = tclistval2(list, j);
- TCMAP *attrs = tcxmlattrs(elem);
- tcmapdel(attrs);
- }
- tclistdel(list);
- }
- if(i % 10 == 1){
- for(int16_t j = 1; j <= 0x2000; j *= 2){
- for(int16_t num = j - 1; num <= j + 1; num++){
- int16_t nnum = TCHTOIS(num);
- if(num != TCITOHS(nnum)) err = true;
- }
- }
- for(int32_t j = 1; j <= 0x20000000; j *= 2){
- for(int32_t num = j - 1; num <= j + 1; num++){
- int32_t nnum = TCHTOIL(num);
- if(num != TCITOHL(nnum)) err = true;
- char buf[TCNUMBUFSIZ];
- int step, nstep;
- TCSETVNUMBUF(step, buf, num);
- TCREADVNUMBUF(buf, nnum, nstep);
- if(num != nnum || step != nstep) err = true;
- }
- }
- for(int64_t j = 1; j <= 0x2000000000000000; j *= 2){
- for(int64_t num = j - 1; num <= j + 1; num++){
- int64_t nnum = TCHTOILL(num);
- if(num != TCITOHLL(nnum)) err = true;
- char buf[TCNUMBUFSIZ];
- int step, nstep;
- TCSETVNUMBUF64(step, buf, num);
- TCREADVNUMBUF64(buf, nnum, nstep);
- if(num != nnum || step != nstep) err = true;
- }
- }
- char *bitmap = TCBITMAPNEW(100);
- for(int j = 0; j < 100; j++){
- if(j % 3 == 0) TCBITMAPON(bitmap, j);
- if(j % 5 == 0) TCBITMAPOFF(bitmap, j);
- }
- for(int j = 0; j < 100; j++){
- if(j % 5 == 0){
- if(TCBITMAPCHECK(bitmap, j)) err = true;
- } else if(j % 3 == 0){
- if(!TCBITMAPCHECK(bitmap, j)) err = true;
- }
- }
- TCBITMAPDEL(bitmap);
- buf = tcmalloc(i / 8 + 2);
- TCBITSTRM strm;
- TCBITSTRMINITW(strm, buf);
- for(int j = 0; j < i; j++){
- int sign = j % 3 == 0 || j % 7 == 0;
- TCBITSTRMCAT(strm, sign);
- }
- TCBITSTRMSETEND(strm);
- int bnum = TCBITSTRMNUM(strm);
- if(bnum != i) err = true;
- TCBITSTRMINITR(strm, buf, bsiz);
- for(int j = 0; j < i; j++){
- int sign;
- TCBITSTRMREAD(strm, sign);
- if(sign != (j % 3 == 0 || j % 7 == 0)) err = true;
- }
- free(buf);
- }
- if(rnum > 250 && i % (rnum / 250) == 0){
- putchar('.');
- fflush(stdout);
- if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
- }
- }
- iprintf("time: %.3f\n", tctime() - stime);
- if(err){
- iprintf("error\n\n");
- return 1;
- }
- iprintf("ok\n\n");
- return 0;
-}
-
-
-/* perform wicked command */
-static int procwicked(int rnum){
- iprintf("<Wicked Writing Test>\n rnum=%d\n\n", rnum);
- double stime = tctime();
- TCMPOOL *mpool = tcmpoolglobal();
- TCXSTR *xstr = myrand(2) > 0 ? tcxstrnew() : tcxstrnew2("hello world");
- tcmpoolputxstr(mpool, xstr);
- TCLIST *list = myrand(2) > 0 ? tclistnew() : tclistnew2(myrand(rnum) + rnum / 2);
- tcmpoolputlist(mpool, list);
- TCMAP *map = myrand(2) > 0 ? tcmapnew() : tcmapnew2(myrand(rnum) + rnum / 2);
- tcmpoolputmap(mpool, map);
- TCMDB *mdb = myrand(2) > 0 ? tcmdbnew() : tcmdbnew2(myrand(rnum) + rnum / 2);
- tcmpoolput(mpool, mdb, (void (*)(void*))tcmdbdel);
- for(int i = 1; i <= rnum; i++){
- char kbuf[RECBUFSIZ];
- int ksiz = sprintf(kbuf, "%d", myrand(i));
- char vbuf[RECBUFSIZ];
- int vsiz = sprintf(vbuf, "%d", myrand(i));
- char *tmp;
- switch(myrand(69)){
- case 0:
- putchar('0');
- tcxstrcat(xstr, kbuf, ksiz);
- break;
- case 1:
- putchar('1');
- tcxstrcat2(xstr, kbuf);
- break;
- case 2:
- putchar('2');
- if(myrand(rnum / 100 + 1) == 0) tcxstrclear(xstr);
- break;
- case 3:
- putchar('3');
- tcxstrprintf(xstr, "[%s:%d]", kbuf, i);
- break;
- case 4:
- putchar('4');
- tclistpush(list, kbuf, ksiz);
- break;
- case 5:
- putchar('5');
- tclistpush2(list, kbuf);
- break;
- case 6:
- putchar('6');
- tmp = tcmemdup(kbuf, ksiz);
- tclistpushmalloc(list, tmp, strlen(tmp));
- break;
- case 7:
- putchar('7');
- if(myrand(10) == 0) free(tclistpop(list, &ksiz));
- break;
- case 8:
- putchar('8');
- if(myrand(10) == 0) free(tclistpop2(list));
- break;
- case 9:
- putchar('9');
- tclistunshift(list, kbuf, ksiz);
- break;
- case 10:
- putchar('A');
- tclistunshift2(list, kbuf);
- break;
- case 11:
- putchar('B');
- if(myrand(10) == 0) free(tclistshift(list, &ksiz));
- break;
- case 12:
- putchar('C');
- if(myrand(10) == 0) free(tclistshift2(list));
- break;
- case 13:
- putchar('D');
- tclistinsert(list, i / 10, kbuf, ksiz);
- break;
- case 14:
- putchar('E');
- tclistinsert2(list, i / 10, kbuf);
- break;
- case 15:
- putchar('F');
- if(myrand(10) == 0) free(tclistremove(list, i / 10, &ksiz));
- break;
- case 16:
- putchar('G');
- if(myrand(10) == 0) free(tclistremove2(list, i / 10));
- break;
- case 17:
- putchar('H');
- tclistover(list, i / 10, kbuf, ksiz);
- break;
- case 18:
- putchar('I');
- tclistover2(list, i / 10, kbuf);
- break;
- case 19:
- putchar('J');
- if(myrand(rnum / 1000 + 1) == 0) tclistsort(list);
- break;
- case 20:
- putchar('K');
- if(myrand(rnum / 1000 + 1) == 0) tclistsortci(list);
- break;
- case 21:
- putchar('L');
- if(myrand(rnum / 1000 + 1) == 0) tclistlsearch(list, kbuf, ksiz);
- break;
- case 22:
- putchar('M');
- if(myrand(rnum / 1000 + 1) == 0) tclistbsearch(list, kbuf, ksiz);
- break;
- case 23:
- putchar('N');
- if(myrand(rnum / 100 + 1) == 0) tclistclear(list);
- break;
- case 24:
- putchar('O');
- if(myrand(rnum / 100 + 1) == 0){
- int dsiz;
- char *dbuf = tclistdump(list, &dsiz);
- tclistdel(tclistload(dbuf, dsiz));
- free(dbuf);
- }
- break;
- case 25:
- putchar('P');
- if(myrand(100) == 0){
- if(myrand(2) == 0){
- for(int j = 0; j < tclistnum(list); j++){
- int rsiz;
- tclistval(list, j, &rsiz);
- }
- } else {
- for(int j = 0; j < tclistnum(list); j++){
- tclistval2(list, j);
- }
- }
- }
- break;
- case 26:
- putchar('Q');
- tcmapput(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 27:
- putchar('R');
- tcmapput2(map, kbuf, vbuf);
- break;
- case 28:
- putchar('S');
- tcmapput3(map, kbuf, ksiz, vbuf, vsiz, vbuf, vsiz);
- break;
- case 29:
- putchar('T');
- tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 30:
- putchar('U');
- tcmapputkeep2(map, kbuf, vbuf);
- break;
- case 31:
- putchar('V');
- tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
- break;
- case 32:
- putchar('W');
- tcmapputcat2(map, kbuf, vbuf);
- break;
- case 33:
- putchar('X');
- if(myrand(10) == 0) tcmapout(map, kbuf, ksiz);
- break;
- case 34:
- putchar('Y');
- if(myrand(10) == 0) tcmapout2(map, kbuf);
- break;
- case 35:
- putchar('Z');
- tcmapget3(map, kbuf, ksiz, &vsiz);
- break;
- case 36:
- putchar('a');
- tcmapmove(map, kbuf, ksiz, true);
- break;
- case 37:
- putchar('b');
- tcmapmove(map, kbuf, ksiz, false);
- break;
- case 38:
- putchar('c');
- tcmapmove2(map, kbuf, true);
- break;
- case 39:
- putchar('d');
- if(myrand(100) == 0) tcmapiterinit(map);
- break;
- case 40:
- putchar('e');
- tcmapiternext(map, &vsiz);
- break;
- case 41:
- putchar('f');
- tcmapiternext2(map);
- break;
- case 42:
- putchar('g');
- if(myrand(100) == 0){
- if(myrand(2) == 0){
- tclistdel(tcmapkeys(map));
- } else {
- tclistdel(tcmapvals(map));
- }
- }
- break;
- case 43:
- putchar('h');
- if(myrand(rnum / 100 + 1) == 0) tcmapclear(map);
- break;
- case 44:
- putchar('i');
- if(myrand(20) == 0) tcmapcutfront(map, myrand(10));
- break;
- case 45:
- putchar('j');
- if(myrand(rnum / 100 + 1) == 0){
- int dsiz;
- char *dbuf = tcmapdump(map, &dsiz);
- free(tcmaploadone(dbuf, dsiz, kbuf, ksiz, &vsiz));
- tcmapdel(tcmapload(dbuf, dsiz));
- free(dbuf);
- }
- break;
- case 46:
- putchar('k');
- tcmdbput(mdb, kbuf, ksiz, vbuf, vsiz);
- break;
- case 47:
- putchar('l');
- tcmdbput2(mdb, kbuf, vbuf);
- break;
- case 48:
- putchar('m');
- tcmdbputkeep(mdb, kbuf, ksiz, vbuf, vsiz);
- break;
- case 49:
- putchar('n');
- tcmdbputkeep2(mdb, kbuf, vbuf);
- break;
- case 50:
- putchar('o');
- tcmdbputcat(mdb, kbuf, ksiz, vbuf, vsiz);
- break;
- case 51:
- putchar('p');
- tcmdbputcat2(mdb, kbuf, vbuf);
- break;
- case 52:
- putchar('q');
- if(myrand(10) == 0) tcmdbout(mdb, kbuf, ksiz);
- break;
- case 53:
- putchar('r');
- if(myrand(10) == 0) tcmdbout2(mdb, kbuf);
- break;
- case 54:
- putchar('s');
- free(tcmdbget(mdb, kbuf, ksiz, &vsiz));
- break;
- case 55:
- putchar('t');
- free(tcmdbget3(mdb, kbuf, ksiz, &vsiz));
- break;
- case 56:
- putchar('u');
- if(myrand(100) == 0) tcmdbiterinit(mdb);
- break;
- case 57:
- putchar('v');
- free(tcmdbiternext(mdb, &vsiz));
- break;
- case 58:
- putchar('w');
- tmp = tcmdbiternext2(mdb);
- free(tmp);
- break;
- case 59:
- putchar('x');
- if(myrand(rnum / 100 + 1) == 0) tcmdbvanish(mdb);
- break;
- case 60:
- putchar('y');
- if(myrand(200) == 0) tcmdbcutfront(mdb, myrand(100));
- break;
- case 61:
- putchar('+');
- if(myrand(100) == 0) tcmpoolmalloc(mpool, 1);
- break;
- case 62:
- putchar('+');
- if(myrand(100) == 0) tcmpoolxstrnew(mpool);
- break;
- case 63:
- putchar('+');
- if(myrand(100) == 0) tcmpoollistnew(mpool);
- break;
- case 64:
- putchar('+');
- if(myrand(100) == 0) tcmpoolmapnew(mpool);
- break;
- default:
- putchar('@');
- if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
- break;
- }
- if(i % 50 == 0) iprintf(" (%08d)\n", i);
- }
- if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
- iprintf("time: %.3f\n", tctime() - stime);
- iprintf("ok\n\n");
- return 0;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The utility API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#include "tcutil.h"
-#include "myconf.h"
-
-
-/*************************************************************************************************
- * basic utilities
- *************************************************************************************************/
-
-
-/* String containing the version information. */
-const char *tcversion = _TC_VERSION;
-
-
-/* Call back function for handling a fatal error. */
-void (*tcfatalfunc)(const char *message) = NULL;
-
-
-/* Allocate a region on memory. */
-void *tcmalloc(size_t size){
- assert(size > 0 && size < INT_MAX);
- char *p = malloc(size);
- if(!p) tcmyfatal("out of memory");
- return p;
-}
-
-
-/* Allocate a nullified region on memory. */
-void *tccalloc(size_t nmemb, size_t size){
- assert(nmemb > 0 && size < INT_MAX && size > 0 && size < INT_MAX);
- char *p = calloc(nmemb, size);
- if(!p) tcmyfatal("out of memory");
- return p;
-}
-
-
-/* Re-allocate a region on memory. */
-void *tcrealloc(void *ptr, size_t size){
- assert(size >= 0 && size < INT_MAX);
- char *p = realloc(ptr, size);
- if(!p) tcmyfatal("out of memory");
- return p;
-}
-
-
-/* Duplicate a region on memory. */
-void *tcmemdup(const void *ptr, size_t size){
- assert(ptr && size >= 0);
- char *p;
- TCMALLOC(p, size + 1);
- memcpy(p, ptr, size);
- p[size] = '\0';
- return p;
-}
-
-
-/* Duplicate a string on memory. */
-char *tcstrdup(const void *str){
- assert(str);
- int size = strlen(str);
- char *p;
- TCMALLOC(p, size + 1);
- memcpy(p, str, size);
- p[size] = '\0';
- return p;
-}
-
-
-/* Free a region on memory. */
-void tcfree(void *ptr){
- free(ptr);
-}
-
-
-
-/*************************************************************************************************
- * extensible string
- *************************************************************************************************/
-
-
-#define TCXSTRUNIT 12 // allocation unit size of an extensible string
-
-
-/* private function prototypes */
-static void tcvxstrprintf(TCXSTR *xstr, const char *format, va_list ap);
-
-
-/* Create an extensible string object. */
-TCXSTR *tcxstrnew(void){
- TCXSTR *xstr;
- TCMALLOC(xstr, sizeof(*xstr));
- TCMALLOC(xstr->ptr, TCXSTRUNIT);
- xstr->size = 0;
- xstr->asize = TCXSTRUNIT;
- xstr->ptr[0] = '\0';
- return xstr;
-}
-
-
-/* Create an extensible string object from a character string. */
-TCXSTR *tcxstrnew2(const char *str){
- assert(str);
- TCXSTR *xstr;
- TCMALLOC(xstr, sizeof(*xstr));
- int size = strlen(str);
- int asize = tclmax(size + 1, TCXSTRUNIT);
- TCMALLOC(xstr->ptr, asize);
- xstr->size = size;
- xstr->asize = asize;
- memcpy(xstr->ptr, str, size + 1);
- return xstr;
-}
-
-
-/* Create an extensible string object with the initial allocation size. */
-TCXSTR *tcxstrnew3(int asiz){
- assert(asiz >= 0);
- asiz = tclmax(asiz, TCXSTRUNIT);
- TCXSTR *xstr;
- TCMALLOC(xstr, sizeof(*xstr));
- TCMALLOC(xstr->ptr, asiz);
- xstr->size = 0;
- xstr->asize = asiz;
- xstr->ptr[0] = '\0';
- return xstr;
-}
-
-
-/* Copy an extensible string object. */
-TCXSTR *tcxstrdup(const TCXSTR *xstr){
- assert(xstr);
- TCXSTR *nxstr;
- TCMALLOC(nxstr, sizeof(*nxstr));
- int asize = tclmax(xstr->size + 1, TCXSTRUNIT);
- TCMALLOC(nxstr->ptr, asize);
- nxstr->size = xstr->size;
- nxstr->asize = asize;
- memcpy(nxstr->ptr, xstr->ptr, xstr->size + 1);
- return nxstr;
-}
-
-
-/* Delete an extensible string object. */
-void tcxstrdel(TCXSTR *xstr){
- assert(xstr);
- free(xstr->ptr);
- free(xstr);
-}
-
-
-/* Concatenate a region to the end of an extensible string object. */
-void tcxstrcat(TCXSTR *xstr, const void *ptr, int size){
- assert(xstr && ptr && size >= 0);
- int nsize = xstr->size + size + 1;
- if(xstr->asize < nsize){
- while(xstr->asize < nsize){
- xstr->asize *= 2;
- if(xstr->asize < nsize) xstr->asize = nsize;
- }
- TCREALLOC(xstr->ptr, xstr->ptr, xstr->asize);
- }
- memcpy(xstr->ptr + xstr->size, ptr, size);
- xstr->size += size;
- xstr->ptr[xstr->size] = '\0';
-}
-
-
-/* Concatenate a character string to the end of an extensible string object. */
-void tcxstrcat2(TCXSTR *xstr, const char *str){
- assert(xstr && str);
- int size = strlen(str);
- int nsize = xstr->size + size + 1;
- if(xstr->asize < nsize){
- while(xstr->asize < nsize){
- xstr->asize *= 2;
- if(xstr->asize < nsize) xstr->asize = nsize;
- }
- TCREALLOC(xstr->ptr, xstr->ptr, xstr->asize);
- }
- memcpy(xstr->ptr + xstr->size, str, size + 1);
- xstr->size += size;
-}
-
-
-/* Get the pointer of the region of an extensible string object. */
-const void *tcxstrptr(const TCXSTR *xstr){
- assert(xstr);
- return xstr->ptr;
-}
-
-
-/* Get the size of the region of an extensible string object. */
-int tcxstrsize(const TCXSTR *xstr){
- assert(xstr);
- return xstr->size;
-}
-
-
-/* Clear an extensible string object. */
-void tcxstrclear(TCXSTR *xstr){
- assert(xstr);
- xstr->size = 0;
- xstr->ptr[0] = '\0';
-}
-
-
-/* Convert an extensible string object into a usual allocated region. */
-void *tcxstrtomalloc(TCXSTR *xstr){
- assert(xstr);
- char *ptr;
- ptr = xstr->ptr;
- free(xstr);
- return ptr;
-}
-
-
-/* Create an extensible string object from an allocated region. */
-TCXSTR *tcxstrfrommalloc(void *ptr, int size){
- TCXSTR *xstr;
- TCMALLOC(xstr, sizeof(*xstr));
- TCREALLOC(xstr->ptr, ptr, size + 1);
- xstr->ptr[size] = '\0';
- xstr->size = size;
- xstr->asize = size;
- return xstr;
-}
-
-
-/* Perform formatted output into an extensible string object. */
-void tcxstrprintf(TCXSTR *xstr, const char *format, ...){
- assert(xstr && format);
- va_list ap;
- va_start(ap, format);
- tcvxstrprintf(xstr, format, ap);
- va_end(ap);
-}
-
-
-/* Allocate a formatted string on memory. */
-char *tcsprintf(const char *format, ...){
- assert(format);
- TCXSTR *xstr = tcxstrnew();
- va_list ap;
- va_start(ap, format);
- tcvxstrprintf(xstr, format, ap);
- va_end(ap);
- return tcxstrtomalloc(xstr);
-}
-
-
-/* Perform formatted output into an extensible string object. */
-static void tcvxstrprintf(TCXSTR *xstr, const char *format, va_list ap){
- assert(xstr && format);
- while(*format != '\0'){
- if(*format == '%'){
- char cbuf[TCNUMBUFSIZ];
- cbuf[0] = '%';
- int cblen = 1;
- int lnum = 0;
- format++;
- while(strchr("0123456789 .+-hlLz", *format) && *format != '\0' &&
- cblen < TCNUMBUFSIZ - 1){
- if(*format == 'l' || *format == 'L') lnum++;
- cbuf[cblen++] = *(format++);
- }
- cbuf[cblen++] = *format;
- cbuf[cblen] = '\0';
- int tlen;
- char *tmp, tbuf[TCNUMBUFSIZ*2];
- switch(*format){
- case 's':
- tmp = va_arg(ap, char *);
- if(!tmp) tmp = "(null)";
- tcxstrcat2(xstr, tmp);
- break;
- case 'd':
- if(lnum >= 2){
- tlen = sprintf(tbuf, cbuf, va_arg(ap, long long));
- } else if(lnum >= 1){
- tlen = sprintf(tbuf, cbuf, va_arg(ap, long));
- } else {
- tlen = sprintf(tbuf, cbuf, va_arg(ap, int));
- }
- TCXSTRCAT(xstr, tbuf, tlen);
- break;
- case 'o': case 'u': case 'x': case 'X': case 'c':
- if(lnum >= 2){
- tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned long long));
- } else if(lnum >= 1){
- tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned long));
- } else {
- tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned int));
- }
- TCXSTRCAT(xstr, tbuf, tlen);
- break;
- case 'e': case 'E': case 'f': case 'g': case 'G':
- if(lnum >= 1){
- tlen = sprintf(tbuf, cbuf, va_arg(ap, long double));
- } else {
- tlen = sprintf(tbuf, cbuf, va_arg(ap, double));
- }
- TCXSTRCAT(xstr, tbuf, tlen);
- break;
- case '@':
- tmp = va_arg(ap, char *);
- if(!tmp) tmp = "(null)";
- while(*tmp){
- switch(*tmp){
- case '&': TCXSTRCAT(xstr, "&", 5); break;
- case '<': TCXSTRCAT(xstr, "<", 4); break;
- case '>': TCXSTRCAT(xstr, ">", 4); break;
- case '"': TCXSTRCAT(xstr, """, 6); break;
- default:
- if(!((*tmp >= 0 && *tmp <= 0x8) || (*tmp >= 0x0e && *tmp <= 0x1f)))
- TCXSTRCAT(xstr, tmp, 1);
- break;
- }
- tmp++;
- }
- break;
- case '?':
- tmp = va_arg(ap, char *);
- if(!tmp) tmp = "(null)";
- while(*tmp){
- unsigned char c = *(unsigned char *)tmp;
- if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){
- TCXSTRCAT(xstr, tmp, 1);
- } else {
- tlen = sprintf(tbuf, "%%%02X", c);
- TCXSTRCAT(xstr, tbuf, tlen);
- }
- tmp++;
- }
- break;
- case '%':
- TCXSTRCAT(xstr, "%", 1);
- break;
- }
- } else {
- TCXSTRCAT(xstr, format, 1);
- }
- format++;
- }
-}
-
-
-
-/*************************************************************************************************
- * array list
- *************************************************************************************************/
-
-
-#define TCLISTUNIT 64 // allocation unit number of a list handle
-
-
-/* private function prototypes */
-static int tclistelemcmp(const void *a, const void *b);
-static int tclistelemcmpci(const void *a, const void *b);
-
-
-/* Create a list object. */
-TCLIST *tclistnew(void){
- TCLIST *list;
- TCMALLOC(list, sizeof(*list));
- list->anum = TCLISTUNIT;
- TCMALLOC(list->array, sizeof(list->array[0]) * list->anum);
- list->start = 0;
- list->num = 0;
- return list;
-}
-
-
-/* Create a list object. */
-TCLIST *tclistnew2(int anum){
- TCLIST *list;
- TCMALLOC(list, sizeof(*list));
- if(anum < 1) anum = 1;
- list->anum = anum;
- TCMALLOC(list->array, sizeof(list->array[0]) * list->anum);
- list->start = 0;
- list->num = 0;
- return list;
-}
-
-
-/* Copy a list object. */
-TCLIST *tclistdup(const TCLIST *list){
- assert(list);
- int num = list->num;
- if(num < 1) tclistnew();
- const TCLISTDATUM *array = list->array + list->start;
- TCLIST *nlist;
- TCMALLOC(nlist, sizeof(*nlist));
- TCLISTDATUM *narray;
- TCMALLOC(narray, sizeof(list->array[0]) * tclmax(num, 1));
- for(int i = 0; i < num; i++){
- int size = array[i].size;
- TCMALLOC(narray[i].ptr, tclmax(size + 1, TCXSTRUNIT));
- memcpy(narray[i].ptr, array[i].ptr, size + 1);
- narray[i].size = array[i].size;
- }
- nlist->anum = num;
- nlist->array = narray;
- nlist->start = 0;
- nlist->num = num;
- return nlist;
-}
-
-
-/* Delete a list object. */
-void tclistdel(TCLIST *list){
- assert(list);
- TCLISTDATUM *array = list->array;
- int end = list->start + list->num;
- for(int i = list->start; i < end; i++){
- free(array[i].ptr);
- }
- free(list->array);
- free(list);
-}
-
-
-/* Get the number of elements of a list object. */
-int tclistnum(const TCLIST *list){
- assert(list);
- return list->num;
-}
-
-
-/* Get the pointer to the region of an element of a list object. */
-const void *tclistval(const TCLIST *list, int index, int *sp){
- assert(list && index >= 0 && sp);
- if(index >= list->num) return NULL;
- index += list->start;
- *sp = list->array[index].size;
- return list->array[index].ptr;
-}
-
-
-/* Get the string of an element of a list object. */
-const char *tclistval2(const TCLIST *list, int index){
- assert(list && index >= 0);
- if(index >= list->num) return NULL;
- index += list->start;
- return list->array[index].ptr;
-}
-
-
-/* Add an element at the end of a list object. */
-void tclistpush(TCLIST *list, const void *ptr, int size){
- assert(list && ptr && size >= 0);
- int index = list->start + list->num;
- if(index >= list->anum){
- list->anum += list->num + 1;
- TCREALLOC(list->array, list->array, list->anum * sizeof(list->array[0]));
- }
- TCLISTDATUM *array = list->array;
- TCMALLOC(array[index].ptr, tclmax(size + 1, TCXSTRUNIT));
- memcpy(array[index].ptr, ptr, size);
- array[index].ptr[size] = '\0';
- array[index].size = size;
- list->num++;
-}
-
-
-/* Add a string element at the end of a list object. */
-void tclistpush2(TCLIST *list, const char *str){
- assert(list && str);
- int index = list->start + list->num;
- if(index >= list->anum){
- list->anum += list->num + 1;
- TCREALLOC(list->array, list->array, list->anum * sizeof(list->array[0]));
- }
- int size = strlen(str);
- TCLISTDATUM *array = list->array;
- TCMALLOC(array[index].ptr, tclmax(size + 1, TCXSTRUNIT));
- memcpy(array[index].ptr, str, size + 1);
- array[index].size = size;
- list->num++;
-}
-
-
-/* Add an allocated element at the end of a list object. */
-void tclistpushmalloc(TCLIST *list, void *ptr, int size){
- assert(list && ptr && size >= 0);
- int index = list->start + list->num;
- if(index >= list->anum){
- list->anum += list->num + 1;
- TCREALLOC(list->array, list->array, list->anum * sizeof(list->array[0]));
- }
- TCLISTDATUM *array = list->array;
- TCREALLOC(array[index].ptr, ptr, size + 1);
- array[index].ptr[size] = '\0';
- array[index].size = size;
- list->num++;
-}
-
-
-/* Remove an element of the end of a list object. */
-void *tclistpop(TCLIST *list, int *sp){
- assert(list && sp);
- if(list->num < 1) return NULL;
- int index = list->start + list->num - 1;
- list->num--;
- *sp = list->array[index].size;
- return list->array[index].ptr;
-}
-
-
-/* Remove a string element of the end of a list object. */
-char *tclistpop2(TCLIST *list){
- assert(list);
- if(list->num < 1) return NULL;
- int index = list->start + list->num - 1;
- list->num--;
- return list->array[index].ptr;
-}
-
-
-/* Add an element at the top of a list object. */
-void tclistunshift(TCLIST *list, const void *ptr, int size){
- assert(list && ptr && size >= 0);
- if(list->start < 1){
- if(list->start + list->num >= list->anum){
- list->anum += list->num + 1;
- TCREALLOC(list->array, list->array, list->anum * sizeof(list->array[0]));
- }
- list->start = list->anum - list->num;
- memmove(list->array + list->start, list->array, list->num * sizeof(list->array[0]));
- }
- int index = list->start - 1;
- TCMALLOC(list->array[index].ptr, tclmax(size + 1, TCXSTRUNIT));
- memcpy(list->array[index].ptr, ptr, size);
- list->array[index].ptr[size] = '\0';
- list->array[index].size = size;
- list->start--;
- list->num++;
-}
-
-
-/* Add a string element at the top of a list object. */
-void tclistunshift2(TCLIST *list, const char *str){
- assert(list && str);
- if(list->start < 1){
- if(list->start + list->num >= list->anum){
- list->anum += list->num + 1;
- TCREALLOC(list->array, list->array, list->anum * sizeof(list->array[0]));
- }
- list->start = list->anum - list->num;
- memmove(list->array + list->start, list->array, list->num * sizeof(list->array[0]));
- }
- int index = list->start - 1;
- int size = strlen(str);
- TCMALLOC(list->array[index].ptr, tclmax(size + 1, TCXSTRUNIT));
- memcpy(list->array[index].ptr, str, size + 1);
- list->array[index].size = size;
- list->start--;
- list->num++;
-}
-
-
-/* Remove an element of the top of a list object. */
-void *tclistshift(TCLIST *list, int *sp){
- assert(list && sp);
- if(list->num < 1) return NULL;
- int index = list->start;
- list->start++;
- list->num--;
- *sp = list->array[index].size;
- void *rv = list->array[index].ptr;
- if((list->start & 0xff) == 0 && list->start > (list->num >> 1)){
- memmove(list->array, list->array + list->start, list->num * sizeof(list->array[0]));
- list->start = 0;
- }
- return rv;
-}
-
-
-/* Remove a string element of the top of a list object. */
-char *tclistshift2(TCLIST *list){
- assert(list);
- if(list->num < 1) return NULL;
- int index = list->start;
- list->start++;
- list->num--;
- void *rv = list->array[index].ptr;
- if((list->start & 0xff) == 0 && list->start > (list->num >> 1)){
- memmove(list->array, list->array + list->start, list->num * sizeof(list->array[0]));
- list->start = 0;
- }
- return rv;
-}
-
-
-/* Add an element at the specified location of a list object. */
-void tclistinsert(TCLIST *list, int index, const void *ptr, int size){
- assert(list && index >= 0 && ptr && size >= 0);
- if(index > list->num) return;
- index += list->start;
- if(list->start + list->num >= list->anum){
- list->anum += list->num + 1;
- TCREALLOC(list->array, list->array, list->anum * sizeof(list->array[0]));
- }
- memmove(list->array + index + 1, list->array + index,
- sizeof(list->array[0]) * (list->start + list->num - index));
- TCMALLOC(list->array[index].ptr, tclmax(size + 1, TCXSTRUNIT));
- memcpy(list->array[index].ptr, ptr, size);
- list->array[index].ptr[size] = '\0';
- list->array[index].size = size;
- list->num++;
-}
-
-
-/* Add a string element at the specified location of a list object. */
-void tclistinsert2(TCLIST *list, int index, const char *str){
- assert(list && index >= 0 && str);
- if(index > list->num) return;
- index += list->start;
- if(list->start + list->num >= list->anum){
- list->anum += list->num + 1;
- TCREALLOC(list->array, list->array, list->anum * sizeof(list->array[0]));
- }
- memmove(list->array + index + 1, list->array + index,
- sizeof(list->array[0]) * (list->start + list->num - index));
- int size = strlen(str);
- TCMALLOC(list->array[index].ptr, tclmax(size + 1, TCXSTRUNIT));
- memcpy(list->array[index].ptr, str, size);
- list->array[index].ptr[size] = '\0';
- list->array[index].size = size;
- list->num++;
-}
-
-
-/* Remove an element at the specified location of a list object. */
-void *tclistremove(TCLIST *list, int index, int *sp){
- assert(list && index >= 0 && sp);
- if(index >= list->num) return NULL;
- index += list->start;
- char *ptr = list->array[index].ptr;
- *sp = list->array[index].size;
- list->num--;
- memmove(list->array + index, list->array + index + 1,
- sizeof(list->array[0]) * (list->start + list->num - index));
- return ptr;
-}
-
-
-/* Remove a string element at the specified location of a list object. */
-char *tclistremove2(TCLIST *list, int index){
- assert(list && index >= 0);
- if(index >= list->num) return NULL;
- index += list->start;
- char *ptr = list->array[index].ptr;
- list->num--;
- memmove(list->array + index, list->array + index + 1,
- sizeof(list->array[0]) * (list->start + list->num - index));
- return ptr;
-}
-
-
-/* Overwrite an element at the specified location of a list object. */
-void tclistover(TCLIST *list, int index, const void *ptr, int size){
- assert(list && index >= 0 && ptr && size >= 0);
- if(index >= list->num) return;
- index += list->start;
- if(size > list->array[index].size)
- TCREALLOC(list->array[index].ptr, list->array[index].ptr, size + 1);
- memcpy(list->array[index].ptr, ptr, size);
- list->array[index].size = size;
- list->array[index].ptr[size] = '\0';
-}
-
-
-/* Overwrite a string element at the specified location of a list object. */
-void tclistover2(TCLIST *list, int index, const char *str){
- assert(list && index >= 0 && str);
- if(index >= list->num) return;
- index += list->start;
- int size = strlen(str);
- if(size > list->array[index].size)
- TCREALLOC(list->array[index].ptr, list->array[index].ptr, size + 1);
- memcpy(list->array[index].ptr, str, size + 1);
- list->array[index].size = size;
-}
-
-
-/* Sort elements of a list object in lexical order. */
-void tclistsort(TCLIST *list){
- assert(list);
- qsort(list->array + list->start, list->num, sizeof(list->array[0]), tclistelemcmp);
-}
-
-
-/* Sort elements of a list object in case-insensitive lexical order. */
-void tclistsortci(TCLIST *list){
- assert(list);
- qsort(list->array + list->start, list->num, sizeof(list->array[0]), tclistelemcmpci);
-}
-
-
-/* Sort elements of a list object by an arbitrary comparison function. */
-void tclistsortex(TCLIST *list, int (*cmp)(const TCLISTDATUM *, const TCLISTDATUM *)){
- assert(list && cmp);
- qsort(list->array + list->start, list->num, sizeof(list->array[0]),
- (int (*)(const void *, const void *))cmp);
-}
-
-
-/* Search a list object for an element using liner search. */
-int tclistlsearch(const TCLIST *list, const void *ptr, int size){
- assert(list && ptr && size >= 0);
- int end = list->start + list->num;
- for(int i = list->start; i < end; i++){
- if(list->array[i].size == size && !memcmp(list->array[i].ptr, ptr, size))
- return i - list->start;
- }
- return -1;
-}
-
-
-/* Search a list object for an element using binary search. */
-int tclistbsearch(const TCLIST *list, const void *ptr, int size){
- assert(list && ptr && size >= 0);
- TCLISTDATUM key;
- key.ptr = (char *)ptr;
- key.size = size;
- TCLISTDATUM *res = bsearch(&key, list->array + list->start,
- list->num, sizeof(list->array[0]), tclistelemcmp);
- return res ? res - list->array - list->start : -1;
-}
-
-
-/* Clear a list object. */
-void tclistclear(TCLIST *list){
- assert(list);
- TCLISTDATUM *array = list->array;
- int end = list->start + list->num;
- for(int i = list->start; i < end; i++){
- free(array[i].ptr);
- }
- list->start = 0;
- list->num = 0;
-}
-
-
-/* Serialize a list object into a byte array. */
-void *tclistdump(const TCLIST *list, int *sp){
- assert(list && sp);
- const TCLISTDATUM *array = list->array;
- int end = list->start + list->num;
- int tsiz = 0;
- for(int i = list->start; i < end; i++){
- tsiz += array[i].size + sizeof(int);
- }
- char *buf;
- TCMALLOC(buf, tsiz + 1);
- char *wp = buf;
- for(int i = list->start; i < end; i++){
- int step;
- TCSETVNUMBUF(step, wp, array[i].size);
- wp += step;
- memcpy(wp, array[i].ptr, array[i].size);
- wp += array[i].size;
- }
- *sp = wp - buf;
- return buf;
-}
-
-
-/* Create a list object from a serialized byte array. */
-TCLIST *tclistload(const void *ptr, int size){
- assert(ptr && size >= 0);
- TCLIST *list;
- TCMALLOC(list, sizeof(*list));
- int anum = size / sizeof(int) + 1;
- TCLISTDATUM *array;
- TCMALLOC(array, sizeof(array[0]) * anum);
- int num = 0;
- const char *rp = ptr;
- const char *ep = (char *)ptr + size;
- while(rp < ep){
- int step, vsiz;
- TCREADVNUMBUF(rp, vsiz, step);
- rp += step;
- if(num >= anum){
- anum *= 2;
- TCREALLOC(array, array, anum * sizeof(array[0]));
- }
- TCMALLOC(array[num].ptr, tclmax(vsiz + 1, TCXSTRUNIT));
- memcpy(array[num].ptr, rp, vsiz);
- array[num].ptr[vsiz] = '\0';
- array[num].size = vsiz;
- num++;
- rp += vsiz;
- }
- list->anum = anum;
- list->array = array;
- list->start = 0;
- list->num = num;
- return list;
-}
-
-
-/* Compare two list elements in lexical order.
- `a' specifies the pointer to one element.
- `b' specifies the pointer to the other element.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-static int tclistelemcmp(const void *a, const void *b){
- assert(a && b);
- unsigned char *ao = (unsigned char *)((TCLISTDATUM *)a)->ptr;
- unsigned char *bo = (unsigned char *)((TCLISTDATUM *)b)->ptr;
- int size = (((TCLISTDATUM *)a)->size < ((TCLISTDATUM *)b)->size) ?
- ((TCLISTDATUM *)a)->size : ((TCLISTDATUM *)b)->size;
- for(int i = 0; i < size; i++){
- if(ao[i] > bo[i]) return 1;
- if(ao[i] < bo[i]) return -1;
- }
- return ((TCLISTDATUM *)a)->size - ((TCLISTDATUM *)b)->size;
-}
-
-
-/* Compare two list elements in case-insensitive lexical order..
- `a' specifies the pointer to one element.
- `b' specifies the pointer to the other element.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-static int tclistelemcmpci(const void *a, const void *b){
- assert(a && b);
- TCLISTDATUM *ap = (TCLISTDATUM *)a;
- TCLISTDATUM *bp = (TCLISTDATUM *)b;
- unsigned char *ao = (unsigned char *)ap->ptr;
- unsigned char *bo = (unsigned char *)bp->ptr;
- int size = (ap->size < bp->size) ? ap->size : bp->size;
- for(int i = 0; i < size; i++){
- int ac = ao[i];
- bool ab = false;
- if(ac >= 'A' && ac <= 'Z'){
- ac += 'a' - 'A';
- ab = true;
- }
- int bc = bo[i];
- bool bb = false;
- if(bc >= 'A' && bc <= 'Z'){
- bc += 'a' - 'A';
- bb = true;
- }
- if(ac > bc) return 1;
- if(ac < bc) return -1;
- if(!ab && bb) return 1;
- if(ab && !bb) return -1;
- }
- return ap->size - bp->size;
-}
-
-
-
-/*************************************************************************************************
- * hash map
- *************************************************************************************************/
-
-
-#define TCMAPBNUM 4093 // allocation unit number of a map
-#define TCMAPCSUNIT 52 // small allocation unit size of map concatenation
-#define TCMAPCBUNIT 252 // big allocation unit size of map concatenation
-
-/* get the first hash value */
-#define TCMAPHASH1(TC_res, TC_kbuf, TC_ksiz) \
- do { \
- const unsigned char *_TC_p = (const unsigned char *)(TC_kbuf); \
- int _TC_ksiz = TC_ksiz; \
- for((TC_res) = 19780211; _TC_ksiz--;){ \
- (TC_res) = ((TC_res) << 5) + ((TC_res) << 2) + (TC_res) + *(_TC_p)++; \
- } \
- } while(false)
-
-/* get the second hash value */
-#define TCMAPHASH2(TC_res, TC_kbuf, TC_ksiz) \
- do { \
- const unsigned char *_TC_p = (const unsigned char *)(TC_kbuf) + TC_ksiz - 1; \
- int _TC_ksiz = TC_ksiz; \
- for((TC_res) = 0x13579bdf; _TC_ksiz--;){ \
- (TC_res) = ((TC_res) << 5) - (TC_res) + *(_TC_p)--; \
- } \
- } while(false)
-
-/* get the size of padding bytes for pointer alignment */
-#define TCALIGNPAD(TC_hsiz) \
- (((TC_hsiz | ~-(int)sizeof(void *)) + 1) - TC_hsiz)
-
-/* compare two keys */
-#define TCKEYCMP(TC_abuf, TC_asiz, TC_bbuf, TC_bsiz) \
- ((TC_asiz > TC_bsiz) ? 1 : (TC_asiz < TC_bsiz) ? -1 : memcmp(TC_abuf, TC_bbuf, TC_asiz))
-
-
-/* Create a map object. */
-TCMAP *tcmapnew(void){
- return tcmapnew2(TCMAPBNUM);
-}
-
-
-/* Create a map object with specifying the number of the buckets. */
-TCMAP *tcmapnew2(uint32_t bnum){
- if(bnum < 1) bnum = 1;
- TCMAP *map;
- TCMALLOC(map, sizeof(*map));
- TCMAPREC **buckets;
- TCCALLOC(buckets, bnum, sizeof(map->buckets[0]));
- map->buckets = buckets;
- map->first = NULL;
- map->last = NULL;
- map->cur = NULL;
- map->bnum = bnum;
- map->rnum = 0;
- map->msiz = 0;
- return map;
-}
-
-
-/* Copy a map object. */
-TCMAP *tcmapdup(const TCMAP *map){
- assert(map);
- TCMAP *nmap = tcmapnew2(tclmax(tclmax(map->bnum, map->rnum), TCMAPBNUM));
- TCMAPREC *cur = map->cur;
- const char *kbuf;
- int ksiz;
- ((TCMAP *)map)->cur = map->first;
- while((kbuf = tcmapiternext((TCMAP *)map, &ksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- tcmapputkeep(nmap, kbuf, ksiz, vbuf, vsiz);
- }
- ((TCMAP *)map)->cur = cur;
- return nmap;
-}
-
-
-/* Close a map object. */
-void tcmapdel(TCMAP *map){
- assert(map);
- TCMAPREC *rec = map->first;
- while(rec){
- TCMAPREC *next = rec->next;
- free(rec);
- rec = next;
- }
- free(map->buckets);
- free(map);
-}
-
-
-/* Store a record into a map object. */
-void tcmapput(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(map && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- int bidx = hash % map->bnum;
- TCMAPREC *rec = map->buckets[bidx];
- TCMAPREC **entp = map->buckets + bidx;
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- entp = &(rec->left);
- rec = rec->left;
- } else if(hash < rec->hash){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- entp = &(rec->left);
- rec = rec->left;
- } else if(kcmp > 0){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- map->msiz += vsiz - rec->vsiz;
- int psiz = TCALIGNPAD(ksiz);
- if(vsiz > rec->vsiz){
- TCMAPREC *old = rec;
- TCREALLOC(rec, rec, sizeof(*rec) + ksiz + psiz + vsiz + 1);
- if(rec != old){
- if(map->first == old) map->first = rec;
- if(map->last == old) map->last = rec;
- if(map->cur == old) map->cur = rec;
- if(*entp == old) *entp = rec;
- if(rec->prev) rec->prev->next = rec;
- if(rec->next) rec->next->prev = rec;
- dbuf = (char *)rec + sizeof(*rec);
- }
- }
- memcpy(dbuf + ksiz + psiz, vbuf, vsiz);
- dbuf[ksiz+psiz+vsiz] = '\0';
- rec->vsiz = vsiz;
- return;
- }
- }
- }
- int psiz = TCALIGNPAD(ksiz);
- map->msiz += ksiz + vsiz;
- TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + vsiz + 1);
- char *dbuf = (char *)rec + sizeof(*rec);
- memcpy(dbuf, kbuf, ksiz);
- dbuf[ksiz] = '\0';
- rec->ksiz = ksiz;
- memcpy(dbuf + ksiz + psiz, vbuf, vsiz);
- dbuf[ksiz+psiz+vsiz] = '\0';
- rec->vsiz = vsiz;
- rec->hash = hash;
- rec->left = NULL;
- rec->right = NULL;
- rec->prev = map->last;
- rec->next = NULL;
- *entp = rec;
- if(!map->first) map->first = rec;
- if(map->last) map->last->next = rec;
- map->last = rec;
- map->rnum++;
-}
-
-
-/* Store a string record into a map object. */
-void tcmapput2(TCMAP *map, const char *kstr, const char *vstr){
- assert(map && kstr && vstr);
- tcmapput(map, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Store a record of the value of two regions into a map object. */
-void tcmapput3(TCMAP *map, const char *kbuf, int ksiz,
- const void *fvbuf, int fvsiz, const char *lvbuf, int lvsiz){
- assert(map && kbuf && ksiz >= 0 && fvbuf && fvsiz >= 0 && lvbuf && lvsiz >= 0);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- int bidx = hash % map->bnum;
- TCMAPREC *rec = map->buckets[bidx];
- TCMAPREC **entp = map->buckets + bidx;
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- entp = &(rec->left);
- rec = rec->left;
- } else if(hash < rec->hash){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- entp = &(rec->left);
- rec = rec->left;
- } else if(kcmp > 0){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- int vsiz = fvsiz + lvsiz;
- map->msiz += vsiz - rec->vsiz;
- int psiz = TCALIGNPAD(ksiz);
- ksiz += psiz;
- if(vsiz > rec->vsiz){
- TCMAPREC *old = rec;
- TCREALLOC(rec, rec, sizeof(*rec) + ksiz + vsiz + 1);
- if(rec != old){
- if(map->first == old) map->first = rec;
- if(map->last == old) map->last = rec;
- if(map->cur == old) map->cur = rec;
- if(*entp == old) *entp = rec;
- if(rec->prev) rec->prev->next = rec;
- if(rec->next) rec->next->prev = rec;
- dbuf = (char *)rec + sizeof(*rec);
- }
- }
- memcpy(dbuf + ksiz, fvbuf, fvsiz);
- memcpy(dbuf + ksiz + fvsiz, lvbuf, lvsiz);
- dbuf[ksiz+vsiz] = '\0';
- rec->vsiz = vsiz;
- return;
- }
- }
- }
- int vsiz = fvsiz + lvsiz;
- int psiz = TCALIGNPAD(ksiz);
- map->msiz += ksiz + vsiz;
- TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + vsiz + 1);
- char *dbuf = (char *)rec + sizeof(*rec);
- memcpy(dbuf, kbuf, ksiz);
- dbuf[ksiz] = '\0';
- rec->ksiz = ksiz;
- ksiz += psiz;
- memcpy(dbuf + ksiz, fvbuf, fvsiz);
- memcpy(dbuf + ksiz + fvsiz, lvbuf, lvsiz);
- dbuf[ksiz+vsiz] = '\0';
- rec->vsiz = vsiz;
- rec->hash = hash;
- rec->left = NULL;
- rec->right = NULL;
- rec->prev = map->last;
- rec->next = NULL;
- *entp = rec;
- if(!map->first) map->first = rec;
- if(map->last) map->last->next = rec;
- map->last = rec;
- map->rnum++;
-}
-
-
-/* Store a new record into a map object. */
-bool tcmapputkeep(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(map && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- int bidx = hash % map->bnum;
- TCMAPREC *rec = map->buckets[bidx];
- TCMAPREC **entp = map->buckets + bidx;
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- entp = &(rec->left);
- rec = rec->left;
- } else if(hash < rec->hash){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- entp = &(rec->left);
- rec = rec->left;
- } else if(kcmp > 0){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- return false;
- }
- }
- }
- int psiz = TCALIGNPAD(ksiz);
- map->msiz += ksiz + vsiz;
- TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + vsiz + 1);
- char *dbuf = (char *)rec + sizeof(*rec);
- memcpy(dbuf, kbuf, ksiz);
- dbuf[ksiz] = '\0';
- rec->ksiz = ksiz;
- memcpy(dbuf + ksiz + psiz, vbuf, vsiz);
- dbuf[ksiz+psiz+vsiz] = '\0';
- rec->vsiz = vsiz;
- rec->hash = hash;
- rec->left = NULL;
- rec->right = NULL;
- rec->prev = map->last;
- rec->next = NULL;
- *entp = rec;
- if(!map->first) map->first = rec;
- if(map->last) map->last->next = rec;
- map->last = rec;
- map->rnum++;
- return true;
-}
-
-
-/* Store a new string record into a map object.
- `map' specifies the map object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tcmapputkeep2(TCMAP *map, const char *kstr, const char *vstr){
- assert(map && kstr && vstr);
- return tcmapputkeep(map, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Concatenate a value at the end of the value of the existing record in a map object. */
-void tcmapputcat(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(map && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- int bidx = hash % map->bnum;
- TCMAPREC *rec = map->buckets[bidx];
- TCMAPREC **entp = map->buckets + bidx;
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- entp = &(rec->left);
- rec = rec->left;
- } else if(hash < rec->hash){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- entp = &(rec->left);
- rec = rec->left;
- } else if(kcmp > 0){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- map->msiz += vsiz;
- int psiz = TCALIGNPAD(ksiz);
- int asiz = sizeof(*rec) + ksiz + psiz + rec->vsiz + vsiz + 1;
- int unit = (asiz <= TCMAPCSUNIT) ? TCMAPCSUNIT : TCMAPCBUNIT;
- asiz = (asiz - 1) + unit - (asiz - 1) % unit;
- TCMAPREC *old = rec;
- TCREALLOC(rec, rec, asiz);
- if(rec != old){
- if(map->first == old) map->first = rec;
- if(map->last == old) map->last = rec;
- if(map->cur == old) map->cur = rec;
- if(*entp == old) *entp = rec;
- if(rec->prev) rec->prev->next = rec;
- if(rec->next) rec->next->prev = rec;
- dbuf = (char *)rec + sizeof(*rec);
- }
- memcpy(dbuf + ksiz + psiz + rec->vsiz, vbuf, vsiz);
- dbuf[ksiz+psiz+rec->vsiz+vsiz] = '\0';
- rec->vsiz += vsiz;
- return;
- }
- }
- }
- int psiz = TCALIGNPAD(ksiz);
- int asiz = sizeof(*rec) + ksiz + psiz + vsiz + 1;
- int unit = (asiz <= TCMAPCSUNIT) ? TCMAPCSUNIT : TCMAPCBUNIT;
- asiz = (asiz - 1) + unit - (asiz - 1) % unit;
- map->msiz += ksiz + vsiz;
- TCMALLOC(rec, asiz);
- char *dbuf = (char *)rec + sizeof(*rec);
- memcpy(dbuf, kbuf, ksiz);
- dbuf[ksiz] = '\0';
- rec->ksiz = ksiz;
- memcpy(dbuf + ksiz + psiz, vbuf, vsiz);
- dbuf[ksiz+psiz+vsiz] = '\0';
- rec->vsiz = vsiz;
- rec->hash = hash;
- rec->left = NULL;
- rec->right = NULL;
- rec->prev = map->last;
- rec->next = NULL;
- *entp = rec;
- if(!map->first) map->first = rec;
- if(map->last) map->last->next = rec;
- map->last = rec;
- map->rnum++;
-}
-
-
-/* Concatenate a string value at the end of the value of the existing record in a map object. */
-void tcmapputcat2(TCMAP *map, const char *kstr, const char *vstr){
- assert(map && kstr && vstr);
- tcmapputcat(map, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Remove a record of a map object. */
-bool tcmapout(TCMAP *map, const void *kbuf, int ksiz){
- assert(map && kbuf && ksiz >= 0);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- int bidx = hash % map->bnum;
- TCMAPREC *rec = map->buckets[bidx];
- TCMAPREC **entp = map->buckets + bidx;
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- entp = &(rec->left);
- rec = rec->left;
- } else if(hash < rec->hash){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- entp = &(rec->left);
- rec = rec->left;
- } else if(kcmp > 0){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- map->rnum--;
- map->msiz -= rec->ksiz + rec->vsiz;
- if(rec->prev) rec->prev->next = rec->next;
- if(rec->next) rec->next->prev = rec->prev;
- if(rec == map->first) map->first = rec->next;
- if(rec == map->last) map->last = rec->prev;
- if(rec == map->cur) map->cur = rec->next;
- if(rec->left && !rec->right){
- *entp = rec->left;
- } else if(!rec->left && rec->right){
- *entp = rec->right;
- } else if(!rec->left && !rec->left){
- *entp = NULL;
- } else {
- *entp = rec->left;
- TCMAPREC *tmp = *entp;
- while(tmp->right){
- tmp = tmp->right;
- }
- tmp->right = rec->right;
- }
- free(rec);
- return true;
- }
- }
- }
- return false;
-}
-
-
-/* Remove a string record of a map object. */
-bool tcmapout2(TCMAP *map, const char *kstr){
- assert(map && kstr);
- return tcmapout(map, kstr, strlen(kstr));
-}
-
-
-/* Retrieve a record in a map object. */
-const void *tcmapget(const TCMAP *map, const void *kbuf, int ksiz, int *sp){
- assert(map && kbuf && ksiz >= 0 && sp);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- TCMAPREC *rec = map->buckets[hash%map->bnum];
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- rec = rec->left;
- } else if(hash < rec->hash){
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- rec = rec->left;
- } else if(kcmp > 0){
- rec = rec->right;
- } else {
- *sp = rec->vsiz;
- return dbuf + rec->ksiz + TCALIGNPAD(rec->ksiz);
- }
- }
- }
- return NULL;
-}
-
-
-/* Retrieve a string record in a map object. */
-const char *tcmapget2(const TCMAP *map, const char *kstr){
- assert(map && kstr);
- int ksiz = strlen(kstr);
- unsigned int hash;
- TCMAPHASH1(hash, kstr, ksiz);
- TCMAPREC *rec = map->buckets[hash%map->bnum];
- TCMAPHASH2(hash, kstr, ksiz);
- while(rec){
- if(hash > rec->hash){
- rec = rec->left;
- } else if(hash < rec->hash){
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kstr, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- rec = rec->left;
- } else if(kcmp > 0){
- rec = rec->right;
- } else {
- return dbuf + rec->ksiz + TCALIGNPAD(rec->ksiz);
- }
- }
- }
- return NULL;
-}
-
-
-/* Retrieve a semivolatile record in a map object. */
-const void *tcmapget3(TCMAP *map, const void *kbuf, int ksiz, int *sp){
- assert(map && kbuf && ksiz >= 0 && sp);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- TCMAPREC *rec = map->buckets[hash%map->bnum];
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- rec = rec->left;
- } else if(hash < rec->hash){
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- rec = rec->left;
- } else if(kcmp > 0){
- rec = rec->right;
- } else {
- if(map->last != rec){
- if(map->first == rec) map->first = rec->next;
- if(rec->prev) rec->prev->next = rec->next;
- if(rec->next) rec->next->prev = rec->prev;
- rec->prev = map->last;
- rec->next = NULL;
- map->last->next = rec;
- map->last = rec;
- }
- *sp = rec->vsiz;
- return dbuf + rec->ksiz + TCALIGNPAD(rec->ksiz);
- }
- }
- }
- return NULL;
-}
-
-
-/* Move a record to the edge of a map object. */
-bool tcmapmove(TCMAP *map, const void *kbuf, int ksiz, bool head){
- assert(map && kbuf && ksiz >= 0);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- TCMAPREC *rec = map->buckets[hash%map->bnum];
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- rec = rec->left;
- } else if(hash < rec->hash){
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- rec = rec->left;
- } else if(kcmp > 0){
- rec = rec->right;
- } else {
- if(head){
- if(map->first == rec) return true;
- if(map->last == rec) map->last = rec->prev;
- if(rec->prev) rec->prev->next = rec->next;
- if(rec->next) rec->next->prev = rec->prev;
- rec->prev = NULL;
- rec->next = map->first;
- map->first->prev = rec;
- map->first = rec;
- } else {
- if(map->last == rec) return true;
- if(map->first == rec) map->first = rec->next;
- if(rec->prev) rec->prev->next = rec->next;
- if(rec->next) rec->next->prev = rec->prev;
- rec->prev = map->last;
- rec->next = NULL;
- map->last->next = rec;
- map->last = rec;
- }
- return true;
- }
- }
- }
- return false;
-}
-
-
-/* Move a string record to the edge of a map object. */
-bool tcmapmove2(TCMAP *map, const char *kstr, bool head){
- assert(map && kstr);
- return tcmapmove(map, kstr, strlen(kstr), head);
-}
-
-
-/* Initialize the iterator of a map object. */
-void tcmapiterinit(TCMAP *map){
- assert(map);
- map->cur = map->first;
-}
-
-
-/* Get the next key of the iterator of a map object. */
-const void *tcmapiternext(TCMAP *map, int *sp){
- assert(map && sp);
- TCMAPREC *rec;
- if(!map->cur) return NULL;
- rec = map->cur;
- map->cur = rec->next;
- *sp = rec->ksiz;
- return (char *)rec + sizeof(*rec);
-}
-
-
-/* Get the next key string of the iterator of a map object. */
-const char *tcmapiternext2(TCMAP *map){
- assert(map);
- TCMAPREC *rec;
- if(!map->cur) return NULL;
- rec = map->cur;
- map->cur = rec->next;
- return (char *)rec + sizeof(*rec);
-}
-
-
-/* Get the value bound to the key fetched from the iterator of a map object. */
-const void *tcmapiterval(const void *kbuf, int *sp){
- assert(kbuf && sp);
- TCMAPREC *rec = (TCMAPREC *)((char *)kbuf - sizeof(*rec));
- *sp = rec->vsiz;
- return (char *)kbuf + rec->ksiz + TCALIGNPAD(rec->ksiz);
-}
-
-
-/* Get the value string bound to the key fetched from the iterator of a map object. */
-const char *tcmapiterval2(const char *kstr){
- assert(kstr);
- TCMAPREC *rec = (TCMAPREC *)(kstr - sizeof(*rec));
- return kstr + rec->ksiz + TCALIGNPAD(rec->ksiz);
-}
-
-
-/* Get the number of records stored in a map object. */
-uint64_t tcmaprnum(const TCMAP *map){
- assert(map);
- return map->rnum;
-}
-
-
-/* Get the total size of memory used in a map object. */
-uint64_t tcmapmsiz(const TCMAP *map){
- assert(map);
- return map->msiz + map->rnum * (sizeof(*map->first) + sizeof(void *)) +
- map->bnum * sizeof(void *);
-}
-
-
-/* Create a list object containing all keys in a map object. */
-TCLIST *tcmapkeys(const TCMAP *map){
- assert(map);
- TCLIST *list = tclistnew2(map->rnum);
- TCMAPREC *cur = map->cur;
- const char *kbuf;
- int ksiz;
- ((TCMAP *)map)->cur = map->first;
- while((kbuf = tcmapiternext((TCMAP *)map, &ksiz)) != NULL){
- TCLISTPUSH(list, kbuf, ksiz);
- }
- ((TCMAP *)map)->cur = cur;
- return list;
-}
-
-
-/* Create a list object containing all values in a map object. */
-TCLIST *tcmapvals(const TCMAP *map){
- assert(map);
- TCLIST *list = tclistnew2(map->rnum);
- TCMAPREC *cur = map->cur;
- const char *kbuf;
- int ksiz;
- ((TCMAP *)map)->cur = map->first;
- while((kbuf = tcmapiternext((TCMAP *)map, &ksiz)) != NULL){
- int vsiz;
- const char *vbuf = tcmapiterval(kbuf, &vsiz);
- TCLISTPUSH(list, vbuf, vsiz);
- }
- ((TCMAP *)map)->cur = cur;
- return list;
-}
-
-
-/* Add an integer to a record in a map object. */
-void tcmapaddint(TCMAP *map, const char *kbuf, int ksiz, int num){
- assert(map && kbuf && ksiz >= 0);
- unsigned int hash;
- TCMAPHASH1(hash, kbuf, ksiz);
- int bidx = hash % map->bnum;
- TCMAPREC *rec = map->buckets[bidx];
- TCMAPREC **entp = map->buckets + bidx;
- TCMAPHASH2(hash, kbuf, ksiz);
- while(rec){
- if(hash > rec->hash){
- entp = &(rec->left);
- rec = rec->left;
- } else if(hash < rec->hash){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- char *dbuf = (char *)rec + sizeof(*rec);
- int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz);
- if(kcmp < 0){
- entp = &(rec->left);
- rec = rec->left;
- } else if(kcmp > 0){
- entp = &(rec->right);
- rec = rec->right;
- } else {
- int psiz = TCALIGNPAD(ksiz);
- *(int *)(dbuf + ksiz + psiz) += num;
- return;
- }
- }
- }
- int psiz = TCALIGNPAD(ksiz);
- TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + sizeof(num) + 1);
- char *dbuf = (char *)rec + sizeof(*rec);
- memcpy(dbuf, kbuf, ksiz);
- dbuf[ksiz] = '\0';
- rec->ksiz = ksiz;
- memcpy(dbuf + ksiz + psiz, &num, sizeof(num));
- dbuf[ksiz+psiz+sizeof(num)] = '\0';
- rec->vsiz = sizeof(num);
- rec->hash = hash;
- rec->left = NULL;
- rec->right = NULL;
- rec->prev = map->last;
- rec->next = NULL;
- *entp = rec;
- if(!map->first) map->first = rec;
- if(map->last) map->last->next = rec;
- map->last = rec;
- map->rnum++;
-}
-
-
-/* Clear a map object. */
-void tcmapclear(TCMAP *map){
- assert(map);
- TCMAPREC *rec = map->first;
- while(rec){
- TCMAPREC *next = rec->next;
- free(rec);
- rec = next;
- }
- TCMAPREC **buckets = map->buckets;
- int bnum = map->bnum;
- for(int i = 0; i < bnum; i++){
- buckets[i] = NULL;
- }
- map->first = NULL;
- map->last = NULL;
- map->cur = NULL;
- map->rnum = 0;
- map->msiz = 0;
-}
-
-
-/* Remove front records of a map object. */
-void tcmapcutfront(TCMAP *map, int num){
- assert(map && num >= 0);
- tcmapiterinit(map);
- while(num-- > 0){
- int ksiz;
- const char *kbuf = tcmapiternext(map, &ksiz);
- if(!kbuf) break;
- tcmapout(map, kbuf, ksiz);
- }
-}
-
-
-/* Serialize a map object into a byte array. */
-void *tcmapdump(const TCMAP *map, int *sp){
- assert(map && sp);
- TCMAPREC *cur = map->cur;
- int tsiz = 0;
- const char *kbuf, *vbuf;
- int ksiz, vsiz;
- ((TCMAP *)map)->cur = map->first;
- while((kbuf = tcmapiternext((TCMAP *)map, &ksiz)) != NULL){
- vbuf = tcmapiterval(kbuf, &vsiz);
- tsiz += ksiz + vsiz + sizeof(int) * 2;
- }
- char *buf;
- TCMALLOC(buf, tsiz + 1);
- char *wp = buf;
- ((TCMAP *)map)->cur = map->first;
- while((kbuf = tcmapiternext((TCMAP *)map, &ksiz)) != NULL){
- vbuf = tcmapiterval(kbuf, &vsiz);
- int step;
- TCSETVNUMBUF(step, wp, ksiz);
- wp += step;
- memcpy(wp, kbuf, ksiz);
- wp += ksiz;
- TCSETVNUMBUF(step, wp, vsiz);
- wp += step;
- memcpy(wp, vbuf, vsiz);
- wp += vsiz;
- }
- ((TCMAP *)map)->cur = cur;
- *sp = wp - buf;
- return buf;
-}
-
-
-/* Create a map object from a serialized byte array. */
-TCMAP *tcmapload(const void *ptr, int size){
- assert(ptr && size >= 0);
- TCMAP *map = tcmapnew();
- const char *rp = ptr;
- const char *ep = (char *)ptr + size;
- while(rp < ep){
- int step, ksiz, vsiz;
- TCREADVNUMBUF(rp, ksiz, step);
- rp += step;
- const char *kbuf = rp;
- rp += ksiz;
- TCREADVNUMBUF(rp, vsiz, step);
- rp += step;
- tcmapputkeep(map, kbuf, ksiz, rp, vsiz);
- rp += vsiz;
- }
- return map;
-}
-
-
-/* Extract a map record from a serialized byte array. */
-void *tcmaploadone(const void *ptr, int size, const void *kbuf, int ksiz, int *sp){
- assert(ptr && size >= 0 && kbuf && ksiz >= 0 && sp);
- const char *rp = ptr;
- const char *ep = (char *)ptr + size;
- while(rp < ep){
- int step, rsiz;
- TCREADVNUMBUF(rp, rsiz, step);
- rp += step;
- if(rsiz == ksiz && !memcmp(kbuf, rp, rsiz)){
- rp += rsiz;
- TCREADVNUMBUF(rp, rsiz, step);
- rp += step;
- *sp = rsiz;
- char *rv;
- TCMEMDUP(rv, rp, rsiz);
- return rv;
- }
- rp += rsiz;
- TCREADVNUMBUF(rp, rsiz, step);
- rp += step;
- rp += rsiz;
- }
- return NULL;
-}
-
-
-
-/*************************************************************************************************
- * on-memory database
- *************************************************************************************************/
-
-
-#define TCMDBMNUM 8 // number of internal maps
-#define TCMDBBNUM 65536 // allocation unit number of a map
-
-/* get the first hash value */
-#define TCMDBHASH(TC_res, TC_kbuf, TC_ksiz) \
- do { \
- const unsigned char *_TC_p = (const unsigned char *)(TC_kbuf) + TC_ksiz - 1; \
- int _TC_ksiz = TC_ksiz; \
- for((TC_res) = 0x20071123; _TC_ksiz--;){ \
- (TC_res) = ((TC_res) << 5) + (TC_res) + *(_TC_p)--; \
- } \
- (TC_res) &= TCMDBMNUM - 1; \
- } while(false)
-
-
-/* Create an on-memory database object. */
-TCMDB *tcmdbnew(void){
- return tcmdbnew2(TCMDBBNUM);
-}
-
-
-/* Create an on-memory database with specifying the number of the buckets. */
-TCMDB *tcmdbnew2(uint32_t bnum){
- TCMDB *mdb;
- if(bnum < 1) bnum = TCMDBBNUM;
- bnum = bnum / TCMDBMNUM + 17;
- TCMALLOC(mdb, sizeof(*mdb));
- TCMALLOC(mdb->mmtxs, sizeof(pthread_rwlock_t) * TCMDBMNUM);
- TCMALLOC(mdb->imtx, sizeof(pthread_mutex_t));
- TCMALLOC(mdb->maps, sizeof(TCMAP *) * TCMDBMNUM);
- if(pthread_mutex_init(mdb->imtx, NULL) != 0) tcmyfatal("mutex error");
- for(int i = 0; i < TCMDBMNUM; i++){
- if(pthread_rwlock_init((pthread_rwlock_t *)mdb->mmtxs + i, NULL) != 0)
- tcmyfatal("rwlock error");
- mdb->maps[i] = tcmapnew2(bnum);
- }
- mdb->iter = -1;
- return mdb;
-}
-
-
-/* Delete an on-memory database object. */
-void tcmdbdel(TCMDB *mdb){
- assert(mdb);
- for(int i = TCMDBMNUM - 1; i >= 0; i--){
- tcmapdel(mdb->maps[i]);
- pthread_rwlock_destroy((pthread_rwlock_t *)mdb->mmtxs + i);
- }
- pthread_mutex_destroy(mdb->imtx);
- free(mdb->maps);
- free(mdb->imtx);
- free(mdb->mmtxs);
- free(mdb);
-}
-
-
-/* Store a record into an on-memory database. */
-void tcmdbput(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(mdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- unsigned int mi;
- TCMDBHASH(mi, kbuf, ksiz);
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return;
- tcmapput(mdb->maps[mi], kbuf, ksiz, vbuf, vsiz);
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
-}
-
-
-/* Store a string record into an on-memory database. */
-void tcmdbput2(TCMDB *mdb, const char *kstr, const char *vstr){
- assert(mdb && kstr && vstr);
- tcmdbput(mdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Store a record of the value of two regions into an on-memory database object. */
-void tcmdbput3(TCMDB *mdb, const char *kbuf, int ksiz,
- const void *fvbuf, int fvsiz, const char *lvbuf, int lvsiz){
- assert(mdb && kbuf && ksiz >= 0 && fvbuf && fvsiz >= 0 && lvbuf && lvsiz >= 0);
- unsigned int mi;
- TCMDBHASH(mi, kbuf, ksiz);
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return;
- tcmapput3(mdb->maps[mi], kbuf, ksiz, fvbuf, fvsiz, lvbuf, lvsiz);
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
-}
-
-
-/* Store a new record into an on-memory database. */
-bool tcmdbputkeep(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(mdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- unsigned int mi;
- TCMDBHASH(mi, kbuf, ksiz);
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return false;
- bool rv = tcmapputkeep(mdb->maps[mi], kbuf, ksiz, vbuf, vsiz);
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
- return rv;
-}
-
-
-/* Store a new string record into an on-memory database. */
-bool tcmdbputkeep2(TCMDB *mdb, const char *kstr, const char *vstr){
- assert(mdb && kstr && vstr);
- return tcmdbputkeep(mdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Concatenate a value at the end of the value of the existing record in an on-memory database. */
-void tcmdbputcat(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
- assert(mdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
- unsigned int mi;
- TCMDBHASH(mi, kbuf, ksiz);
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return;
- tcmapputcat(mdb->maps[mi], kbuf, ksiz, vbuf, vsiz);
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
-}
-
-
-/* Concatenate a string at the end of the value of the existing record in an on-memory database. */
-void tcmdbputcat2(TCMDB *mdb, const char *kstr, const char *vstr){
- assert(mdb && kstr && vstr);
- tcmdbputcat(mdb, kstr, strlen(kstr), vstr, strlen(vstr));
-}
-
-
-/* Remove a record of an on-memory database. */
-bool tcmdbout(TCMDB *mdb, const void *kbuf, int ksiz){
- assert(mdb && kbuf && ksiz >= 0);
- unsigned int mi;
- TCMDBHASH(mi, kbuf, ksiz);
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return false;
- bool rv = tcmapout(mdb->maps[mi], kbuf, ksiz);
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
- return rv;
-}
-
-
-/* Remove a string record of an on-memory database. */
-bool tcmdbout2(TCMDB *mdb, const char *kstr){
- assert(mdb && kstr);
- return tcmdbout(mdb, kstr, strlen(kstr));
-}
-
-
-/* Retrieve a record in an on-memory database. */
-void *tcmdbget(TCMDB *mdb, const void *kbuf, int ksiz, int *sp){
- assert(mdb && kbuf && ksiz >= 0 && sp);
- unsigned int mi;
- TCMDBHASH(mi, kbuf, ksiz);
- if(pthread_rwlock_rdlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return NULL;
- int vsiz;
- const char *vbuf = tcmapget(mdb->maps[mi], kbuf, ksiz, &vsiz);
- char *rv;
- if(vbuf){
- TCMEMDUP(rv, vbuf, vsiz);
- *sp = vsiz;
- } else {
- rv = NULL;
- }
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
- return rv;
-}
-
-
-/* Retrieve a string record in an on-memory database. */
-char *tcmdbget2(TCMDB *mdb, const char *kstr){
- assert(mdb && kstr);
- int vsiz;
- return tcmdbget(mdb, kstr, strlen(kstr), &vsiz);
-}
-
-
-/* Retrieve a record and move it astern in an on-memory database. */
-void *tcmdbget3(TCMDB *mdb, const void *kbuf, int ksiz, int *sp){
- assert(mdb && kbuf && ksiz >= 0 && sp);
- unsigned int mi;
- TCMDBHASH(mi, kbuf, ksiz);
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return NULL;
- int vsiz;
- const char *vbuf = tcmapget3(mdb->maps[mi], kbuf, ksiz, &vsiz);
- char *rv;
- if(vbuf){
- TCMEMDUP(rv, vbuf, vsiz);
- *sp = vsiz;
- } else {
- rv = NULL;
- }
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
- return rv;
-}
-
-
-/* Get the size of the value of a record in an on-memory database object. */
-int tcmdbvsiz(TCMDB *mdb, const void *kbuf, int ksiz){
- assert(mdb && kbuf && ksiz >= 0);
- unsigned int mi;
- TCMDBHASH(mi, kbuf, ksiz);
- if(pthread_rwlock_rdlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return -1;
- int vsiz;
- const char *vbuf = tcmapget(mdb->maps[mi], kbuf, ksiz, &vsiz);
- if(!vbuf) vsiz = -1;
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
- return vsiz;
-}
-
-
-/* Get the size of the value of a string record in an on-memory database object. */
-int tcmdbvsiz2(TCMDB *mdb, const char *kstr){
- assert(mdb && kstr);
- return tcmdbvsiz(mdb, kstr, strlen(kstr));
-}
-
-
-/* Initialize the iterator of an on-memory database. */
-void tcmdbiterinit(TCMDB *mdb){
- assert(mdb);
- if(pthread_mutex_lock(mdb->imtx) != 0) return;
- for(int i = 0; i < TCMDBMNUM; i++){
- tcmapiterinit(mdb->maps[i]);
- }
- mdb->iter = 0;
- pthread_mutex_unlock(mdb->imtx);
-}
-
-
-/* Get the next key of the iterator of an on-memory database. */
-void *tcmdbiternext(TCMDB *mdb, int *sp){
- assert(mdb && sp);
- if(pthread_mutex_lock(mdb->imtx) != 0) return NULL;
- if(mdb->iter < 0 || mdb->iter >= TCMDBMNUM){
- pthread_mutex_unlock(mdb->imtx);
- return NULL;
- }
- int mi = mdb->iter;
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0){
- pthread_mutex_unlock(mdb->imtx);
- return NULL;
- }
- int ksiz;
- const char *kbuf;
- while(!(kbuf = tcmapiternext(mdb->maps[mi], &ksiz)) && mi < TCMDBMNUM - 1){
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
- mi = ++mdb->iter;
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0){
- pthread_mutex_unlock(mdb->imtx);
- return NULL;
- }
- }
- char *rv;
- if(kbuf){
- TCMEMDUP(rv, kbuf, ksiz);
- *sp = ksiz;
- } else {
- rv = NULL;
- }
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
- pthread_mutex_unlock(mdb->imtx);
- return rv;
-}
-
-
-/* Get the next key string of the iterator of an on-memory database. */
-char *tcmdbiternext2(TCMDB *mdb){
- assert(mdb);
- int ksiz;
- return tcmdbiternext(mdb, &ksiz);
-}
-
-
-/* Get forward matching keys in an on-memory database object. */
-TCLIST *tcmdbfwmkeys(TCMDB *mdb, const void *pbuf, int psiz, int max){
- assert(mdb && pbuf && psiz >= 0);
- TCLIST* keys = tclistnew();
- if(pthread_mutex_lock(mdb->imtx) != 0) return keys;
- if(max < 0) max = INT_MAX;
- for(int i = 0; i < TCMDBMNUM && TCLISTNUM(keys) < max; i++){
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + i) == 0){
- TCMAP *map = mdb->maps[i];
- TCMAPREC *cur = map->cur;
- tcmapiterinit(map);
- int ksiz;
- const char *kbuf;
- while(TCLISTNUM(keys) < max && (kbuf = tcmapiternext(map, &ksiz)) != NULL){
- if(ksiz >= psiz && !memcmp(kbuf, pbuf, psiz)) tclistpush(keys, kbuf, ksiz);
- }
- map->cur = cur;
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + i);
- }
- }
- pthread_mutex_unlock(mdb->imtx);
- return keys;
-}
-
-
-/* Get forward matching string keys in an on-memory database object. */
-TCLIST *tcmdbfwmkeys2(TCMDB *mdb, const char *pstr, int max){
- assert(mdb && pstr);
- return tcmdbfwmkeys(mdb, pstr, strlen(pstr), max);
-}
-
-
-/* Get the number of records stored in an on-memory database. */
-uint64_t tcmdbrnum(TCMDB *mdb){
- assert(mdb);
- uint64_t rnum = 0;
- for(int i = 0; i < TCMDBMNUM; i++){
- rnum += tcmaprnum(mdb->maps[i]);
- }
- return rnum;
-}
-
-
-/* Get the total size of memory used in an on-memory database object. */
-uint64_t tcmdbmsiz(TCMDB *mdb){
- assert(mdb);
- uint64_t msiz = 0;
- for(int i = 0; i < TCMDBMNUM; i++){
- msiz += tcmapmsiz(mdb->maps[i]);
- }
- return msiz;
-}
-
-
-/* Clear an on-memory database object. */
-void tcmdbvanish(TCMDB *mdb){
- assert(mdb);
- for(int i = 0; i < TCMDBMNUM; i++){
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + i) == 0){
- tcmapclear(mdb->maps[i]);
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + i);
- }
- }
-}
-
-
-/* Remove front records of a map object. */
-void tcmdbcutfront(TCMDB *mdb, int num){
- assert(mdb && num >= 0);
- num = num / TCMDBMNUM + 1;
- for(int i = 0; i < TCMDBMNUM; i++){
- if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + i) == 0){
- tcmapcutfront(mdb->maps[i], num);
- pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + i);
- }
- }
-}
-
-
-
-/*************************************************************************************************
- * memory pool
- *************************************************************************************************/
-
-
-#define TCMPOOLUNIT 128 // allocation unit size of memory pool elements
-
-
-/* Global memory pool object. */
-TCMPOOL *tcglobalmemorypool = NULL;
-
-
-/* private function prototypes */
-static void tcmpooldelglobal(void);
-
-
-/* Create a memory pool object. */
-TCMPOOL *tcmpoolnew(void){
- TCMPOOL *mpool;
- TCMALLOC(mpool, sizeof(*mpool));
- TCMALLOC(mpool->mutex, sizeof(pthread_mutex_t));
- if(pthread_mutex_init(mpool->mutex, NULL) != 0) tcmyfatal("locking failed");
- mpool->anum = TCMPOOLUNIT;
- TCMALLOC(mpool->elems, sizeof(mpool->elems[0]) * mpool->anum);
- mpool->num = 0;
- return mpool;
-}
-
-
-/* Delete a memory pool object. */
-void tcmpooldel(TCMPOOL *mpool){
- assert(mpool);
- TCMPELEM *elems = mpool->elems;
- for(int i = mpool->num - 1; i >= 0; i--){
- elems[i].del(elems[i].ptr);
- }
- free(elems);
- pthread_mutex_destroy(mpool->mutex);
- free(mpool->mutex);
- free(mpool);
-}
-
-
-/* Relegate an arbitrary object to a memory pool object. */
-void tcmpoolput(TCMPOOL *mpool, void *ptr, void (*del)(void *)){
- assert(mpool && ptr && del);
- if(pthread_mutex_lock(mpool->mutex) != 0) tcmyfatal("locking failed");
- int num = mpool->num;
- if(num >= mpool->anum){
- mpool->anum *= 2;
- TCREALLOC(mpool->elems, mpool->elems, mpool->anum * sizeof(mpool->elems[0]));
- }
- mpool->elems[num].ptr = ptr;
- mpool->elems[num].del = del;
- mpool->num++;
- pthread_mutex_unlock(mpool->mutex);
-}
-
-
-/* Relegate an allocated region to a memory pool object. */
-void tcmpoolputptr(TCMPOOL *mpool, void *ptr){
- assert(mpool && ptr);
- tcmpoolput(mpool, ptr, (void (*)(void *))free);
-}
-
-
-/* Relegate an extensible string object to a memory pool object. */
-void tcmpoolputxstr(TCMPOOL *mpool, TCXSTR *xstr){
- assert(mpool && xstr);
- tcmpoolput(mpool, xstr, (void (*)(void *))tcxstrdel);
-}
-
-
-/* Relegate a list object to a memory pool object. */
-void tcmpoolputlist(TCMPOOL *mpool, TCLIST *list){
- assert(mpool && list);
- tcmpoolput(mpool, list, (void (*)(void *))tclistdel);
-}
-
-
-/* Relegate a map object to a memory pool object. */
-void tcmpoolputmap(TCMPOOL *mpool, TCMAP *map){
- assert(mpool && map);
- tcmpoolput(mpool, map, (void (*)(void *))tcmapdel);
-}
-
-
-/* Allocate a region relegated to a memory pool object. */
-void *tcmpoolmalloc(TCMPOOL *mpool, size_t size){
- assert(mpool && size > 0);
- void *ptr;
- TCMALLOC(ptr, size);
- tcmpoolput(mpool, ptr, (void (*)(void *))free);
- return ptr;
-}
-
-
-/* Create an extensible string object relegated to a memory pool object. */
-TCXSTR *tcmpoolxstrnew(TCMPOOL *mpool){
- assert(mpool);
- TCXSTR *xstr = tcxstrnew();
- tcmpoolput(mpool, xstr, (void (*)(void *))tcxstrdel);
- return xstr;
-}
-
-
-/* Create a list object relegated to a memory pool object. */
-TCLIST *tcmpoollistnew(TCMPOOL *mpool){
- assert(mpool);
- TCLIST *list = tclistnew();
- tcmpoolput(mpool, list, (void (*)(void *))tclistdel);
- return list;
-}
-
-
-/* Create a map object relegated to a memory pool object. */
-TCMAP *tcmpoolmapnew(TCMPOOL *mpool){
- assert(mpool);
- TCMAP *map = tcmapnew();
- tcmpoolput(mpool, map, (void (*)(void *))tcmapdel);
- return map;
-}
-
-
-/* Get the global memory pool object. */
-TCMPOOL *tcmpoolglobal(void){
- if(tcglobalmemorypool) return tcglobalmemorypool;
- tcglobalmemorypool = tcmpoolnew();
- atexit(tcmpooldelglobal);
- return tcglobalmemorypool;
-}
-
-
-/* Detete global memory pool object. */
-static void tcmpooldelglobal(void){
- if(tcglobalmemorypool) tcmpooldel(tcglobalmemorypool);
-}
-
-
-
-/*************************************************************************************************
- * miscellaneous utilities
- *************************************************************************************************/
-
-
-#define TCRANDDEV "/dev/urandom" // path of the random device file
-#define TCDISTBUFSIZ 16384 // size of an distance buffer
-
-
-/* File descriptor of random number generator. */
-int tcrandomdevfd = -1;
-
-
-/* private function prototypes */
-static void tcrandomfdclose(void);
-static time_t tcmkgmtime(struct tm *tm);
-
-
-/* Get the larger value of two integers. */
-long tclmax(long a, long b){
- return (a > b) ? a : b;
-}
-
-
-/* Get the lesser value of two integers. */
-long tclmin(long a, long b){
- return (a < b) ? a : b;
-}
-
-
-/* Get a random number as long integer based on uniform distribution. */
-unsigned long tclrand(void){
- static unsigned int cnt = 0;
- static unsigned int seed = 0;
- static unsigned long mask = 0;
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- if((cnt & 0xff) == 0 && pthread_mutex_lock(&mutex) == 0){
- if(cnt++ == 0) seed = time(NULL);
- if(tcrandomdevfd == -1 && (tcrandomdevfd = open(TCRANDDEV, O_RDONLY, 00644)) != -1)
- atexit(tcrandomfdclose);
- if(tcrandomdevfd != -1) read(tcrandomdevfd, &mask, sizeof(mask));
- pthread_mutex_unlock(&mutex);
- }
- return (mask ^ cnt++) ^ (unsigned long)rand_r(&seed);
-}
-
-
-/* Get a random number as double decimal based on uniform distribution. */
-double tcdrand(void){
- return tclrand() / (ULONG_MAX + 0.01);
-}
-
-
-/* Get a random number as double decimal based on normal distribution. */
-double tcdrandnd(double avg, double sd){
- assert(sd >= 0.0);
- return sqrt(-2.0 * log(tcdrand())) * cos(2 * 3.141592653589793 * tcdrand()) * sd + avg;
-}
-
-
-/* Compare two strings with case insensitive evaluation. */
-int tcstricmp(const char *astr, const char *bstr){
- assert(astr && bstr);
- while(*astr != '\0'){
- if(*bstr == '\0') return 1;
- int ac = (*astr >= 'A' && *astr <= 'Z') ? *astr + ('a' - 'A') : *(unsigned char *)astr;
- int bc = (*bstr >= 'A' && *bstr <= 'Z') ? *bstr + ('a' - 'A') : *(unsigned char *)bstr;
- if(ac != bc) return ac - bc;
- astr++;
- bstr++;
- }
- return (*bstr == '\0') ? 0 : -1;
-}
-
-
-/* Check whether a string begins with a key. */
-bool tcstrfwm(const char *str, const char *key){
- assert(str && key);
- while(*key != '\0'){
- if(*str != *key || *str == '\0') return false;
- key++;
- str++;
- }
- return true;
-}
-
-
-/* Check whether a string begins with a key with case insensitive evaluation. */
-bool tcstrifwm(const char *str, const char *key){
- assert(str && key);
- while(*key != '\0'){
- if(*str == '\0') return false;
- int sc = *str;
- if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A';
- int kc = *key;
- if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A';
- if(sc != kc) return false;
- key++;
- str++;
- }
- return true;
-}
-
-
-/* Check whether a string ends with a key. */
-bool tcstrbwm(const char *str, const char *key){
- assert(str && key);
- int slen = strlen(str);
- int klen = strlen(key);
- for(int i = 1; i <= klen; i++){
- if(i > slen || str[slen-i] != key[klen-i]) return false;
- }
- return true;
-}
-
-
-/* Check whether a string ends with a key with case insensitive evaluation. */
-bool tcstribwm(const char *str, const char *key){
- assert(str && key);
- int slen = strlen(str);
- int klen = strlen(key);
- for(int i = 1; i <= klen; i++){
- if(i > slen) return false;
- int sc = str[slen-i];
- if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A';
- int kc = key[klen-i];
- if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A';
- if(sc != kc) return false;
- }
- return true;
-}
-
-
-/* Calculate the edit distance of two strings. */
-int tcstrdist(const char *astr, const char *bstr){
- assert(astr && bstr);
- int alen = strlen(astr);
- int blen = strlen(bstr);
- int dsiz = blen + 1;
- int tbuf[TCDISTBUFSIZ];
- int *tbl;
- if((alen + 1) * dsiz < TCDISTBUFSIZ){
- tbl = tbuf;
- } else {
- TCMALLOC(tbl, (alen + 1) * dsiz * sizeof(*tbl));
- }
- for(int i = 0; i <= alen; i++){
- tbl[i*dsiz] = i;
- }
- for(int i = 1; i <= blen; i++){
- tbl[i] = i;
- }
- astr--;
- bstr--;
- for(int i = 1; i <= alen; i++){
- for(int j = 1; j <= blen; j++){
- int ac = tbl[(i-1)*dsiz+j] + 1;
- int bc = tbl[i*dsiz+j-1] + 1;
- int cc = tbl[(i-1)*dsiz+j-1] + (astr[i] != bstr[j]);
- ac = ac < bc ? ac : bc;
- tbl[i*dsiz+j] = ac < cc ? ac : cc;
- }
- }
- int rv = tbl[alen*dsiz+blen];
- if(tbl != tbuf) free(tbl);
- return rv;
-}
-
-
-/* Calculate the edit distance of two UTF-8 strings. */
-int tcstrdistutf(const char *astr, const char *bstr){
- assert(astr && bstr);
- int alen = strlen(astr);
- uint16_t abuf[TCDISTBUFSIZ];
- uint16_t *aary;
- if(alen < TCDISTBUFSIZ){
- aary = abuf;
- } else {
- TCMALLOC(aary, alen * sizeof(*aary));
- }
- tcstrutftoucs(astr, aary, &alen);
- int blen = strlen(bstr);
- uint16_t bbuf[TCDISTBUFSIZ];
- uint16_t *bary;
- if(blen < TCDISTBUFSIZ){
- bary = bbuf;
- } else {
- TCMALLOC(bary, blen * sizeof(*bary));
- }
- tcstrutftoucs(bstr, bary, &blen);
- int dsiz = blen + 1;
- int tbuf[TCDISTBUFSIZ];
- int *tbl;
- if((alen + 1) * dsiz < TCDISTBUFSIZ){
- tbl = tbuf;
- } else {
- TCMALLOC(tbl, (alen + 1) * dsiz * sizeof(*tbl));
- }
- for(int i = 0; i <= alen; i++){
- tbl[i*dsiz] = i;
- }
- for(int i = 1; i <= blen; i++){
- tbl[i] = i;
- }
- aary--;
- bary--;
- for(int i = 1; i <= alen; i++){
- for(int j = 1; j <= blen; j++){
- int ac = tbl[(i-1)*dsiz+j] + 1;
- int bc = tbl[i*dsiz+j-1] + 1;
- int cc = tbl[(i-1)*dsiz+j-1] + (aary[i] != bary[j]);
- ac = ac < bc ? ac : bc;
- tbl[i*dsiz+j] = ac < cc ? ac : cc;
- }
- }
- aary++;
- bary++;
- int rv = tbl[alen*dsiz+blen];
- if(tbl != tbuf) free(tbl);
- if(bary != bbuf) free(bary);
- if(aary != abuf) free(aary);
- return rv;
-}
-
-
-/* Convert the letters of a string into upper case. */
-char *tcstrtoupper(char *str){
- assert(str);
- char *wp = str;
- while(*wp != '\0'){
- if(*wp >= 'a' && *wp <= 'z') *wp -= 'a' - 'A';
- wp++;
- }
- return str;
-}
-
-
-/* Convert the letters of a string into lower case. */
-char *tcstrtolower(char *str){
- assert(str);
- char *wp = str;
- while(*wp != '\0'){
- if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A';
- wp++;
- }
- return str;
-}
-
-
-/* Cut space characters at head or tail of a string. */
-char *tcstrtrim(char *str){
- assert(str);
- const char *rp = str;
- char *wp = str;
- bool head = true;
- while(*rp != '\0'){
- if(*rp > '\0' && *rp <= ' '){
- if(!head) *(wp++) = *rp;
- } else {
- *(wp++) = *rp;
- head = false;
- }
- rp++;
- }
- *wp = '\0';
- while(wp > str && wp[-1] > '\0' && wp[-1] <= ' '){
- *(--wp) = '\0';
- }
- return str;
-}
-
-
-/* Squeeze space characters in a string and trim it. */
-char *tcstrsqzspc(char *str){
- assert(str);
- char *rp = str;
- char *wp = str;
- bool spc = true;
- while(*rp != '\0'){
- if(*rp > 0 && *rp <= ' '){
- if(!spc) *(wp++) = *rp;
- spc = true;
- } else {
- *(wp++) = *rp;
- spc = false;
- }
- rp++;
- }
- *wp = '\0';
- for(wp--; wp >= str; wp--){
- if(*wp > 0 && *wp <= ' '){
- *wp = '\0';
- } else {
- break;
- }
- }
- return str;
-}
-
-
-/* Substitute characters in a string. */
-char *tcstrsubchr(char *str, const char *rstr, const char *sstr){
- assert(str && rstr && sstr);
- int slen = strlen(sstr);
- char *wp = str;
- for(int i = 0; str[i] != '\0'; i++){
- const char *p = strchr(rstr, str[i]);
- if(p){
- int idx = p - rstr;
- if(idx < slen) *(wp++) = sstr[idx];
- } else {
- *(wp++) = str[i];
- }
- }
- *wp = '\0';
- return str;
-}
-
-
-/* Count the number of characters in a string of UTF-8. */
-int tcstrcntutf(const char *str){
- assert(str);
- const unsigned char *rp = (unsigned char *)str;
- int cnt = 0;
- while(*rp != '\0'){
- if((*rp & 0x80) == 0x00 || (*rp & 0xe0) == 0xc0 ||
- (*rp & 0xf0) == 0xe0 || (*rp & 0xf8) == 0xf0) cnt++;
- rp++;
- }
- return cnt;
-}
-
-
-/* Cut a string of UTF-8 at the specified number of characters. */
-char *tcstrcututf(char *str, int num){
- assert(str && num >= 0);
- unsigned char *wp = (unsigned char *)str;
- int cnt = 0;
- while(*wp != '\0'){
- if((*wp & 0x80) == 0x00 || (*wp & 0xe0) == 0xc0 ||
- (*wp & 0xf0) == 0xe0 || (*wp & 0xf8) == 0xf0){
- cnt++;
- if(cnt > num){
- *wp = '\0';
- break;
- }
- }
- wp++;
- }
- return str;
-}
-
-
-/* Convert a UTF-8 string into a UCS-2 array. */
-void tcstrutftoucs(const char *str, uint16_t *ary, int *np){
- assert(str && ary && np);
- const unsigned char *rp = (unsigned char *)str;
- unsigned int wi = 0;
- while(*rp != '\0'){
- int c = *(unsigned char *)rp;
- if(c < 0x80){
- ary[wi++] = c;
- } else if(c < 0xe0){
- if(rp[1] >= 0x80){
- ary[wi++] = ((rp[0] & 0x1f) << 6) | (rp[1] & 0x3f);
- rp++;
- }
- } else if(c < 0xf0){
- if(rp[1] >= 0x80 && rp[2] >= 0x80){
- ary[wi++] = ((rp[0] & 0xf) << 12) | ((rp[1] & 0x3f) << 6) | (rp[2] & 0x3f);
- rp += 2;
- }
- }
- rp++;
- }
- *np = wi;
-}
-
-
-/* Convert a UCS-2 array into a UTF-8 string. */
-void tcstrucstoutf(const uint16_t *ary, int num, char *str){
- assert(ary && num >= 0 && str);
- unsigned char *wp = (unsigned char *)str;
- for(int i = 0; i < num; i++){
- unsigned int c = ary[i];
- if(c < 0x80){
- *(wp++) = c;
- } else if(c < 0x800){
- *(wp++) = 0xc0 | (c >> 6);
- *(wp++) = 0x80 | (c & 0x3f);
- } else {
- *(wp++) = 0xe0 | (c >> 12);
- *(wp++) = 0x80 | ((c & 0xfff) >> 6);
- *(wp++) = 0x80 | (c & 0x3f);
- }
- }
- *wp = '\0';
-}
-
-
-/* Create a list object by splitting a string. */
-TCLIST *tcstrsplit(const char *str, const char *delims){
- assert(str && delims);
- TCLIST *list = tclistnew();
- while(true){
- const char *sp = str;
- while(*str != '\0' && !strchr(delims, *str)){
- str++;
- }
- TCLISTPUSH(list, sp, str - sp);
- if(*str == '\0') break;
- str++;
- }
- return list;
-}
-
-
-/* Create a string by joining all elements of a list object. */
-char *tcstrjoin(TCLIST *list, char delim){
- assert(list);
- int num = TCLISTNUM(list);
- int size = num + 1;
- for(int i = 0; i < num; i++){
- size += TCLISTVALNUM(list, i);
- }
- char *buf;
- TCMALLOC(buf, size);
- char *wp = buf;
- for(int i = 0; i < num; i++){
- if(i > 0) *(wp++) = delim;
- int vsiz;
- const char *vbuf = tclistval(list, i, &vsiz);
- memcpy(wp, vbuf, vsiz);
- wp += vsiz;
- }
- *wp = '\0';
- return buf;
-}
-
-
-/* Check whether a string matches a regular expression. */
-bool tcregexmatch(const char *str, const char *regex){
- assert(str && regex);
- int options = REG_EXTENDED | REG_NOSUB;
- if(*regex == '*'){
- options |= REG_ICASE;
- regex++;
- }
- regex_t rbuf;
- if(regcomp(&rbuf, regex, options) != 0) return false;
- bool rv = regexec(&rbuf, str, 0, NULL, 0) == 0;
- regfree(&rbuf);
- return rv;
-}
-
-
-/* Replace each substring matching a regular expression string. */
-char *tcregexreplace(const char *str, const char *regex, const char *alt){
- assert(str && regex && alt);
- int options = REG_EXTENDED;
- if(*regex == '*'){
- options |= REG_ICASE;
- regex++;
- }
- regex_t rbuf;
- if(regex[0] == '\0' || regcomp(&rbuf, regex, options) != 0) return tcstrdup(str);
- regmatch_t subs[256];
- if(regexec(&rbuf, str, 32, subs, 0) != 0){
- regfree(&rbuf);
- return tcstrdup(str);
- }
- const char *sp = str;
- TCXSTR *xstr = tcxstrnew();
- bool first = true;
- while(sp[0] != '\0' && regexec(&rbuf, sp, 10, subs, first ? 0 : REG_NOTBOL) == 0){
- first = false;
- if(subs[0].rm_so == -1) break;
- tcxstrcat(xstr, sp, subs[0].rm_so);
- for(const char *rp = alt; *rp != '\0'; rp++){
- if(*rp == '\\'){
- if(rp[1] >= '0' && rp[1] <= '9'){
- int num = rp[1] - '0';
- if(subs[num].rm_so != -1 && subs[num].rm_eo != -1)
- tcxstrcat(xstr, sp + subs[num].rm_so, subs[num].rm_eo - subs[num].rm_so);
- ++rp;
- } else if(rp[1] != '\0'){
- tcxstrcat(xstr, ++rp, 1);
- }
- } else if(*rp == '&'){
- tcxstrcat(xstr, sp + subs[0].rm_so, subs[0].rm_eo - subs[0].rm_so);
- } else {
- tcxstrcat(xstr, rp, 1);
- }
- }
- sp += subs[0].rm_eo;
- if(subs[0].rm_eo < 1) break;
- }
- tcxstrcat2(xstr, sp);
- regfree(&rbuf);
- return tcxstrtomalloc(xstr);
-}
-
-
-/* Get the time of day in seconds. */
-double tctime(void){
- struct timeval tv;
- if(gettimeofday(&tv, NULL) == -1) return 0.0;
- return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
-}
-
-
-/* Get the Gregorian calendar of a time. */
-void tccalendar(int64_t t, int jl, int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp){
- if(t == INT64_MAX || jl == INT_MAX){
- struct timeval tv;
- struct timezone tz;
- if(gettimeofday(&tv, &tz) == 0){
- if(t == INT64_MAX) t = tv.tv_sec;
- if(jl == INT_MAX) jl = tz.tz_minuteswest * -60;
- } else {
- if(yearp) *yearp = 0;
- if(monp) *monp = 0;
- if(dayp) *dayp = 0;
- if(hourp) *hourp = 0;
- if(minp) *minp = 0;
- if(secp) *secp = 0;
- }
- }
- time_t tt = (time_t)t + jl;
- struct tm ts;
- if(!gmtime_r(&tt, &ts)){
- if(yearp) *yearp = 0;
- if(monp) *monp = 0;
- if(dayp) *dayp = 0;
- if(hourp) *hourp = 0;
- if(minp) *minp = 0;
- if(secp) *secp = 0;
- }
- if(yearp) *yearp = ts.tm_year + 1900;
- if(monp) *monp = ts.tm_mon + 1;
- if(dayp) *dayp = ts.tm_mday;
- if(hourp) *hourp = ts.tm_hour;
- if(minp) *minp = ts.tm_min;
- if(secp) *secp = ts.tm_sec;
-}
-
-
-/* Format a date as a string in W3CDTF. */
-void tcdatestrwww(int64_t t, int jl, char *buf){
- assert(buf);
- if(t == INT64_MAX || jl == INT_MAX){
- struct timeval tv;
- struct timezone tz;
- if(gettimeofday(&tv, &tz) == 0){
- if(t == INT64_MAX) t = tv.tv_sec;
- if(jl == INT_MAX) jl = tz.tz_minuteswest * -60;
- } else {
- if(t == INT64_MAX) t = time(NULL);
- if(jl == INT_MAX) jl = 0;
- }
- }
- time_t tt = (time_t)t + jl;
- struct tm ts;
- if(!gmtime_r(&tt, &ts)) memset(&ts, 0, sizeof(ts));
- ts.tm_year += 1900;
- ts.tm_mon += 1;
- jl /= 60;
- char tzone[16];
- if(jl == 0){
- sprintf(tzone, "Z");
- } else if(jl < 0){
- jl *= -1;
- sprintf(tzone, "-%02d:%02d", jl / 60, jl % 60);
- } else {
- sprintf(tzone, "+%02d:%02d", jl / 60, jl % 60);
- }
- sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d%s",
- ts.tm_year, ts.tm_mon, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, tzone);
-}
-
-
-/* Format a date as a string in RFC 1123 format. */
-void tcdatestrhttp(int64_t t, int jl, char *buf){
- assert(buf);
- if(t == INT64_MAX || jl == INT_MAX){
- struct timeval tv;
- struct timezone tz;
- if(gettimeofday(&tv, &tz) == 0){
- if(t == INT64_MAX) t = tv.tv_sec;
- if(jl == INT_MAX) jl = tz.tz_minuteswest * -60;
- } else {
- if(t == INT64_MAX) t = time(NULL);
- if(jl == INT_MAX) jl = 0;
- }
- }
- time_t tt = (time_t)t + jl;
- struct tm ts;
- if(!gmtime_r(&tt, &ts)) memset(&ts, 0, sizeof(ts));
- ts.tm_year += 1900;
- ts.tm_mon += 1;
- jl /= 60;
- char *wp = buf;
- switch(tcdayofweek(ts.tm_year, ts.tm_mon, ts.tm_mday)){
- case 0: wp += sprintf(wp, "Sun, "); break;
- case 1: wp += sprintf(wp, "Mon, "); break;
- case 2: wp += sprintf(wp, "Tue, "); break;
- case 3: wp += sprintf(wp, "Wed, "); break;
- case 4: wp += sprintf(wp, "Thu, "); break;
- case 5: wp += sprintf(wp, "Fri, "); break;
- case 6: wp += sprintf(wp, "Sat, "); break;
- }
- wp += sprintf(wp, "%02d ", ts.tm_mday);
- switch(ts.tm_mon){
- case 1: wp += sprintf(wp, "Jan "); break;
- case 2: wp += sprintf(wp, "Feb "); break;
- case 3: wp += sprintf(wp, "Mar "); break;
- case 4: wp += sprintf(wp, "Apr "); break;
- case 5: wp += sprintf(wp, "May "); break;
- case 6: wp += sprintf(wp, "Jun "); break;
- case 7: wp += sprintf(wp, "Jul "); break;
- case 8: wp += sprintf(wp, "Aug "); break;
- case 9: wp += sprintf(wp, "Sep "); break;
- case 10: wp += sprintf(wp, "Oct "); break;
- case 11: wp += sprintf(wp, "Nov "); break;
- case 12: wp += sprintf(wp, "Dec "); break;
- }
- wp += sprintf(wp, "%04d %02d:%02d:%02d ", ts.tm_year, ts.tm_hour, ts.tm_min, ts.tm_sec);
- if(jl == 0){
- sprintf(wp, "GMT");
- } else if(jl < 0){
- jl *= -1;
- sprintf(wp, "-%02d%02d", jl / 60, jl % 60);
- } else {
- sprintf(wp, "+%02d%02d", jl / 60, jl % 60);
- }
-}
-
-
-/* Get the time value of a date string. */
-int64_t tcstrmktime(const char *str){
- assert(str);
- while(*str > '\0' && *str <= ' '){
- str++;
- }
- if(*str == '\0') return 0;
- if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
- return (int64_t)strtoll(str + 2, NULL, 16);
- struct tm ts;
- memset(&ts, 0, sizeof(ts));
- ts.tm_year = 70;
- ts.tm_mon = 0;
- ts.tm_mday = 1;
- ts.tm_hour = 0;
- ts.tm_min = 0;
- ts.tm_sec = 0;
- ts.tm_isdst = 0;
- int len = strlen(str);
- char *pv;
- time_t t = (time_t)strtoll(str, &pv, 10);
- if(*(signed char *)pv >= '\0' && *pv <= ' '){
- while(*pv > '\0' && *pv <= ' '){
- pv++;
- }
- if(*pv == '\0') return (int64_t)t;
- }
- if((pv[0] == 's' || pv[0] == 'S') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ')
- return (int64_t)t;
- if((pv[0] == 'm' || pv[0] == 'M') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ')
- return (int64_t)t * 60;
- if((pv[0] == 'h' || pv[0] == 'H') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ')
- return (int64_t)t * 60 * 60;
- if((pv[0] == 'd' || pv[0] == 'D') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ')
- return (int64_t)t * 60 * 60 * 24;
- if(len > 4 && str[4] == '-'){
- ts.tm_year = atoi(str) - 1900;
- if((pv = strchr(str, '-')) != NULL && pv - str == 4){
- char *rp = pv + 1;
- ts.tm_mon = atoi(rp) - 1;
- if((pv = strchr(rp, '-')) != NULL && pv - str == 7){
- rp = pv + 1;
- ts.tm_mday = atoi(rp);
- if((pv = strchr(rp, 'T')) != NULL && pv - str == 10){
- rp = pv + 1;
- ts.tm_hour = atoi(rp);
- if((pv = strchr(rp, ':')) != NULL && pv - str == 13){
- rp = pv + 1;
- ts.tm_min = atoi(rp);
- }
- if((pv = strchr(rp, ':')) != NULL && pv - str == 16){
- rp = pv + 1;
- ts.tm_sec = atoi(rp);
- }
- if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1;
- strtol(rp, &pv, 10);
- if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':')
- ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1);
- }
- }
- }
- return (int64_t)tcmkgmtime(&ts);
- }
- if(len > 4 && str[4] == '/'){
- ts.tm_year = atoi(str) - 1900;
- if((pv = strchr(str, '/')) != NULL && pv - str == 4){
- char *rp = pv + 1;
- ts.tm_mon = atoi(rp) - 1;
- if((pv = strchr(rp, '/')) != NULL && pv - str == 7){
- rp = pv + 1;
- ts.tm_mday = atoi(rp);
- if((pv = strchr(rp, ' ')) != NULL && pv - str == 10){
- rp = pv + 1;
- ts.tm_hour = atoi(rp);
- if((pv = strchr(rp, ':')) != NULL && pv - str == 13){
- rp = pv + 1;
- ts.tm_min = atoi(rp);
- }
- if((pv = strchr(rp, ':')) != NULL && pv - str == 16){
- rp = pv + 1;
- ts.tm_sec = atoi(rp);
- }
- if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1;
- strtol(rp, &pv, 10);
- if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':')
- ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1);
- }
- }
- }
- return (int64_t)tcmkgmtime(&ts);
- }
- const char *crp = str;
- if(len >= 4 && str[3] == ',') crp = str + 4;
- while(*crp == ' '){
- crp++;
- }
- ts.tm_mday = atoi(crp);
- while((*crp >= '0' && *crp <= '9') || *crp == ' '){
- crp++;
- }
- if(tcstrifwm(crp, "Jan")){
- ts.tm_mon = 0;
- } else if(tcstrifwm(crp, "Feb")){
- ts.tm_mon = 1;
- } else if(tcstrifwm(crp, "Mar")){
- ts.tm_mon = 2;
- } else if(tcstrifwm(crp, "Apr")){
- ts.tm_mon = 3;
- } else if(tcstrifwm(crp, "May")){
- ts.tm_mon = 4;
- } else if(tcstrifwm(crp, "Jun")){
- ts.tm_mon = 5;
- } else if(tcstrifwm(crp, "Jul")){
- ts.tm_mon = 6;
- } else if(tcstrifwm(crp, "Aug")){
- ts.tm_mon = 7;
- } else if(tcstrifwm(crp, "Sep")){
- ts.tm_mon = 8;
- } else if(tcstrifwm(crp, "Oct")){
- ts.tm_mon = 9;
- } else if(tcstrifwm(crp, "Nov")){
- ts.tm_mon = 10;
- } else if(tcstrifwm(crp, "Dec")){
- ts.tm_mon = 11;
- } else {
- ts.tm_mon = -1;
- }
- if(ts.tm_mon >= 0) crp += 3;
- while(*crp == ' '){
- crp++;
- }
- ts.tm_year = atoi(crp);
- if(ts.tm_year >= 1969) ts.tm_year -= 1900;
- while(*crp >= '0' && *crp <= '9'){
- crp++;
- }
- while(*crp == ' '){
- crp++;
- }
- if(ts.tm_mday > 0 && ts.tm_mon >= 0 && ts.tm_year >= 0){
- int clen = strlen(crp);
- if(clen >= 8 && crp[2] == ':' && crp[5] == ':'){
- ts.tm_hour = atoi(crp + 0);
- ts.tm_min = atoi(crp + 3);
- ts.tm_sec = atoi(crp + 6);
- if(clen >= 14 && crp[8] == ' ' && (crp[9] == '+' || crp[9] == '-')){
- ts.tm_sec -= ((crp[10] - '0') * 36000 + (crp[11] - '0') * 3600 +
- (crp[12] - '0') * 600 + (crp[13] - '0') * 60) * (crp[9] == '+' ? 1 : -1);
- } else if(clen > 9){
- if(!strcmp(crp + 9, "JST")){
- ts.tm_sec -= 9 * 3600;
- } else if(!strcmp(crp + 9, "CCT")){
- ts.tm_sec -= 8 * 3600;
- } else if(!strcmp(crp + 9, "KST")){
- ts.tm_sec -= 9 * 3600;
- } else if(!strcmp(crp + 9, "EDT")){
- ts.tm_sec -= -4 * 3600;
- } else if(!strcmp(crp + 9, "EST")){
- ts.tm_sec -= -5 * 3600;
- } else if(!strcmp(crp + 9, "CDT")){
- ts.tm_sec -= -5 * 3600;
- } else if(!strcmp(crp + 9, "CST")){
- ts.tm_sec -= -6 * 3600;
- } else if(!strcmp(crp + 9, "MDT")){
- ts.tm_sec -= -6 * 3600;
- } else if(!strcmp(crp + 9, "MST")){
- ts.tm_sec -= -7 * 3600;
- } else if(!strcmp(crp + 9, "PDT")){
- ts.tm_sec -= -7 * 3600;
- } else if(!strcmp(crp + 9, "PST")){
- ts.tm_sec -= -8 * 3600;
- } else if(!strcmp(crp + 9, "HDT")){
- ts.tm_sec -= -9 * 3600;
- } else if(!strcmp(crp + 9, "HST")){
- ts.tm_sec -= -10 * 3600;
- }
- }
- }
- return (int64_t)tcmkgmtime(&ts);
- }
- return 0;
-}
-
-
-/* Get the day of week of a date. */
-int tcdayofweek(int year, int mon, int day){
- if(mon < 3){
- year--;
- mon += 12;
- }
- return (day + ((8 + (13 * mon)) / 5) + (year + (year / 4) - (year / 100) + (year / 400))) % 7;
-}
-
-
-/* Close the random number generator. */
-static void tcrandomfdclose(void){
- close(tcrandomdevfd);
-}
-
-
-/* Make the GMT from a time structure.
- `tm' specifies the pointer to the time structure.
- The return value is the GMT. */
-static time_t tcmkgmtime(struct tm *tm){
-#if defined(_SYS_LINUX_)
- assert(tm);
- return timegm(tm);
-#else
- assert(tm);
- static int jl = INT_MAX;
- if(jl == INT_MAX){
- struct timeval tv;
- struct timezone tz;
- if(gettimeofday(&tv, &tz) == 0){
- jl = tz.tz_minuteswest * -60;
- } else {
- jl = 0;
- }
- }
- tm->tm_sec += jl;
- return mktime(tm);
-#endif
-}
-
-
-
-/*************************************************************************************************
- * filesystem utilities
- *************************************************************************************************/
-
-
-#define TCFILEMODE 00644 // permission of a creating file
-#define TCIOBUFSIZ 16384 // size of an I/O buffer
-
-
-/* Get the canonicalized absolute path of a file. */
-char *tcrealpath(const char *path){
- assert(path);
- char buf[PATH_MAX];
- if(!realpath(path, buf)) return NULL;
- return tcstrdup(buf);
-}
-
-
-/* Read whole data of a file. */
-void *tcreadfile(const char *path, int limit, int *sp){
- int fd = path ? open(path, O_RDONLY, TCFILEMODE) : 0;
- if(fd == -1) return NULL;
- if(fd == 0){
- TCXSTR *xstr = tcxstrnew();
- char buf[TCIOBUFSIZ];
- limit = limit > 0 ? limit : INT_MAX;
- int rsiz;
- while((rsiz = read(fd, buf, tclmin(TCIOBUFSIZ, limit))) > 0){
- TCXSTRCAT(xstr, buf, rsiz);
- limit -= rsiz;
- }
- if(sp) *sp = TCXSTRSIZE(xstr);
- return tcxstrtomalloc(xstr);
- }
- struct stat sbuf;
- if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){
- close(fd);
- return NULL;
- }
- limit = limit > 0 ? tclmin((int)sbuf.st_size, limit) : sbuf.st_size;
- char *buf;
- TCMALLOC(buf, sbuf.st_size + 1);
- char *wp = buf;
- int rsiz;
- while((rsiz = read(fd, wp, limit - (wp - buf))) > 0){
- wp += rsiz;
- }
- *wp = '\0';
- close(fd);
- if(sp) *sp = wp - buf;
- return buf;
-}
-
-
-/* Read every line of a file. */
-TCLIST *tcreadfilelines(const char *path){
- int fd = path ? open(path, O_RDONLY, TCFILEMODE) : 0;
- if(fd == -1) return NULL;
- TCLIST *list = tclistnew();
- TCXSTR *xstr = tcxstrnew();
- char buf[TCIOBUFSIZ];
- int rsiz;
- while((rsiz = read(fd, buf, TCIOBUFSIZ)) > 0){
- for(int i = 0; i < rsiz; i++){
- switch(buf[i]){
- case '\r':
- break;
- case '\n':
- TCLISTPUSH(list, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
- tcxstrclear(xstr);
- break;
- default:
- TCXSTRCAT(xstr, buf + i, 1);
- break;
- }
- }
- }
- TCLISTPUSH(list, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
- tcxstrdel(xstr);
- if(path) close(fd);
- return list;
-}
-
-
-/* Write data into a file. */
-bool tcwritefile(const char *path, const void *ptr, int size){
- assert(ptr && size >= 0);
- int fd = 1;
- if(path && (fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, TCFILEMODE)) == -1) return false;
- bool err = false;
- if(!tcwrite(fd, ptr, size)) err = true;
- if(close(fd) == -1) err = true;
- return !err;
-}
-
-
-/* Copy a file. */
-bool tccopyfile(const char *src, const char *dest){
- int ifd = open(src, O_RDONLY, TCFILEMODE);
- if(ifd == -1) return false;
- int ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, TCFILEMODE);
- if(ofd == -1){
- close(ifd);
- return false;
- }
- bool err = false;
- while(true){
- char buf[TCIOBUFSIZ];
- int size = read(ifd, buf, TCIOBUFSIZ);
- if(size > 0){
- if(!tcwrite(ofd, buf, size)){
- err = true;
- break;
- }
- } else if(size == -1){
- if(errno != EINTR){
- err = true;
- break;
- }
- } else {
- break;
- }
- }
- if(close(ofd) == -1) err = true;
- if(close(ifd) == -1) err = true;
- return !err;
-}
-
-
-/* Read names of files in a directory. */
-TCLIST *tcreaddir(const char *path){
- assert(path);
- DIR *DD;
- struct dirent *dp;
- if(!(DD = opendir(path))) return NULL;
- TCLIST *list = tclistnew();
- while((dp = readdir(DD)) != NULL){
- if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue;
- TCLISTPUSH(list, dp->d_name, strlen(dp->d_name));
- }
- closedir(DD);
- return list;
-}
-
-
-/* Expand a pattern into a list of matched paths. */
-TCLIST *tcglobpat(const char *pattern){
- assert(pattern);
- TCLIST *list = tclistnew();
- glob_t gbuf;
- memset(&gbuf, 0, sizeof(gbuf));
- if(glob(pattern, GLOB_ERR | GLOB_NOSORT, NULL, &gbuf) == 0){
- for(int i = 0; i < gbuf.gl_pathc; i++){
- tclistpush2(list, gbuf.gl_pathv[i]);
- }
- globfree(&gbuf);
- }
- return list;
-}
-
-
-/* Remove a file or a directory and its sub ones recursively. */
-bool tcremovelink(const char *path){
- assert(path);
- struct stat sbuf;
- if(lstat(path, &sbuf) == -1) return false;
- if(unlink(path) == 0) return true;
- TCLIST *list;
- if(!S_ISDIR(sbuf.st_mode) || !(list = tcreaddir(path))) return false;
- bool tail = path[0] != '\0' && path[strlen(path)-1] == MYPATHCHR;
- for(int i = 0; i < TCLISTNUM(list); i++){
- const char *elem = TCLISTVALPTR(list, i);
- if(!strcmp(MYCDIRSTR, elem) || !strcmp(MYPDIRSTR, elem)) continue;
- char *cpath;
- if(tail){
- cpath = tcsprintf("%s%s", path, elem);
- } else {
- cpath = tcsprintf("%s%c%s", path, MYPATHCHR, elem);
- }
- tcremovelink(cpath);
- free(cpath);
- }
- tclistdel(list);
- return rmdir(path) == 0 ? true : false;
-}
-
-
-/* Write data into a file. */
-bool tcwrite(int fd, const void *buf, size_t size){
- assert(fd >= 0 && buf && size >= 0);
- const char *rp = buf;
- do {
- int wb = write(fd, rp, size);
- switch(wb){
- case -1: if(errno != EINTR) return false;
- case 0: break;
- default:
- rp += wb;
- size -= wb;
- break;
- }
- } while(size > 0);
- return true;
-}
-
-
-/* Read data from a file. */
-bool tcread(int fd, void *buf, size_t size){
- assert(fd >= 0 && buf && size >= 0);
- char *wp = buf;
- do {
- int rb = read(fd, wp, size);
- switch(rb){
- case -1: if(errno != EINTR) return false;
- case 0: return size < 1;
- default:
- wp += rb;
- size -= rb;
- }
- } while(size > 0);
- return true;
-}
-
-
-/* Lock a file. */
-bool tclock(int fd, bool ex, bool nb){
- assert(fd >= 0);
- struct flock lock;
- memset(&lock, 0, sizeof(struct flock));
- lock.l_type = ex ? F_WRLCK : F_RDLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
- lock.l_pid = 0;
- while(fcntl(fd, nb ? F_SETLK : F_SETLKW, &lock) == -1){
- if(errno != EINTR) return false;
- }
- return true;
-}
-
-
-
-/*************************************************************************************************
- * encoding utilities
- *************************************************************************************************/
-
-
-#define TCURLELBNUM 31 // bucket number of URL elements
-#define TCENCBUFSIZ 32 // size of a buffer for encoding name
-#define TCXMLATBNUM 31 // bucket number of XML attributes
-
-
-/* Encode a serial object with URL encoding. */
-char *tcurlencode(const char *ptr, int size){
- assert(ptr && size >= 0);
- char *buf;
- TCMALLOC(buf, size * 3 + 1);
- char *wp = buf;
- for(int i = 0; i < size; i++){
- int c = ((unsigned char *)ptr)[i];
- if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.!~*'()", c))){
- *(wp++) = c;
- } else {
- wp += sprintf(wp, "%%%02X", c);
- }
- }
- *wp = '\0';
- return buf;
-}
-
-
-/* Decode a string encoded with URL encoding. */
-char *tcurldecode(const char *str, int *sp){
- assert(str && sp);
- char *buf = tcstrdup(str);
- char *wp = buf;
- while(*str != '\0'){
- if(*str == '%'){
- str++;
- if(((str[0] >= '0' && str[0] <= '9') || (str[0] >= 'A' && str[0] <= 'F') ||
- (str[0] >= 'a' && str[0] <= 'f')) &&
- ((str[1] >= '0' && str[1] <= '9') || (str[1] >= 'A' && str[1] <= 'F') ||
- (str[1] >= 'a' && str[1] <= 'f'))){
- unsigned char c = *str;
- if(c >= 'A' && c <= 'Z') c += 'a' - 'A';
- if(c >= 'a' && c <= 'z'){
- *wp = c - 'a' + 10;
- } else {
- *wp = c - '0';
- }
- *wp *= 0x10;
- str++;
- c = *str;
- if(c >= 'A' && c <= 'Z') c += 'a' - 'A';
- if(c >= 'a' && c <= 'z'){
- *wp += c - 'a' + 10;
- } else {
- *wp += c - '0';
- }
- str++;
- wp++;
- } else {
- break;
- }
- } else if(*str == '+'){
- *wp = ' ';
- str++;
- wp++;
- } else {
- *wp = *str;
- str++;
- wp++;
- }
- }
- *wp = '\0';
- *sp = wp - buf;
- return buf;
-}
-
-
-/* Break up a URL into elements. */
-TCMAP *tcurlbreak(const char *str){
- assert(str);
- TCMAP *map = tcmapnew2(TCURLELBNUM);
- char *tmp = tcstrdup(str);
- const char *rp = tcstrtrim(tmp);
- tcmapput2(map, "self", rp);
- bool serv = false;
- if(tcstrifwm(rp, "http://")){
- tcmapput2(map, "scheme", "http");
- rp += 7;
- serv = true;
- } else if(tcstrifwm(rp, "https://")){
- tcmapput2(map, "scheme", "https");
- rp += 8;
- serv = true;
- } else if(tcstrifwm(rp, "ftp://")){
- tcmapput2(map, "scheme", "ftp");
- rp += 6;
- serv = true;
- } else if(tcstrifwm(rp, "sftp://")){
- tcmapput2(map, "scheme", "sftp");
- rp += 7;
- serv = true;
- } else if(tcstrifwm(rp, "ftps://")){
- tcmapput2(map, "scheme", "ftps");
- rp += 7;
- serv = true;
- } else if(tcstrifwm(rp, "tftp://")){
- tcmapput2(map, "scheme", "tftp");
- rp += 7;
- serv = true;
- } else if(tcstrifwm(rp, "ldap://")){
- tcmapput2(map, "scheme", "ldap");
- rp += 7;
- serv = true;
- } else if(tcstrifwm(rp, "ldaps://")){
- tcmapput2(map, "scheme", "ldaps");
- rp += 8;
- serv = true;
- } else if(tcstrifwm(rp, "file://")){
- tcmapput2(map, "scheme", "file");
- rp += 7;
- serv = true;
- }
- char *ep;
- if((ep = strchr(rp, '#')) != NULL){
- tcmapput2(map, "fragment", ep + 1);
- *ep = '\0';
- }
- if((ep = strchr(rp, '?')) != NULL){
- tcmapput2(map, "query", ep + 1);
- *ep = '\0';
- }
- if(serv){
- if((ep = strchr(rp, '/')) != NULL){
- tcmapput2(map, "path", ep);
- *ep = '\0';
- } else {
- tcmapput2(map, "path", "/");
- }
- if((ep = strchr(rp, '@')) != NULL){
- *ep = '\0';
- if(rp[0] != '\0') tcmapput2(map, "authority", rp);
- rp = ep + 1;
- }
- if((ep = strchr(rp, ':')) != NULL){
- if(ep[1] != '\0') tcmapput2(map, "port", ep + 1);
- *ep = '\0';
- }
- if(rp[0] != '\0') tcmapput2(map, "host", rp);
- } else {
- tcmapput2(map, "path", rp);
- }
- free(tmp);
- if((rp = tcmapget2(map, "path")) != NULL){
- if((ep = strrchr(rp, '/')) != NULL){
- if(ep[1] != '\0') tcmapput2(map, "file", ep + 1);
- } else {
- tcmapput2(map, "file", rp);
- }
- }
- if((rp = tcmapget2(map, "file")) != NULL && (!strcmp(rp, ".") || !strcmp(rp, "..")))
- tcmapout2(map, "file");
- return map;
-}
-
-
-/* Resolve a relative URL with an absolute URL. */
-char *tcurlresolve(const char *base, const char *target){
- assert(base && target);
- const char *vbuf, *path;
- char *tmp, *wp, *enc;
- while(*base > '\0' && *base <= ' '){
- base++;
- }
- while(*target > '\0' && *target <= ' '){
- target++;
- }
- if(*target == '\0') target = base;
- TCXSTR *rbuf = tcxstrnew();
- TCMAP *telems = tcurlbreak(target);
- int port = 80;
- TCMAP *belems = tcurlbreak(tcmapget2(telems, "scheme") ? target : base);
- if((vbuf = tcmapget2(belems, "scheme")) != NULL){
- tcxstrcat2(rbuf, vbuf);
- TCXSTRCAT(rbuf, "://", 3);
- if(!tcstricmp(vbuf, "https")){
- port = 443;
- } else if(!tcstricmp(vbuf, "ftp")){
- port = 21;
- } else if(!tcstricmp(vbuf, "sftp")){
- port = 115;
- } else if(!tcstricmp(vbuf, "ftps")){
- port = 22;
- } else if(!tcstricmp(vbuf, "tftp")){
- port = 69;
- } else if(!tcstricmp(vbuf, "ldap")){
- port = 389;
- } else if(!tcstricmp(vbuf, "ldaps")){
- port = 636;
- }
- } else {
- tcxstrcat2(rbuf, "http://");
- }
- int vsiz;
- if((vbuf = tcmapget2(belems, "authority")) != NULL){
- if((wp = strchr(vbuf, ':')) != NULL){
- *wp = '\0';
- tmp = tcurldecode(vbuf, &vsiz);
- enc = tcurlencode(tmp, vsiz);
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- TCXSTRCAT(rbuf, ":", 1);
- wp++;
- tmp = tcurldecode(wp, &vsiz);
- enc = tcurlencode(tmp, vsiz);
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- } else {
- tmp = tcurldecode(vbuf, &vsiz);
- enc = tcurlencode(tmp, vsiz);
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- }
- TCXSTRCAT(rbuf, "@", 1);
- }
- if((vbuf = tcmapget2(belems, "host")) != NULL){
- tmp = tcurldecode(vbuf, &vsiz);
- tcstrtolower(tmp);
- enc = tcurlencode(tmp, vsiz);
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- } else {
- TCXSTRCAT(rbuf, "localhost", 9);
- }
- int num;
- char numbuf[TCNUMBUFSIZ];
- if((vbuf = tcmapget2(belems, "port")) != NULL && (num = atoi(vbuf)) != port && num > 0){
- sprintf(numbuf, ":%d", num);
- tcxstrcat2(rbuf, numbuf);
- }
- if(!(path = tcmapget2(telems, "path"))) path = "/";
- if(path[0] == '\0' && (vbuf = tcmapget2(belems, "path")) != NULL) path = vbuf;
- if(path[0] == '\0') path = "/";
- TCLIST *bpaths = tclistnew();
- TCLIST *opaths;
- if(path[0] != '/' && (vbuf = tcmapget2(belems, "path")) != NULL){
- opaths = tcstrsplit(vbuf, "/");
- } else {
- opaths = tcstrsplit("/", "/");
- }
- free(tclistpop2(opaths));
- for(int i = 0; i < TCLISTNUM(opaths); i++){
- vbuf = tclistval(opaths, i, &vsiz);
- if(vsiz < 1 || !strcmp(vbuf, ".")) continue;
- if(!strcmp(vbuf, "..")){
- free(tclistpop2(bpaths));
- } else {
- TCLISTPUSH(bpaths, vbuf, vsiz);
- }
- }
- tclistdel(opaths);
- opaths = tcstrsplit(path, "/");
- for(int i = 0; i < TCLISTNUM(opaths); i++){
- vbuf = tclistval(opaths, i, &vsiz);
- if(vsiz < 1 || !strcmp(vbuf, ".")) continue;
- if(!strcmp(vbuf, "..")){
- free(tclistpop2(bpaths));
- } else {
- TCLISTPUSH(bpaths, vbuf, vsiz);
- }
- }
- tclistdel(opaths);
- for(int i = 0; i < TCLISTNUM(bpaths); i++){
- vbuf = TCLISTVALPTR(bpaths, i);
- if(strchr(vbuf, '%')){
- tmp = tcurldecode(vbuf, &vsiz);
- } else {
- tmp = tcstrdup(vbuf);
- }
- enc = tcurlencode(tmp, strlen(tmp));
- TCXSTRCAT(rbuf, "/", 1);
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- }
- if(tcstrbwm(path, "/")) TCXSTRCAT(rbuf, "/", 1);
- tclistdel(bpaths);
- if((vbuf = tcmapget2(telems, "query")) != NULL ||
- (*target == '#' && (vbuf = tcmapget2(belems, "query")) != NULL)){
- TCXSTRCAT(rbuf, "?", 1);
- TCLIST *qelems = tcstrsplit(vbuf, "&;");
- for(int i = 0; i < TCLISTNUM(qelems); i++){
- vbuf = TCLISTVALPTR(qelems, i);
- if(i > 0) TCXSTRCAT(rbuf, "&", 1);
- if((wp = strchr(vbuf, '=')) != NULL){
- *wp = '\0';
- tmp = tcurldecode(vbuf, &vsiz);
- enc = tcurlencode(tmp, vsiz);
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- TCXSTRCAT(rbuf, "=", 1);
- wp++;
- tmp = tcurldecode(wp, &vsiz);
- enc = tcurlencode(tmp, strlen(tmp));
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- } else {
- tmp = tcurldecode(vbuf, &vsiz);
- enc = tcurlencode(tmp, vsiz);
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- }
- }
- tclistdel(qelems);
- }
- if((vbuf = tcmapget2(telems, "fragment")) != NULL){
- tmp = tcurldecode(vbuf, &vsiz);
- enc = tcurlencode(tmp, vsiz);
- TCXSTRCAT(rbuf, "#", 1);
- tcxstrcat2(rbuf, enc);
- free(enc);
- free(tmp);
- }
- tcmapdel(belems);
- tcmapdel(telems);
- return tcxstrtomalloc(rbuf);
-}
-
-
-/* Encode a serial object with Base64 encoding. */
-char *tcbaseencode(const char *ptr, int size){
- assert(ptr && size >= 0);
- char *tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- const unsigned char *obj = (const unsigned char *)ptr;
- char *buf;
- TCMALLOC(buf, 4 * (size + 2) / 3 + 1);
- char *wp = buf;
- for(int i = 0; i < size; i += 3){
- switch(size - i){
- case 1:
- *wp++ = tbl[obj[0] >> 2];
- *wp++ = tbl[(obj[0] & 3) << 4];
- *wp++ = '=';
- *wp++ = '=';
- break;
- case 2:
- *wp++ = tbl[obj[0] >> 2];
- *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)];
- *wp++ = tbl[(obj[1] & 0xf) << 2];
- *wp++ = '=';
- break;
- default:
- *wp++ = tbl[obj[0] >> 2];
- *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)];
- *wp++ = tbl[((obj[1] & 0xf) << 2) + (obj[2] >> 6)];
- *wp++ = tbl[obj[2] & 0x3f];
- break;
- }
- obj += 3;
- }
- *wp = '\0';
- return buf;
-}
-
-
-/* Decode a string encoded with Base64 encoding. */
-char *tcbasedecode(const char *str, int *sp){
- assert(str && sp);
- int cnt = 0;
- int bpos = 0;
- int eqcnt = 0;
- int len = strlen(str);
- unsigned char *obj;
- TCMALLOC(obj, len + 4);
- unsigned char *wp = obj;
- while(bpos < len && eqcnt == 0){
- int bits = 0;
- int i;
- for(i = 0; bpos < len && i < 4; bpos++){
- if(str[bpos] >= 'A' && str[bpos] <= 'Z'){
- bits = (bits << 6) | (str[bpos] - 'A');
- i++;
- } else if(str[bpos] >= 'a' && str[bpos] <= 'z'){
- bits = (bits << 6) | (str[bpos] - 'a' + 26);
- i++;
- } else if(str[bpos] >= '0' && str[bpos] <= '9'){
- bits = (bits << 6) | (str[bpos] - '0' + 52);
- i++;
- } else if(str[bpos] == '+'){
- bits = (bits << 6) | 62;
- i++;
- } else if(str[bpos] == '/'){
- bits = (bits << 6) | 63;
- i++;
- } else if(str[bpos] == '='){
- bits <<= 6;
- i++;
- eqcnt++;
- }
- }
- if(i == 0 && bpos >= len) continue;
- switch(eqcnt){
- case 0:
- *wp++ = (bits >> 16) & 0xff;
- *wp++ = (bits >> 8) & 0xff;
- *wp++ = bits & 0xff;
- cnt += 3;
- break;
- case 1:
- *wp++ = (bits >> 16) & 0xff;
- *wp++ = (bits >> 8) & 0xff;
- cnt += 2;
- break;
- case 2:
- *wp++ = (bits >> 16) & 0xff;
- cnt += 1;
- break;
- }
- }
- obj[cnt] = '\0';
- *sp = cnt;
- return (char *)obj;
-}
-
-
-/* Encode a serial object with Quoted-printable encoding. */
-char *tcquoteencode(const char *ptr, int size){
- assert(ptr && size >= 0);
- const unsigned char *rp = (const unsigned char *)ptr;
- char *buf;
- TCMALLOC(buf, size * 3 + 1);
- char *wp = buf;
- int cols = 0;
- for(int i = 0; i < size; i++){
- if(rp[i] == '=' || (rp[i] < 0x20 && rp[i] != '\r' && rp[i] != '\n' && rp[i] != '\t') ||
- rp[i] > 0x7e){
- wp += sprintf(wp, "=%02X", rp[i]);
- cols += 3;
- } else {
- *(wp++) = rp[i];
- cols++;
- }
- }
- *wp = '\0';
- return buf;
-}
-
-
-/* Decode a string encoded with Quoted-printable encoding. */
-char *tcquotedecode(const char *str, int *sp){
- assert(str && sp);
- char *buf;
- TCMALLOC(buf, strlen(str) + 1);
- char *wp = buf;
- for(; *str != '\0'; str++){
- if(*str == '='){
- str++;
- if(*str == '\0'){
- break;
- } else if(str[0] == '\r' && str[1] == '\n'){
- str++;
- } else if(str[0] != '\n' && str[0] != '\r'){
- if(*str >= 'A' && *str <= 'Z'){
- *wp = (*str - 'A' + 10) * 16;
- } else if(*str >= 'a' && *str <= 'z'){
- *wp = (*str - 'a' + 10) * 16;
- } else {
- *wp = (*str - '0') * 16;
- }
- str++;
- if(*str == '\0') break;
- if(*str >= 'A' && *str <= 'Z'){
- *wp += *str - 'A' + 10;
- } else if(*str >= 'a' && *str <= 'z'){
- *wp += *str - 'a' + 10;
- } else {
- *wp += *str - '0';
- }
- wp++;
- }
- } else {
- *wp = *str;
- wp++;
- }
- }
- *wp = '\0';
- *sp = wp - buf;
- return buf;
-}
-
-
-/* Encode a string with MIME encoding. */
-char *tcmimeencode(const char *str, const char *encname, bool base){
- assert(str && encname);
- int len = strlen(str);
- char *buf;
- TCMALLOC(buf, len * 3 + strlen(encname) + 16);
- char *wp = buf;
- wp += sprintf(wp, "=?%s?%c?", encname, base ? 'B' : 'Q');
- char *enc = base ? tcbaseencode(str, len) : tcquoteencode(str, len);
- wp += sprintf(wp, "%s?=", enc);
- free(enc);
- return buf;
-}
-
-
-/* Decode a string encoded with MIME encoding. */
-char *tcmimedecode(const char *str, char *enp){
- assert(str);
- if(enp) sprintf(enp, "US-ASCII");
- char *buf;
- TCMALLOC(buf, strlen(str) + 1);
- char *wp = buf;
- while(*str != '\0'){
- if(tcstrfwm(str, "=?")){
- str += 2;
- const char *pv = str;
- const char *ep = strchr(str, '?');
- if(!ep) continue;
- if(enp && ep - pv < TCENCBUFSIZ){
- memcpy(enp, pv, ep - pv);
- enp[ep-pv] = '\0';
- }
- pv = ep + 1;
- bool quoted = (*pv == 'Q' || *pv == 'q');
- if(*pv != '\0') pv++;
- if(*pv != '\0') pv++;
- if(!(ep = strchr(pv, '?'))) continue;
- char *tmp;
- TCMEMDUP(tmp, pv, ep - pv);
- int len;
- char *dec = quoted ? tcquotedecode(tmp, &len) : tcbasedecode(tmp, &len);
- wp += sprintf(wp, "%s", dec);
- free(dec);
- free(tmp);
- str = ep + 1;
- if(*str != '\0') str++;
- } else {
- *(wp++) = *str;
- str++;
- }
- }
- *wp = '\0';
- return buf;
-}
-
-
-/* Compress a serial object with Packbits encoding. */
-char *tcpackencode(const char *ptr, int size, int *sp){
- assert(ptr && size >= 0 && sp);
- char *buf;
- TCMALLOC(buf, size * 2 + 1);
- char *wp = buf;
- const char *end = ptr + size;
- while(ptr < end){
- char *sp = wp;
- const char *rp = ptr + 1;
- int step = 1;
- while(rp < end && step < 0x7f && *rp == *ptr){
- step++;
- rp++;
- }
- if(step <= 1 && rp < end){
- wp = sp + 1;
- *(wp++) = *ptr;
- while(rp < end && step < 0x7f && *rp != *(rp - 1)){
- *(wp++) = *rp;
- step++;
- rp++;
- }
- if(rp < end && *(rp - 1) == *rp){
- wp--;
- rp--;
- step--;
- }
- *sp = step == 1 ? 1 : -step;
- } else {
- *(wp++) = step;
- *(wp++) = *ptr;
- }
- ptr += step;
- }
- *sp = wp - buf;
- return buf;
-}
-
-
-/* Decompress a serial object compressed with Packbits encoding. */
-char *tcpackdecode(const char *ptr, int size, int *sp){
- assert(ptr && size >= 0 && sp);
- int asiz = size * 3;
- char *buf;
- TCMALLOC(buf, asiz + 1);
- int wi = 0;
- const char *end = ptr + size;
- while(ptr < end){
- int step = abs(*ptr);
- if(wi + step >= asiz){
- asiz = asiz * 2 + step;
- TCREALLOC(buf, buf, asiz + 1);
- }
- if(*(ptr++) >= 0){
- memset(buf + wi, *ptr, step);
- ptr++;
- } else {
- step = tclmin(step, end - ptr);
- memcpy(buf + wi, ptr, step);
- ptr += step;
- }
- wi += step;
- }
- buf[wi] = '\0';
- *sp = wi;
- return buf;
-}
-
-
-/* Compress a serial object with Deflate encoding. */
-char *tcdeflate(const char *ptr, int size, int *sp){
- assert(ptr && sp);
- if(!_tc_deflate) return NULL;
- return _tc_deflate(ptr, size, sp, _TCZMZLIB);
-}
-
-
-/* Decompress a serial object compressed with Deflate encoding. */
-char *tcinflate(const char *ptr, int size, int *sp){
- assert(ptr && size >= 0);
- if(!_tc_inflate) return NULL;
- return _tc_inflate(ptr, size, sp, _TCZMZLIB);
-}
-
-
-/* Compress a serial object with GZIP encoding. */
-char *tcgzipencode(const char *ptr, int size, int *sp){
- assert(ptr && sp);
- if(!_tc_deflate) return NULL;
- return _tc_deflate(ptr, size, sp, _TCZMGZIP);
-}
-
-
-/* Decompress a serial object compressed with GZIP encoding. */
-char *tcgzipdecode(const char *ptr, int size, int *sp){
- assert(ptr && size >= 0);
- if(!_tc_inflate) return NULL;
- return _tc_inflate(ptr, size, sp, _TCZMGZIP);
-}
-
-
-/* Get the CRC32 checksum of a serial object. */
-unsigned int tcgetcrc(const char *ptr, int size){
- assert(ptr && size >= 0);
- if(!_tc_getcrc) return 0;
- return _tc_getcrc(ptr, size);
-}
-
-
-/* Encode an array of nonnegative integers with BER encoding. */
-char *tcberencode(const unsigned int *ary, int anum, int *sp){
- assert(ary && anum >= 0 && sp);
- char *buf;
- TCMALLOC(buf, anum * (sizeof(int) + 1) + 1);
- char *wp = buf;
- for(int i = 0; i < anum; i++){
- unsigned int num = ary[i];
- if(num < (1 << 7)){
- *(wp++) = num;
- } else if(num < (1 << 14)){
- *(wp++) = (num >> 7) | 0x80;
- *(wp++) = num & 0x7f;
- } else if(num < (1 << 21)){
- *(wp++) = (num >> 14) | 0x80;
- *(wp++) = ((num >> 7) & 0x7f) | 0x80;
- *(wp++) = num & 0x7f;
- } else if(num < (1 << 28)){
- *(wp++) = (num >> 21) | 0x80;
- *(wp++) = ((num >> 14) & 0x7f) | 0x80;
- *(wp++) = ((num >> 7) & 0x7f) | 0x80;
- *(wp++) = num & 0x7f;
- } else {
- *(wp++) = (num >> 28) | 0x80;
- *(wp++) = ((num >> 21) & 0x7f) | 0x80;
- *(wp++) = ((num >> 14) & 0x7f) | 0x80;
- *(wp++) = ((num >> 7) & 0x7f) | 0x80;
- *(wp++) = num & 0x7f;
- }
- }
- *sp = wp - buf;
- return buf;
-}
-
-
-/* Decode a serial object encoded with BER encoding. */
-unsigned int *tcberdecode(const char *ptr, int size, int *np){
- assert(ptr && size >= 0 && np);
- unsigned int *buf;
- TCMALLOC(buf, size * sizeof(*buf) + 1);
- unsigned int *wp = buf;
- while(size > 0){
- unsigned int num = 0;
- int c;
- do {
- c = *(unsigned char *)ptr;
- num = num * 0x80 + (c & 0x7f);
- ptr++;
- size--;
- } while(c >= 0x80 && size > 0);
- *(wp++) = num;
- }
- *np = wp - buf;
- return buf;
-}
-
-
-/* Escape meta characters in a string with the entity references of XML. */
-char *tcxmlescape(const char *str){
- assert(str);
- const char *rp = str;
- int bsiz = 0;
- while(*rp != '\0'){
- switch(*rp){
- case '&':
- bsiz += 5;
- break;
- case '<':
- bsiz += 4;
- break;
- case '>':
- bsiz += 4;
- break;
- case '"':
- bsiz += 6;
- break;
- default:
- bsiz++;
- break;
- }
- rp++;
- }
- char *buf;
- TCMALLOC(buf, bsiz + 1);
- char *wp = buf;
- while(*str != '\0'){
- switch(*str){
- case '&':
- memcpy(wp, "&", 5);
- wp += 5;
- break;
- case '<':
- memcpy(wp, "<", 4);
- wp += 4;
- break;
- case '>':
- memcpy(wp, ">", 4);
- wp += 4;
- break;
- case '"':
- memcpy(wp, """, 6);
- wp += 6;
- break;
- default:
- *(wp++) = *str;
- break;
- }
- str++;
- }
- *wp = '\0';
- return buf;
-}
-
-
-/* Unescape entity references in a string of XML. */
-char *tcxmlunescape(const char *str){
- assert(str);
- char *buf;
- TCMALLOC(buf, strlen(str) + 1);
- char *wp = buf;
- while(*str != '\0'){
- if(*str == '&'){
- if(tcstrfwm(str, "&")){
- *(wp++) = '&';
- str += 5;
- } else if(tcstrfwm(str, "<")){
- *(wp++) = '<';
- str += 4;
- } else if(tcstrfwm(str, ">")){
- *(wp++) = '>';
- str += 4;
- } else if(tcstrfwm(str, """)){
- *(wp++) = '"';
- str += 6;
- } else {
- *(wp++) = *(str++);
- }
- } else {
- *(wp++) = *(str++);
- }
- }
- *wp = '\0';
- return buf;
-}
-
-
-/* Split an XML string into tags and text sections. */
-TCLIST *tcxmlbreak(const char *str){
- assert(str);
- TCLIST *list = tclistnew();
- int i = 0;
- int pv = 0;
- bool tag = false;
- char *ep;
- while(true){
- if(str[i] == '\0'){
- if(i > pv) TCLISTPUSH(list, str + pv, i - pv);
- break;
- } else if(!tag && str[i] == '<'){
- if(str[i+1] == '!' && str[i+2] == '-' && str[i+3] == '-'){
- if(i > pv) TCLISTPUSH(list, str + pv, i - pv);
- if((ep = strstr(str + i, "-->")) != NULL){
- TCLISTPUSH(list, str + i, ep - str - i + 3);
- i = ep - str + 2;
- pv = i + 1;
- }
- } else if(str[i+1] == '!' && str[i+2] == '[' && tcstrifwm(str + i, "<![CDATA[")){
- if(i > pv) TCLISTPUSH(list, str + pv, i - pv);
- if((ep = strstr(str + i, "]]>")) != NULL){
- i += 9;
- TCXSTR *xstr = tcxstrnew();
- while(str + i < ep){
- if(str[i] == '&'){
- TCXSTRCAT(xstr, "&", 5);
- } else if(str[i] == '<'){
- TCXSTRCAT(xstr, "<", 4);
- } else if(str[i] == '>'){
- TCXSTRCAT(xstr, ">", 4);
- } else {
- TCXSTRCAT(xstr, str + i, 1);
- }
- i++;
- }
- if(TCXSTRSIZE(xstr) > 0) TCLISTPUSH(list, TCXSTRPTR(xstr), TCXSTRSIZE(xstr));
- tcxstrdel(xstr);
- i = ep - str + 2;
- pv = i + 1;
- }
- } else {
- if(i > pv) TCLISTPUSH(list, str + pv, i - pv);
- tag = true;
- pv = i;
- }
- } else if(tag && str[i] == '>'){
- if(i > pv) TCLISTPUSH(list, str + pv, i - pv + 1);
- tag = false;
- pv = i + 1;
- }
- i++;
- }
- return list;
-}
-
-
-/* Get the map of attributes of an XML tag. */
-TCMAP *tcxmlattrs(const char *str){
- assert(str);
- TCMAP *map = tcmapnew2(TCXMLATBNUM);
- const unsigned char *rp = (unsigned char *)str;
- while(*rp == '<' || *rp == '/' || *rp == '?' || *rp == '!' || *rp == ' '){
- rp++;
- }
- const unsigned char *key = rp;
- while(*rp > 0x20 && *rp != '/' && *rp != '>'){
- rp++;
- }
- tcmapputkeep(map, "", 0, (char *)key, rp - key);
- while(*rp != '\0'){
- while(*rp != '\0' && (*rp <= 0x20 || *rp == '/' || *rp == '?' || *rp == '>')){
- rp++;
- }
- key = rp;
- while(*rp > 0x20 && *rp != '/' && *rp != '>' && *rp != '='){
- rp++;
- }
- int ksiz = rp - key;
- while(*rp != '\0' && (*rp == '=' || *rp <= 0x20)){
- rp++;
- }
- const unsigned char *val;
- int vsiz;
- if(*rp == '"'){
- rp++;
- val = rp;
- while(*rp != '\0' && *rp != '"'){
- rp++;
- }
- vsiz = rp - val;
- } else if(*rp == '\''){
- rp++;
- val = rp;
- while(*rp != '\0' && *rp != '\''){
- rp++;
- }
- vsiz = rp - val;
- } else {
- val = rp;
- while(*rp > 0x20 && *rp != '"' && *rp != '\'' && *rp != '>'){
- rp++;
- }
- vsiz = rp - val;
- }
- if(*rp != '\0') rp++;
- if(ksiz > 0){
- char *copy;
- TCMEMDUP(copy, val, vsiz);
- char *raw = tcxmlunescape(copy);
- tcmapputkeep(map, (char *)key, ksiz, raw, strlen(raw));
- free(raw);
- free(copy);
- }
- }
- return map;
-}
-
-
-
-/*************************************************************************************************
- * features for experts
- *************************************************************************************************/
-
-
-#define TCBSENCUNIT 8192 // unit size of TCBS encoding
-#define TCBWTCNTMIN 64 // minimum element number of counting sort
-#define TCBWTCNTLV 4 // maximum recursion level of counting sort
-#define TCBWTBUFNUM 16384 // number of elements of BWT buffer
-
-typedef struct { // type of structure for a BWT character
- int fchr; // character code of the first character
- int tchr; // character code of the last character
-} TCBWTREC;
-
-
-/* private function prototypes */
-static void tcglobalmutexinit(void);
-static void tcglobalmutexdestroy(void);
-static void tcbwtsortstrcount(const char **arrays, int anum, int len, int level);
-static void tcbwtsortstrinsert(const char **arrays, int anum, int len, int skip);
-static void tcbwtsortstrheap(const char **arrays, int anum, int len, int skip);
-static void tcbwtsortchrcount(unsigned char *str, int len);
-static void tcbwtsortchrinsert(unsigned char *str, int len);
-static void tcbwtsortreccount(TCBWTREC *arrays, int anum);
-static void tcbwtsortrecinsert(TCBWTREC *array, int anum);
-static int tcbwtsearchrec(TCBWTREC *array, int anum, int tchr);
-static void tcmtfencode(char *ptr, int size);
-static void tcmtfdecode(char *ptr, int size);
-static int tcgammaencode(const char *ptr, int size, char *obuf);
-static int tcgammadecode(const char *ptr, int size, char *obuf);
-
-
-/* Show error message on the standard error output and exit. */
-void *tcmyfatal(const char *message){
- assert(message);
- if(tcfatalfunc){
- tcfatalfunc(message);
- } else {
- fprintf(stderr, "fatal error: %s\n", message);
- }
- exit(1);
- return NULL;
-}
-
-
-/* Global mutex object. */
-static pthread_rwlock_t tcglobalmutex;
-static pthread_once_t tcglobalmutexonce = PTHREAD_ONCE_INIT;
-
-
-/* Lock the global mutex object. */
-bool tcglobalmutexlock(void){
- pthread_once(&tcglobalmutexonce, tcglobalmutexinit);
- return pthread_rwlock_wrlock(&tcglobalmutex) == 0;
-}
-
-
-/* Lock the global mutex object by shared locking. */
-bool tcglobalmutexlockshared(void){
- pthread_once(&tcglobalmutexonce, tcglobalmutexinit);
- return pthread_rwlock_rdlock(&tcglobalmutex) == 0;
-}
-
-
-/* Unlock the global mutex object. */
-bool tcglobalmutexunlock(void){
- return pthread_rwlock_unlock(&tcglobalmutex) == 0;
-}
-
-
-/* Compress a serial object with TCBS encoding. */
-char *tcbsencode(const char *ptr, int size, int *sp){
- assert(ptr && size >= 0 && sp);
- char *result;
- TCMALLOC(result, (size * 7) / 3 + (size / TCBSENCUNIT + 1) * sizeof(uint16_t) +
- TCBSENCUNIT * 2 + 0x200);
- char *pv = result + size + 0x100;
- char *wp = pv;
- char *tp = pv + size + 0x100;
- const char *end = ptr + size;
- while(ptr < end){
- int usiz = tclmin(TCBSENCUNIT, end - ptr);
- memcpy(tp, ptr, usiz);
- memcpy(tp + usiz, ptr, usiz);
- char *sp = wp;
- uint16_t idx = 0;
- wp += sizeof(idx);
- const char *arrays[usiz+1];
- for(int i = 0; i < usiz; i++){
- arrays[i] = tp + i;
- }
- const char *fp = arrays[0];
- if(usiz >= TCBWTCNTMIN){
- tcbwtsortstrcount(arrays, usiz, usiz, 0);
- } else if(usiz > 1){
- tcbwtsortstrinsert(arrays, usiz, usiz, 0);
- }
- for(int i = 0; i < usiz; i++){
- int tidx = arrays[i] - fp;
- if(tidx == 0){
- idx = i;
- *(wp++) = ptr[usiz-1];
- } else {
- *(wp++) = ptr[tidx-1];
- }
- }
- idx = TCHTOIS(idx);
- memcpy(sp, &idx, sizeof(idx));
- ptr += TCBSENCUNIT;
- }
- size = wp - pv;
- tcmtfencode(pv, size);
- int nsiz = tcgammaencode(pv, size, result);
- *sp = nsiz;
- return result;
-}
-
-
-/* Decompress a serial object compressed with TCBS encoding. */
-char *tcbsdecode(const char *ptr, int size, int *sp){
- char *result;
- TCMALLOC(result, size * 9 + 0x200);
- char *wp = result + size + 0x100;
- int nsiz = tcgammadecode(ptr, size, wp);
- tcmtfdecode(wp, nsiz);
- ptr = wp;
- wp = result;
- const char *end = ptr + nsiz;
- while(ptr < end){
- uint16_t idx;
- memcpy(&idx, ptr, sizeof(idx));
- idx = TCITOHS(idx);
- ptr += sizeof(idx);
- int usiz = tclmin(TCBSENCUNIT, end - ptr);
- if(idx >= usiz) idx = 0;
- char rbuf[usiz+1];
- memcpy(rbuf, ptr, usiz);
- if(usiz >= TCBWTCNTMIN){
- tcbwtsortchrcount((unsigned char *)rbuf, usiz);
- } else if(usiz > 0){
- tcbwtsortchrinsert((unsigned char *)rbuf, usiz);
- }
- int fnums[0x100], tnums[0x100];
- memset(fnums, 0, sizeof(fnums));
- memset(tnums, 0, sizeof(tnums));
- TCBWTREC array[usiz+1];
- TCBWTREC *rp = array;
- for(int i = 0; i < usiz; i++){
- int fc = *(unsigned char *)(rbuf + i);
- rp->fchr = (fc << 23) + fnums[fc]++;
- int tc = *(unsigned char *)(ptr + i);
- rp->tchr = (tc << 23) + tnums[tc]++;
- rp++;
- }
- unsigned int fchr = array[idx].fchr;
- if(usiz >= TCBWTCNTMIN){
- tcbwtsortreccount(array, usiz);
- } else if(usiz > 1){
- tcbwtsortrecinsert(array, usiz);
- }
- for(int i = 0; i < usiz; i++){
- if(array[i].fchr == fchr){
- idx = i;
- break;
- }
- }
- for(int i = 0; i < usiz; i++){
- *(wp++) = array[idx].fchr >> 23;
- idx = tcbwtsearchrec(array, usiz, array[idx].fchr);
- }
- ptr += usiz;
- }
- *wp = '\0';
- *sp = wp - result;
- return result;
-}
-
-
-/* Encode a serial object with BWT encoding. */
-char *tcbwtencode(const char *ptr, int size, int *idxp){
- assert(ptr && size >= 0 && idxp);
- if(size < 1){
- *idxp = 0;
- char *rv;
- TCMEMDUP(rv, "", 0);
- return rv;
- }
- char *result;
- TCMALLOC(result, size * 3 + 1);
- char *tp = result + size + 1;
- memcpy(tp, ptr, size);
- memcpy(tp + size, ptr, size);
- const char *abuf[TCBWTBUFNUM];
- const char **arrays = abuf;
- if(size > TCBWTBUFNUM) TCMALLOC(arrays, sizeof(*arrays) * size);
- for(int i = 0; i < size; i++){
- arrays[i] = tp + i;
- }
- const char *fp = arrays[0];
- if(size >= TCBWTCNTMIN){
- tcbwtsortstrcount(arrays, size, size, -1);
- } else if(size > 1){
- tcbwtsortstrinsert(arrays, size, size, 0);
- }
- for(int i = 0; i < size; i++){
- int idx = arrays[i] - fp;
- if(idx == 0){
- *idxp = i;
- result[i] = ptr[size-1];
- } else {
- result[i] = ptr[idx-1];
- }
- }
- if(arrays != abuf) free(arrays);
- result[size] = '\0';
- return result;
-}
-
-
-/* Decode a serial object encoded with BWT encoding. */
-char *tcbwtdecode(const char *ptr, int size, int idx){
- assert(ptr && size >= 0);
- if(size < 1 || idx < 0){
- char *rv;
- TCMEMDUP(rv, "", 0);
- return rv;
- }
- if(idx >= size) idx = 0;
- char *result;
- TCMALLOC(result, size + 1);
- memcpy(result, ptr, size);
- if(size >= TCBWTCNTMIN){
- tcbwtsortchrcount((unsigned char *)result, size);
- } else {
- tcbwtsortchrinsert((unsigned char *)result, size);
- }
- int fnums[0x100], tnums[0x100];
- memset(fnums, 0, sizeof(fnums));
- memset(tnums, 0, sizeof(tnums));
- TCBWTREC abuf[TCBWTBUFNUM];
- TCBWTREC *array = abuf;
- if(size > TCBWTBUFNUM) TCMALLOC(array, sizeof(*array) * size);
- TCBWTREC *rp = array;
- for(int i = 0; i < size; i++){
- int fc = *(unsigned char *)(result + i);
- rp->fchr = (fc << 23) + fnums[fc]++;
- int tc = *(unsigned char *)(ptr + i);
- rp->tchr = (tc << 23) + tnums[tc]++;
- rp++;
- }
- unsigned int fchr = array[idx].fchr;
- if(size >= TCBWTCNTMIN){
- tcbwtsortreccount(array, size);
- } else if(size > 1){
- tcbwtsortrecinsert(array, size);
- }
- for(int i = 0; i < size; i++){
- if(array[i].fchr == fchr){
- idx = i;
- break;
- }
- }
- char *wp = result;
- for(int i = 0; i < size; i++){
- *(wp++) = array[idx].fchr >> 23;
- idx = tcbwtsearchrec(array, size, array[idx].fchr);
- }
- *wp = '\0';
- if(array != abuf) free(array);
- return result;
-}
-
-
-/* Initialize the global mutex object */
-static void tcglobalmutexinit(void){
- if(!TCUSEPTHREAD) memset(&tcglobalmutex, 0, sizeof(tcglobalmutex));
- if(pthread_rwlock_init(&tcglobalmutex, NULL) != 0) tcmyfatal("rwlock error");
- atexit(tcglobalmutexdestroy);
-}
-
-
-/* Destroy the global mutex object */
-static void tcglobalmutexdestroy(void){
- pthread_rwlock_destroy(&tcglobalmutex);
-}
-
-
-/* Sort BWT string arrays by dicrionary order by counting sort.
- `array' specifies an array of string arrays.
- `anum' specifies the number of the array.
- `len' specifies the size of each string.
- `level' specifies the level of recursion. */
-static void tcbwtsortstrcount(const char **arrays, int anum, int len, int level){
- assert(arrays && anum >= 0 && len >= 0);
- const char *nbuf[TCBWTBUFNUM];
- const char **narrays = nbuf;
- if(anum > TCBWTBUFNUM) TCMALLOC(narrays, sizeof(*narrays) * anum);
- int count[0x100], accum[0x100];
- memset(count, 0, sizeof(count));
- int skip = level < 0 ? 0 : level;
- for(int i = 0; i < anum; i++){
- count[((unsigned char *)arrays[i])[skip]]++;
- }
- memcpy(accum, count, sizeof(count));
- for(int i = 1; i < 0x100; i++){
- accum[i] = accum[i-1] + accum[i];
- }
- for(int i = 0; i < anum; i++){
- narrays[--accum[((unsigned char *)arrays[i])[skip]]] = arrays[i];
- }
- int off = 0;
- if(level >= 0 && level < TCBWTCNTLV){
- for(int i = 0; i < 0x100; i++){
- int c = count[i];
- if(c > 1){
- if(c >= TCBWTCNTMIN){
- tcbwtsortstrcount(narrays + off, c, len, level + 1);
- } else {
- tcbwtsortstrinsert(narrays + off, c, len, skip + 1);
- }
- }
- off += c;
- }
- } else {
- for(int i = 0; i < 0x100; i++){
- int c = count[i];
- if(c > 1){
- if(c >= TCBWTCNTMIN){
- tcbwtsortstrheap(narrays + off, c, len, skip + 1);
- } else {
- tcbwtsortstrinsert(narrays + off, c, len, skip + 1);
- }
- }
- off += c;
- }
- }
- memcpy(arrays, narrays, anum * sizeof(*narrays));
- if(narrays != nbuf) free(narrays);
-}
-
-
-/* Sort BWT string arrays by dicrionary order by insertion sort.
- `array' specifies an array of string arrays.
- `anum' specifies the number of the array.
- `len' specifies the size of each string.
- `skip' specifies the number of skipped bytes. */
-static void tcbwtsortstrinsert(const char **arrays, int anum, int len, int skip){
- assert(arrays && anum >= 0 && len >= 0);
- for(int i = 1; i < anum; i++){
- int cmp = 0;
- const unsigned char *ap = (unsigned char *)arrays[i-1];
- const unsigned char *bp = (unsigned char *)arrays[i];
- for(int j = skip; j < len; j++){
- if(ap[j] != bp[j]){
- cmp = ap[j] - bp[j];
- break;
- }
- }
- if(cmp > 0){
- const char *swap = arrays[i];
- int j;
- for(j = i; j > 0; j--){
- int cmp = 0;
- const unsigned char *ap = (unsigned char *)arrays[j-1];
- const unsigned char *bp = (unsigned char *)swap;
- for(int k = skip; k < len; k++){
- if(ap[k] != bp[k]){
- cmp = ap[k] - bp[k];
- break;
- }
- }
- if(cmp < 0) break;
- arrays[j] = arrays[j-1];
- }
- arrays[j] = swap;
- }
- }
-}
-
-
-/* Sort BWT string arrays by dicrionary order by heap sort.
- `array' specifies an array of string arrays.
- `anum' specifies the number of the array.
- `len' specifies the size of each string.
- `skip' specifies the number of skipped bytes. */
-static void tcbwtsortstrheap(const char **arrays, int anum, int len, int skip){
- assert(arrays && anum >= 0 && len >= 0);
- anum--;
- int bottom = (anum >> 1) + 1;
- int top = anum;
- while(bottom > 0){
- bottom--;
- int mybot = bottom;
- int i = mybot << 1;
- while(i <= top){
- if(i < top){
- int cmp = 0;
- const unsigned char *ap = (unsigned char *)arrays[i+1];
- const unsigned char *bp = (unsigned char *)arrays[i];
- for(int j = skip; j < len; j++){
- if(ap[j] != bp[j]){
- cmp = ap[j] - bp[j];
- break;
- }
- }
- if(cmp > 0) i++;
- }
- int cmp = 0;
- const unsigned char *ap = (unsigned char *)arrays[mybot];
- const unsigned char *bp = (unsigned char *)arrays[i];
- for(int j = skip; j < len; j++){
- if(ap[j] != bp[j]){
- cmp = ap[j] - bp[j];
- break;
- }
- }
- if(cmp >= 0) break;
- const char *swap = arrays[mybot];
- arrays[mybot] = arrays[i];
- arrays[i] = swap;
- mybot = i;
- i = mybot << 1;
- }
- }
- while(top > 0){
- const char *swap = arrays[0];
- arrays[0] = arrays[top];
- arrays[top] = swap;
- top--;
- int mybot = bottom;
- int i = mybot << 1;
- while(i <= top){
- if(i < top){
- int cmp = 0;
- const unsigned char *ap = (unsigned char *)arrays[i+1];
- const unsigned char *bp = (unsigned char *)arrays[i];
- for(int j = 0; j < len; j++){
- if(ap[j] != bp[j]){
- cmp = ap[j] - bp[j];
- break;
- }
- }
- if(cmp > 0) i++;
- }
- int cmp = 0;
- const unsigned char *ap = (unsigned char *)arrays[mybot];
- const unsigned char *bp = (unsigned char *)arrays[i];
- for(int j = 0; j < len; j++){
- if(ap[j] != bp[j]){
- cmp = ap[j] - bp[j];
- break;
- }
- }
- if(cmp >= 0) break;
- swap = arrays[mybot];
- arrays[mybot] = arrays[i];
- arrays[i] = swap;
- mybot = i;
- i = mybot << 1;
- }
- }
-}
-
-
-/* Sort BWT characters by code number by counting sort.
- `str' specifies a string.
- `len' specifies the length of the string. */
-static void tcbwtsortchrcount(unsigned char *str, int len){
- assert(str && len >= 0);
- int cnt[0x100];
- memset(cnt, 0, sizeof(cnt));
- for(int i = 0; i < len; i++){
- cnt[str[i]]++;
- }
- int pos = 0;
- for(int i = 0; i < 0x100; i++){
- memset(str + pos, i, cnt[i]);
- pos += cnt[i];
- }
-}
-
-
-/* Sort BWT characters by code number by insertion sort.
- `str' specifies a string.
- `len' specifies the length of the string. */
-static void tcbwtsortchrinsert(unsigned char *str, int len){
- assert(str && len >= 0);
- for(int i = 1; i < len; i++){
- if(str[i-1] - str[i] > 0){
- unsigned char swap = str[i];
- int j;
- for(j = i; j > 0; j--){
- if(str[j-1] - swap < 0) break;
- str[j] = str[j-1];
- }
- str[j] = swap;
- }
- }
-}
-
-
-/* Sort BWT records by code number by counting sort.
- `array' specifies an array of records.
- `anum' specifies the number of the array. */
-static void tcbwtsortreccount(TCBWTREC *array, int anum){
- assert(array && anum >= 0);
- TCBWTREC nbuf[TCBWTBUFNUM];
- TCBWTREC *narray = nbuf;
- if(anum > TCBWTBUFNUM) TCMALLOC(narray, sizeof(*narray) * anum);
- int count[0x100], accum[0x100];
- memset(count, 0, sizeof(count));
- for(int i = 0; i < anum; i++){
- count[array[i].tchr>>23]++;
- }
- memcpy(accum, count, sizeof(count));
- for(int i = 1; i < 0x100; i++){
- accum[i] = accum[i-1] + accum[i];
- }
- for(int i = 0; i < 0x100; i++){
- accum[i] -= count[i];
- }
- for(int i = 0; i < anum; i++){
- narray[accum[array[i].tchr>>23]++] = array[i];
- }
- memcpy(array, narray, anum * sizeof(*narray));
- if(narray != nbuf) free(narray);
-}
-
-
-/* Sort BWT records by code number by insertion sort.
- `array' specifies an array of records..
- `anum' specifies the number of the array. */
-static void tcbwtsortrecinsert(TCBWTREC *array, int anum){
- assert(array && anum >= 0);
- for(int i = 1; i < anum; i++){
- if(array[i-1].tchr - array[i].tchr > 0){
- TCBWTREC swap = array[i];
- int j;
- for(j = i; j > 0; j--){
- if(array[j-1].tchr - swap.tchr < 0) break;
- array[j] = array[j-1];
- }
- array[j] = swap;
- }
- }
-}
-
-
-/* Search the element of BWT records.
- `array' specifies an array of records.
- `anum' specifies the number of the array.
- `tchr' specifies the last code number. */
-static int tcbwtsearchrec(TCBWTREC *array, int anum, int tchr){
- assert(array && anum >= 0);
- int bottom = 0;
- int top = anum;
- int mid;
- do {
- mid = (bottom + top) >> 1;
- if(array[mid].tchr == tchr){
- return mid;
- } else if(array[mid].tchr < tchr){
- bottom = mid + 1;
- if(bottom >= anum) break;
- } else {
- top = mid - 1;
- }
- } while(bottom <= top);
- return -1;
-}
-
-
-/* Initialization table for MTF encoder. */
-const unsigned char tcmtftable[] = {
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
- 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
- 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
- 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
- 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
- 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
- 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
- 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
- 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
- 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
- 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
- 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
- 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
- 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
- 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
-};
-
-
-/* Encode a region with MTF encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region. */
-static void tcmtfencode(char *ptr, int size){
- unsigned char table1[0x100], table2[0x100], *table, *another;
- assert(ptr && size >= 0);
- memcpy(table1, tcmtftable, sizeof(tcmtftable));
- table = table1;
- another = table2;
- const char *end = ptr + size;
- char *wp = ptr;
- while(ptr < end){
- unsigned char c = *ptr;
- unsigned char *tp = table;
- unsigned char *tend = table + 0x100;
- while(tp < tend && *tp != c){
- tp++;
- }
- int idx = tp - table;
- *(wp++) = idx;
- if(idx > 0){
- memcpy(another, &c, 1);
- memcpy(another + 1, table, idx);
- memcpy(another + 1 + idx, table + idx + 1, 255 - idx);
- unsigned char *swap = table;
- table = another;
- another = swap;
- }
- ptr++;
- }
-}
-
-
-/* Decode a region compressed with MTF encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region. */
-static void tcmtfdecode(char *ptr, int size){
- assert(ptr && size >= 0);
- unsigned char table1[0x100], table2[0x100], *table, *another;
- assert(ptr && size >= 0);
- memcpy(table1, tcmtftable, sizeof(tcmtftable));
- table = table1;
- another = table2;
- const char *end = ptr + size;
- char *wp = ptr;
- while(ptr < end){
- int idx = *(unsigned char *)ptr;
- unsigned char c = table[idx];
- *(wp++) = c;
- if(idx > 0){
- memcpy(another, &c, 1);
- memcpy(another + 1, table, idx);
- memcpy(another + 1 + idx, table + idx + 1, 255 - idx);
- unsigned char *swap = table;
- table = another;
- another = swap;
- }
- ptr++;
- }
-}
-
-
-/* Encode a region with Elias gamma encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `ptr' specifies the pointer to the output buffer. */
-static int tcgammaencode(const char *ptr, int size, char *obuf){
- assert(ptr && size >= 0 && obuf);
- TCBITSTRM strm;
- TCBITSTRMINITW(strm, obuf);
- const char *end = ptr + size;
- while(ptr < end){
- unsigned int c = *(unsigned char *)ptr;
- if(!c){
- TCBITSTRMCAT(strm, 1);
- } else {
- c++;
- int plen = 8;
- while(plen > 0 && !(c & (1 << plen))){
- plen--;
- }
- int jlen = plen;
- while(jlen-- > 0){
- TCBITSTRMCAT(strm, 0);
- }
- while(plen >= 0){
- int sign = (c & (1 << plen)) > 0;
- TCBITSTRMCAT(strm, sign);
- plen--;
- }
- }
- ptr++;
- }
- TCBITSTRMSETEND(strm);
- return TCBITSTRMSIZE(strm);
-}
-
-
-/* Decode a region compressed with Elias gamma encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `ptr' specifies the pointer to the output buffer. */
-static int tcgammadecode(const char *ptr, int size, char *obuf){
- assert(ptr && size >= 0 && obuf);
- char *wp = obuf;
- TCBITSTRM strm;
- TCBITSTRMINITR(strm, ptr, size);
- int bnum = TCBITSTRMNUM(strm);
- while(bnum > 0){
- int sign;
- TCBITSTRMREAD(strm, sign);
- bnum--;
- if(sign){
- *(wp++) = 0;
- } else {
- int plen = 1;
- while(bnum > 0){
- TCBITSTRMREAD(strm, sign);
- bnum--;
- if(sign) break;
- plen++;
- }
- unsigned int c = 1;
- while(bnum > 0 && plen-- > 0){
- TCBITSTRMREAD(strm, sign);
- bnum--;
- c = (c << 1) + (sign > 0);
- }
- *(wp++) = c - 1;
- }
- }
- return wp - obuf;;
-}
-
-
-
-// END OF FILE
+++ /dev/null
-/*************************************************************************************************
- * The utility API of Tokyo Cabinet
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-#ifndef _TCUTIL_H /* duplication check */
-#define _TCUTIL_H
-
-#if defined(__cplusplus)
-#define __TCUTIL_CLINKAGEBEGIN extern "C" {
-#define __TCUTIL_CLINKAGEEND }
-#else
-#define __TCUTIL_CLINKAGEBEGIN
-#define __TCUTIL_CLINKAGEEND
-#endif
-__TCUTIL_CLINKAGEBEGIN
-
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <time.h>
-
-
-
-/*************************************************************************************************
- * basic utilities
- *************************************************************************************************/
-
-
-/* String containing the version information. */
-extern const char *tcversion;
-
-
-/* Pointer to the call back function for handling a fatal error.
- The argument specifies the error message.
- The initial value of this variable is `NULL'. If the value is `NULL', the default function is
- called when a fatal error occurs. A fatal error occurs when memory allocation is failed. */
-extern void (*tcfatalfunc)(const char *);
-
-
-/* Allocate a region on memory.
- `size' specifies the size of the region.
- The return value is the pointer to the allocated region.
- This function handles failure of memory allocation implicitly. Because the region of the
- return value is allocated with the `malloc' call, it should be released with the `free' call
- when it is no longer in use. */
-void *tcmalloc(size_t size);
-
-
-/* Allocate a nullified region on memory.
- `nmemb' specifies the number of elements.
- `size' specifies the size of each element.
- The return value is the pointer to the allocated nullified region.
- This function handles failure of memory allocation implicitly. Because the region of the
- return value is allocated with the `calloc' call, it should be released with the `free' call
- when it is no longer in use. */
-void *tccalloc(size_t nmemb, size_t size);
-
-
-/* Re-allocate a region on memory.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- The return value is the pointer to the re-allocated region.
- This function handles failure of memory allocation implicitly. Because the region of the
- return value is allocated with the `realloc' call, it should be released with the `free' call
- when it is no longer in use. */
-void *tcrealloc(void *ptr, size_t size);
-
-
-/* Duplicate a region on memory.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- The return value is the pointer to the allocated region of the duplicate.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-void *tcmemdup(const void *ptr, size_t size);
-
-
-/* Duplicate a string on memory.
- `str' specifies the string.
- The return value is the allocated string equivalent to the specified string.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcstrdup(const void *str);
-
-
-/* Free a region on memory.
- `ptr' specifies the pointer to the region. If it is `NULL', this function has no effect.
- Although this function is just a wrapper of `free' call, this is useful in applications using
- another package of the `malloc' series. */
-void tcfree(void *ptr);
-
-
-
-/*************************************************************************************************
- * extensible string
- *************************************************************************************************/
-
-
-typedef struct { /* type of structure for an extensible string object */
- char *ptr; /* pointer to the region */
- int size; /* size of the region */
- int asize; /* size of the allocated region */
-} TCXSTR;
-
-
-/* Create an extensible string object.
- The return value is the new extensible string object. */
-TCXSTR *tcxstrnew(void);
-
-
-/* Create an extensible string object from a character string.
- `str' specifies the string of the initial content.
- The return value is the new extensible string object containing the specified string. */
-TCXSTR *tcxstrnew2(const char *str);
-
-
-/* Create an extensible string object with the initial allocation size.
- `asiz' specifies the initial allocation size.
- The return value is the new extensible string object. */
-TCXSTR *tcxstrnew3(int asiz);
-
-
-/* Copy an extensible string object.
- `xstr' specifies the extensible string object.
- The return value is the new extensible string object equivalent to the specified object. */
-TCXSTR *tcxstrdup(const TCXSTR *xstr);
-
-
-/* Delete an extensible string object.
- `xstr' specifies the extensible string object.
- Note that the deleted object and its derivatives can not be used anymore. */
-void tcxstrdel(TCXSTR *xstr);
-
-
-/* Concatenate a region to the end of an extensible string object.
- `xstr' specifies the extensible string object.
- `ptr' specifies the pointer to the region to be appended.
- `size' specifies the size of the region. */
-void tcxstrcat(TCXSTR *xstr, const void *ptr, int size);
-
-
-/* Concatenate a character string to the end of an extensible string object.
- `xstr' specifies the extensible string object.
- `str' specifies the string to be appended. */
-void tcxstrcat2(TCXSTR *xstr, const char *str);
-
-
-/* Get the pointer of the region of an extensible string object.
- `xstr' specifies the extensible string object.
- The return value is the pointer of the region of the object.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. */
-const void *tcxstrptr(const TCXSTR *xstr);
-
-
-/* Get the size of the region of an extensible string object.
- `xstr' specifies the extensible string object.
- The return value is the size of the region of the object. */
-int tcxstrsize(const TCXSTR *xstr);
-
-
-/* Clear an extensible string object.
- `xstr' specifies the extensible string object.
- The internal buffer of the object is cleared and the size is set zero. */
-void tcxstrclear(TCXSTR *xstr);
-
-
-/* Convert an extensible string object into a usual allocated region.
- `xstr' specifies the extensible string object.
- The return value is the pointer to the allocated region of the object.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. Because the region of the original object is deleted, it should not be
- deleted again. */
-void *tcxstrtomalloc(TCXSTR *xstr);
-
-
-/* Create an extensible string object from an allocated region.
- `ptr' specifies the pointer to the region allocated with `malloc' call.
- `size' specifies the size of the region.
- The return value is the new extensible string object wrapping the specified region.
- Note that the specified region is released when the object is deleted. */
-TCXSTR *tcxstrfrommalloc(void *ptr, int size);
-
-
-/* Perform formatted output into an extensible string object.
- `xstr' specifies the extensible string object.
- `format' specifies the printf-like format string.
- The conversion character `%' can be used with such flag characters as `s', `d', `o', `u',
- `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `%'. `@' works as with `s' but escapes meta
- characters of XML. `?' works as with `s' but escapes meta characters of URL. The other
- conversion character work as with each original.
- The other arguments are used according to the format string. */
-void tcxstrprintf(TCXSTR *xstr, const char *format, ...);
-
-
-/* Allocate a formatted string on memory.
- `format' specifies the printf-like format string.
- The conversion character `%' can be used with such flag characters as `s', `d', `o', `u',
- `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `%'. `@' works as with `s' but escapes meta
- characters of XML. `?' works as with `s' but escapes meta characters of URL. The other
- conversion character work as with each original.
- The other arguments are used according to the format string.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcsprintf(const char *format, ...);
-
-
-
-/*************************************************************************************************
- * array list
- *************************************************************************************************/
-
-
-typedef struct { /* type of structure for an element of a list */
- char *ptr; /* pointer to the region */
- int size; /* size of the effective region */
-} TCLISTDATUM;
-
-typedef struct { /* type of structure for an array list */
- TCLISTDATUM *array; /* array of data */
- int anum; /* number of the elements of the array */
- int start; /* start index of used elements */
- int num; /* number of used elements */
-} TCLIST;
-
-
-/* Create a list object.
- The return value is the new list object. */
-TCLIST *tclistnew(void);
-
-
-/* Create a list object with expecting the number of elements.
- `anum' specifies the number of elements expected to be stored in the list.
- The return value is the new list object. */
-TCLIST *tclistnew2(int anum);
-
-
-/* Copy a list object.
- `list' specifies the list object.
- The return value is the new list object equivalent to the specified object. */
-TCLIST *tclistdup(const TCLIST *list);
-
-
-/* Delete a list object.
- `list' specifies the list object.
- Note that the deleted object and its derivatives can not be used anymore. */
-void tclistdel(TCLIST *list);
-
-
-/* Get the number of elements of a list object.
- `list' specifies the list object.
- The return value is the number of elements of the list. */
-int tclistnum(const TCLIST *list);
-
-
-/* Get the pointer to the region of an element of a list object.
- `list' specifies the list object.
- `index' specifies the index of the element.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the value.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. If `index' is equal to or more than
- the number of elements, the return value is `NULL'. */
-const void *tclistval(const TCLIST *list, int index, int *sp);
-
-
-/* Get the string of an element of a list object.
- `list' specifies the list object.
- `index' specifies the index of the element.
- The return value is the string of the value.
- If `index' is equal to or more than the number of elements, the return value is `NULL'. */
-const char *tclistval2(const TCLIST *list, int index);
-
-
-/* Add an element at the end of a list object.
- `list' specifies the list object.
- `ptr' specifies the pointer to the region of the new element.
- `size' specifies the size of the region. */
-void tclistpush(TCLIST *list, const void *ptr, int size);
-
-
-/* Add a string element at the end of a list object.
- `list' specifies the list object.
- `str' specifies the string of the new element. */
-void tclistpush2(TCLIST *list, const char *str);
-
-
-/* Add an allocated element at the end of a list object.
- `list' specifies the list object.
- `ptr' specifies the pointer to the region allocated with `malloc' call.
- `size' specifies the size of the region.
- Note that the specified region is released when the object is deleted. */
-void tclistpushmalloc(TCLIST *list, void *ptr, int size);
-
-
-/* Remove an element of the end of a list object.
- `list' specifies the list object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the removed element.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. If the list is empty, the return value is `NULL'. */
-void *tclistpop(TCLIST *list, int *sp);
-
-
-/* Remove a string element of the end of a list object.
- `list' specifies the list object.
- The return value is the string of the removed element.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. If the list is empty, the return
- value is `NULL'. */
-char *tclistpop2(TCLIST *list);
-
-
-/* Add an element at the top of a list object.
- `list' specifies the list object.
- `ptr' specifies the pointer to the region of the new element.
- `size' specifies the size of the region. */
-void tclistunshift(TCLIST *list, const void *ptr, int size);
-
-
-/* Add a string element at the top of a list object.
- `list' specifies the list object.
- `str' specifies the string of the new element. */
-void tclistunshift2(TCLIST *list, const char *str);
-
-
-/* Remove an element of the top of a list object.
- `list' specifies the list object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the removed element.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. If the list is empty, the return value is `NULL'. */
-void *tclistshift(TCLIST *list, int *sp);
-
-
-/* Remove a string element of the top of a list object.
- `list' specifies the list object.
- The return value is the string of the removed element.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. If the list is empty, the return
- value is `NULL'. */
-char *tclistshift2(TCLIST *list);
-
-
-/* Add an element at the specified location of a list object.
- `list' specifies the list object.
- `index' specifies the index of the new element.
- `ptr' specifies the pointer to the region of the new element.
- `size' specifies the size of the region.
- If `index' is equal to or more than the number of elements, this function has no effect. */
-void tclistinsert(TCLIST *list, int index, const void *ptr, int size);
-
-
-/* Add a string element at the specified location of a list object.
- `list' specifies the list object.
- `index' specifies the index of the new element.
- `str' specifies the string of the new element.
- If `index' is equal to or more than the number of elements, this function has no effect. */
-void tclistinsert2(TCLIST *list, int index, const char *str);
-
-
-/* Remove an element at the specified location of a list object.
- `list' specifies the list object.
- `index' specifies the index of the element to be removed.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the removed element.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. If `index' is equal to or more than the number of elements, no element
- is removed and the return value is `NULL'. */
-void *tclistremove(TCLIST *list, int index, int *sp);
-
-
-/* Remove a string element at the specified location of a list object.
- `list' specifies the list object.
- `index' specifies the index of the element to be removed.
- The return value is the string of the removed element.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. If `index' is equal to or more
- than the number of elements, no element is removed and the return value is `NULL'. */
-char *tclistremove2(TCLIST *list, int index);
-
-
-/* Overwrite an element at the specified location of a list object.
- `list' specifies the list object.
- `index' specifies the index of the element to be overwritten.
- `ptr' specifies the pointer to the region of the new content.
- `size' specifies the size of the new content.
- If `index' is equal to or more than the number of elements, this function has no effect. */
-void tclistover(TCLIST *list, int index, const void *ptr, int size);
-
-
-/* Overwrite a string element at the specified location of a list object.
- `list' specifies the list object.
- `index' specifies the index of the element to be overwritten.
- `str' specifies the string of the new content.
- If `index' is equal to or more than the number of elements, this function has no effect. */
-void tclistover2(TCLIST *list, int index, const char *str);
-
-
-/* Sort elements of a list object in lexical order.
- `list' specifies the list object. */
-void tclistsort(TCLIST *list);
-
-
-/* Sort elements of a list object in case-insensitive lexical order.
- `list' specifies the list object. */
-void tclistsortci(TCLIST *list);
-
-
-/* Sort elements of a list object by an arbitrary comparison function.
- `list' specifies the list object.
- `cmp' specifies the pointer to the comparison function. The structure TCLISTDATUM has the
- member "ptr" which is the pointer to the region of the element, and the member "size" which is
- the size of the region. */
-void tclistsortex(TCLIST *list, int (*cmp)(const TCLISTDATUM *, const TCLISTDATUM *));
-
-
-/* Search a list object for an element using liner search.
- `list' specifies the list object.
- `ptr' specifies the pointer to the region of the key.
- `size' specifies the size of the region.
- The return value is the index of a corresponding element or -1 if there is no corresponding
- element.
- If two or more elements correspond, the former returns. */
-int tclistlsearch(const TCLIST *list, const void *ptr, int size);
-
-
-/* Search a list object for an element using binary search.
- `list' specifies the list object. It should be sorted in lexical order.
- `ptr' specifies the pointer to the region of the key.
- `size' specifies the size of the region.
- The return value is the index of a corresponding element or -1 if there is no corresponding
- element.
- If two or more elements correspond, which returns is not defined. */
-int tclistbsearch(const TCLIST *list, const void *ptr, int size);
-
-
-/* Clear a list object.
- `list' specifies the list object.
- All elements are removed. */
-void tclistclear(TCLIST *list);
-
-
-/* Serialize a list object into a byte array.
- `list' specifies the list object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the result serial region.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-void *tclistdump(const TCLIST *list, int *sp);
-
-
-/* Create a list object from a serialized byte array.
- `ptr' specifies the pointer to the region of serialized byte array.
- `size' specifies the size of the region.
- The return value is a new list object.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tclistload(const void *ptr, int size);
-
-
-
-/*************************************************************************************************
- * hash map
- *************************************************************************************************/
-
-
-typedef struct _TCMAPREC { /* type of structure for an element of a map */
- int ksiz; /* size of the region of the key */
- int vsiz; /* size of the region of the value */
- unsigned int hash; /* second hash value */
- struct _TCMAPREC *left; /* pointer to the left child */
- struct _TCMAPREC *right; /* pointer to the right child */
- struct _TCMAPREC *prev; /* pointer to the previous element */
- struct _TCMAPREC *next; /* pointer to the next element */
-} TCMAPREC;
-
-typedef struct { /* type of structure for a map */
- TCMAPREC **buckets; /* bucket array */
- TCMAPREC *first; /* pointer to the first element */
- TCMAPREC *last; /* pointer to the last element */
- TCMAPREC *cur; /* pointer to the current element */
- uint32_t bnum; /* number of buckets */
- uint64_t rnum; /* number of records */
- uint64_t msiz; /* total size of records */
-} TCMAP;
-
-
-/* Create a map object.
- The return value is the new map object. */
-TCMAP *tcmapnew(void);
-
-
-/* Create a map object with specifying the number of the buckets.
- `bnum' specifies the number of the buckets.
- The return value is the new map object. */
-TCMAP *tcmapnew2(uint32_t bnum);
-
-
-/* Copy a map object.
- `map' specifies the map object.
- The return value is the new map object equivalent to the specified object. */
-TCMAP *tcmapdup(const TCMAP *map);
-
-
-/* Delete a map object.
- `map' specifies the map object.
- Note that the deleted object and its derivatives can not be used anymore. */
-void tcmapdel(TCMAP *map);
-
-
-/* Store a record into a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If a record with the same key exists in the map, it is overwritten. */
-void tcmapput(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a string record into a map object.
- `map' specifies the map object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If a record with the same key exists in the map, it is overwritten. */
-void tcmapput2(TCMAP *map, const char *kstr, const char *vstr);
-
-
-/* Store a record of the value of two regions into a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `fvbuf' specifies the pointer to the former region of the value.
- `fvsiz' specifies the size of the former region of the value.
- `lvbuf' specifies the pointer to the latter region of the value.
- `lvsiz' specifies the size of the latter region of the value.
- If a record with the same key exists in the map, it is overwritten. */
-void tcmapput3(TCMAP *map, const char *kbuf, int ksiz,
- const void *fvbuf, int fvsiz, const char *lvbuf, int lvsiz);
-
-
-/* Store a new record into a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the map, this function has no effect. */
-bool tcmapputkeep(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a new string record into a map object.
- `map' specifies the map object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the map, this function has no effect. */
-bool tcmapputkeep2(TCMAP *map, const char *kstr, const char *vstr);
-
-
-/* Concatenate a value at the end of the value of the existing record in a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If there is no corresponding record, a new record is created. */
-void tcmapputcat(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Concatenate a string value at the end of the value of the existing record in a map object.
- `map' specifies the map object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If there is no corresponding record, a new record is created. */
-void tcmapputcat2(TCMAP *map, const char *kstr, const char *vstr);
-
-
-/* Remove a record of a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true. False is returned when no record corresponds to
- the specified key. */
-bool tcmapout(TCMAP *map, const void *kbuf, int ksiz);
-
-
-/* Remove a string record of a map object.
- `map' specifies the map object.
- `kstr' specifies the string of the key.
- If successful, the return value is true. False is returned when no record corresponds to
- the specified key. */
-bool tcmapout2(TCMAP *map, const char *kstr);
-
-
-/* Retrieve a record in a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the
- corresponding record. `NULL' is returned when no record corresponds.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. */
-const void *tcmapget(const TCMAP *map, const void *kbuf, int ksiz, int *sp);
-
-
-/* Retrieve a string record in a map object.
- `map' specifies the map object.
- `kstr' specifies the string of the key.
- If successful, the return value is the string of the value of the corresponding record.
- `NULL' is returned when no record corresponds. */
-const char *tcmapget2(const TCMAP *map, const char *kstr);
-
-
-/* Retrieve a semivolatile record in a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the
- corresponding record. `NULL' is returned when no record corresponds.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. The internal region of the returned
- record is moved to the tail so that the record will survive for a time under LRU cache
- algorithm removing records from the head. */
-const void *tcmapget3(TCMAP *map, const void *kbuf, int ksiz, int *sp);
-
-
-/* Move a record to the edge of a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of a key.
- `ksiz' specifies the size of the region of the key.
- `head' specifies the destination which is head if it is true or tail if else.
- If successful, the return value is true. False is returned when no record corresponds to
- the specified key. */
-bool tcmapmove(TCMAP *map, const void *kbuf, int ksiz, bool head);
-
-
-/* Move a string record to the edge of a map object.
- `map' specifies the map object.
- `kstr' specifies the string of a key.
- `head' specifies the destination which is head if it is true or tail if else.
- If successful, the return value is true. False is returned when no record corresponds to
- the specified key. */
-bool tcmapmove2(TCMAP *map, const char *kstr, bool head);
-
-
-/* Initialize the iterator of a map object.
- `map' specifies the map object.
- The iterator is used in order to access the key of every record stored in the map object. */
-void tcmapiterinit(TCMAP *map);
-
-
-/* Get the next key of the iterator of a map object.
- `map' specifies the map object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the next key, else, it is
- `NULL'. `NULL' is returned when no record can be fetched from the iterator.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string.
- The order of iteration is assured to be the same as the stored order. */
-const void *tcmapiternext(TCMAP *map, int *sp);
-
-
-/* Get the next key string of the iterator of a map object.
- `map' specifies the map object.
- If successful, the return value is the pointer to the region of the next key, else, it is
- `NULL'. `NULL' is returned when no record can be fetched from the iterator.
- The order of iteration is assured to be the same as the stored order. */
-const char *tcmapiternext2(TCMAP *map);
-
-
-/* Get the value bound to the key fetched from the iterator of a map object.
- `kbuf' specifies the pointer to the region of the iteration key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the value of the corresponding record.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. */
-const void *tcmapiterval(const void *kbuf, int *sp);
-
-
-/* Get the value string bound to the key fetched from the iterator of a map object.
- `kstr' specifies the string of the iteration key.
- The return value is the pointer to the region of the value of the corresponding record. */
-const char *tcmapiterval2(const char *kstr);
-
-
-/* Get the number of records stored in a map object.
- `map' specifies the map object.
- The return value is the number of the records stored in the map object. */
-uint64_t tcmaprnum(const TCMAP *map);
-
-
-/* Get the total size of memory used in a map object.
- `map' specifies the map object.
- The return value is the total size of memory used in a map object. */
-uint64_t tcmapmsiz(const TCMAP *map);
-
-
-/* Create a list object containing all keys in a map object.
- `map' specifies the map object.
- The return value is the new list object containing all keys in the map object.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcmapkeys(const TCMAP *map);
-
-
-/* Create a list object containing all values in a map object.
- `map' specifies the map object.
- The return value is the new list object containing all values in the map object.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcmapvals(const TCMAP *map);
-
-
-/* Add an integer to a record in a map object.
- `map' specifies the map object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `num' specifies the additional value.
- If the corresponding record exists, the value is treated as a integer and is added to. If no
- record corresponds, a new record of the additional value is stored. */
-void tcmapaddint(TCMAP *map, const char *kbuf, int ksiz, int num);
-
-
-/* Clear a map object.
- `map' specifies the map object.
- All records are removed. */
-void tcmapclear(TCMAP *map);
-
-
-/* Remove front records of a map object.
- `map' specifies the map object.
- `num' specifies the number of records to be removed.
- If successful, the return value is true. False is returned when no record corresponds to
- the specified key. */
-void tcmapcutfront(TCMAP *map, int num);
-
-
-/* Serialize a map object into a byte array.
- `map' specifies the map object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the result serial region.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-void *tcmapdump(const TCMAP *map, int *sp);
-
-
-/* Create a map object from a serialized byte array.
- `ptr' specifies the pointer to the region of serialized byte array.
- `size' specifies the size of the region.
- The return value is a new map object.
- Because the object of the return value is created with the function `tcmapnew', it should be
- deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcmapload(const void *ptr, int size);
-
-
-/* Extract a map record from a serialized byte array.
- `ptr' specifies the pointer to the region of serialized byte array.
- `size' specifies the size of the region.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the
- corresponding record. `NULL' is returned when no record corresponds.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. */
-void *tcmaploadone(const void *ptr, int size, const void *kbuf, int ksiz, int *sp);
-
-
-
-/*************************************************************************************************
- * on-memory database
- *************************************************************************************************/
-
-
-typedef struct { /* type of structure for a on-memory database */
- void **mmtxs; /* mutexes for method */
- void *imtx; /* mutex for iterator */
- TCMAP **maps; /* internal map object */
- int iter; /* index of maps for the iterator */
-} TCMDB;
-
-
-/* Create an on-memory database object.
- The return value is the new on-memory database object.
- The object can be shared by plural threads because of the internal mutex. */
-TCMDB *tcmdbnew(void);
-
-
-/* Create an on-memory database object with specifying the number of the buckets.
- `bnum' specifies the number of the buckets.
- The return value is the new on-memory database object.
- The object can be shared by plural threads because of the internal mutex. */
-TCMDB *tcmdbnew2(uint32_t bnum);
-
-
-/* Delete an on-memory database object.
- `mdb' specifies the on-memory database object. */
-void tcmdbdel(TCMDB *mdb);
-
-
-/* Store a record into an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If a record with the same key exists in the database, it is overwritten. */
-void tcmdbput(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a string record into an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If a record with the same key exists in the database, it is overwritten. */
-void tcmdbput2(TCMDB *mdb, const char *kstr, const char *vstr);
-
-
-/* Store a record of the value of two regions into an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `fvbuf' specifies the pointer to the former region of the value.
- `fvsiz' specifies the size of the former region of the value.
- `lvbuf' specifies the pointer to the latter region of the value.
- `lvsiz' specifies the size of the latter region of the value.
- If a record with the same key exists in the database, it is overwritten. */
-void tcmdbput3(TCMDB *mdb, const char *kbuf, int ksiz,
- const void *fvbuf, int fvsiz, const char *lvbuf, int lvsiz);
-
-
-/* Store a new record into an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tcmdbputkeep(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Store a new string record into an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If successful, the return value is true, else, it is false.
- If a record with the same key exists in the database, this function has no effect. */
-bool tcmdbputkeep2(TCMDB *mdb, const char *kstr, const char *vstr);
-
-
-/* Concatenate a value at the end of the value of the existing record in an on-memory database.
- `mdb' specifies the on-memory database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `vbuf' specifies the pointer to the region of the value.
- `vsiz' specifies the size of the region of the value.
- If there is no corresponding record, a new record is created. */
-void tcmdbputcat(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);
-
-
-/* Concatenate a string at the end of the value of the existing record in an on-memory database.
- `mdb' specifies the on-memory database object.
- `kstr' specifies the string of the key.
- `vstr' specifies the string of the value.
- If there is no corresponding record, a new record is created. */
-void tcmdbputcat2(TCMDB *mdb, const char *kstr, const char *vstr);
-
-
-/* Remove a record of an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is true. False is returned when no record corresponds to
- the specified key. */
-bool tcmdbout(TCMDB *mdb, const void *kbuf, int ksiz);
-
-
-/* Remove a string record of an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kstr' specifies the string of the key.
- If successful, the return value is true. False is returned when no record corresponds to
- the specified key. */
-bool tcmdbout2(TCMDB *mdb, const char *kstr);
-
-
-/* Retrieve a record in an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the
- corresponding record. `NULL' is returned when no record corresponds.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-void *tcmdbget(TCMDB *mdb, const void *kbuf, int ksiz, int *sp);
-
-
-/* Retrieve a string record in an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the string of the value of the corresponding record.
- `NULL' is returned when no record corresponds.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcmdbget2(TCMDB *mdb, const char *kstr);
-
-
-/* Retrieve a record and move it astern in an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the value of the
- corresponding record. `NULL' is returned when no record corresponds.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return value
- is allocated with the `malloc' call, it should be released with the `free' call when it is no
- longer in use. The internal region of the returned record is moved to the tail so that the
- record will survive for a time under LRU cache algorithm removing records from the head. */
-void *tcmdbget3(TCMDB *mdb, const void *kbuf, int ksiz, int *sp);
-
-
-/* Get the size of the value of a record in an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kbuf' specifies the pointer to the region of the key.
- `ksiz' specifies the size of the region of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1. */
-int tcmdbvsiz(TCMDB *mdb, const void *kbuf, int ksiz);
-
-
-/* Get the size of the value of a string record in an on-memory database object.
- `mdb' specifies the on-memory database object.
- `kstr' specifies the string of the key.
- If successful, the return value is the size of the value of the corresponding record, else,
- it is -1. */
-int tcmdbvsiz2(TCMDB *mdb, const char *kstr);
-
-
-/* Initialize the iterator of an on-memory database object.
- `mdb' specifies the on-memory database object.
- The iterator is used in order to access the key of every record stored in the on-memory
- database. */
-void tcmdbiterinit(TCMDB *mdb);
-
-
-/* Get the next key of the iterator of an on-memory database object.
- `mdb' specifies the on-memory database object.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the region of the next key, else, it is
- `NULL'. `NULL' is returned when no record can be fetched from the iterator.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. The order of iteration is assured to be the same as the stored
- order. */
-void *tcmdbiternext(TCMDB *mdb, int *sp);
-
-
-/* Get the next key string of the iterator of an on-memory database object.
- `mdb' specifies the on-memory database object.
- If successful, the return value is the pointer to the region of the next key, else, it is
- `NULL'. `NULL' is returned when no record can be fetched from the iterator.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. The order of iteration is assured
- to be the same as the stored order. */
-char *tcmdbiternext2(TCMDB *mdb);
-
-
-/* Get forward matching keys in an on-memory database object.
- `mdb' specifies the on-memory database object.
- `pbuf' specifies the pointer to the region of the prefix.
- `psiz' specifies the size of the region of the prefix.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the corresponding keys. This function does never fail
- and return an empty list even if no key corresponds.
- Because the object of the return value is created with the function `tclistnew', it should be
- deleted with the function `tclistdel' when it is no longer in use. Note that this function
- may be very slow because every key in the database is scanned. */
-TCLIST *tcmdbfwmkeys(TCMDB *mdb, const void *pbuf, int psiz, int max);
-
-
-/* Get forward matching string keys in an on-memory database object.
- `mdb' specifies the on-memory database object.
- `pstr' specifies the string of the prefix.
- `max' specifies the maximum number of keys to be fetched. If it is negative, no limit is
- specified.
- The return value is a list object of the corresponding keys. This function does never fail
- and return an empty list even if no key corresponds.
- Because the object of the return value is created with the function `tclistnew', it should be
- deleted with the function `tclistdel' when it is no longer in use. Note that this function
- may be very slow because every key in the database is scanned. */
-TCLIST *tcmdbfwmkeys2(TCMDB *mdb, const char *pstr, int max);
-
-
-/* Get the number of records stored in an on-memory database object.
- `mdb' specifies the on-memory database object.
- The return value is the number of the records stored in the database. */
-uint64_t tcmdbrnum(TCMDB *mdb);
-
-
-/* Get the total size of memory used in an on-memory database object.
- `mdb' specifies the on-memory database object.
- The return value is the total size of memory used in the database. */
-uint64_t tcmdbmsiz(TCMDB *mdb);
-
-
-/* Clear an on-memory database object.
- `mdb' specifies the on-memory database object.
- All records are removed. */
-void tcmdbvanish(TCMDB *mdb);
-
-
-/* Remove front records of an on-memory database object.
- `mdb' specifies the on-memory database object.
- `num' specifies the number of records to be removed.
- If successful, the return value is true. False is returned when no record corresponds to
- the specified key. */
-void tcmdbcutfront(TCMDB *mdb, int num);
-
-
-
-/*************************************************************************************************
- * memory pool
- *************************************************************************************************/
-
-
-typedef struct { /* type of an element of memory pool */
- void *ptr; /* pointer */
- void (*del)(void *); /* deleting function */
-} TCMPELEM;
-
-typedef struct { /* type of structure for a memory pool object */
- void *mutex; /* mutex for operations */
- TCMPELEM *elems; /* array of elements */
- int anum; /* number of the elements of the array */
- int num; /* number of used elements */
-} TCMPOOL;
-
-
-/* Create a memory pool object.
- The return value is the new memory pool object. */
-TCMPOOL *tcmpoolnew(void);
-
-
-/* Delete a memory pool object.
- `mpool' specifies the memory pool object.
- Note that the deleted object and its derivatives can not be used anymore. */
-void tcmpooldel(TCMPOOL *mpool);
-
-
-/* Relegate an arbitrary object to a memory pool object.
- `mpool' specifies the memory pool object.
- `ptr' specifies the pointer to the object to be relegated.
- `del' specifies the pointer to the function to delete the object.
- This function assures that the specified object is deleted when the memory pool object is
- deleted. */
-void tcmpoolput(TCMPOOL *mpool, void *ptr, void (*del)(void *));
-
-
-/* Relegate an allocated region to a memory pool object.
- `ptr' specifies the pointer to the region to be relegated.
- This function assures that the specified region is released when the memory pool object is
- deleted. */
-void tcmpoolputptr(TCMPOOL *mpool, void *ptr);
-
-
-/* Relegate an extensible string object to a memory pool object.
- `mpool' specifies the memory pool object.
- `xstr' specifies the extensible string object.
- This function assures that the specified object is deleted when the memory pool object is
- deleted. */
-void tcmpoolputxstr(TCMPOOL *mpool, TCXSTR *xstr);
-
-
-/* Relegate a list object to a memory pool object.
- `mpool' specifies the memory pool object.
- `list' specifies the list object.
- This function assures that the specified object is deleted when the memory pool object is
- deleted. */
-void tcmpoolputlist(TCMPOOL *mpool, TCLIST *list);
-
-
-/* Relegate a map object to a memory pool object.
- `mpool' specifies the memory pool object.
- `map' specifies the map object.
- This function assures that the specified object is deleted when the memory pool object is
- deleted. */
-void tcmpoolputmap(TCMPOOL *mpool, TCMAP *map);
-
-
-/* Allocate a region relegated to a memory pool object.
- `mpool' specifies the memory pool object.
- The return value is the pointer to the allocated region under the memory pool. */
-void *tcmpoolmalloc(TCMPOOL *mpool, size_t size);
-
-
-/* Create an extensible string object relegated to a memory pool object.
- The return value is the new extensible string object under the memory pool. */
-TCXSTR *tcmpoolxstrnew(TCMPOOL *mpool);
-
-
-/* Create a list object relegated to a memory pool object.
- The return value is the new list object under the memory pool. */
-TCLIST *tcmpoollistnew(TCMPOOL *mpool);
-
-
-/* Create a map object relegated to a memory pool object.
- The return value is the new map object under the memory pool. */
-TCMAP *tcmpoolmapnew(TCMPOOL *mpool);
-
-
-/* Get the global memory pool object.
- The return value is the global memory pool object.
- The global memory pool object is a singleton and assured to be deleted when the porcess is
- terminating normally. */
-TCMPOOL *tcmpoolglobal(void);
-
-
-
-/*************************************************************************************************
- * miscellaneous utilities
- *************************************************************************************************/
-
-
-/* Get the larger value of two integers.
- `a' specifies an integer.
- `b' specifies the other integer.
- The return value is the larger value of the two. */
-long tclmax(long a, long b);
-
-
-/* Get the lesser value of two integers.
- `a' specifies an integer.
- `b' specifies the other integer.
- The return value is the lesser value of the two. */
-long tclmin(long a, long b);
-
-
-/* Get a random number as long integer based on uniform distribution.
- The return value is the random number between 0 and `ULONG_MAX'.
- This function uses the random number source device and generates a real random number if
- possible. */
-unsigned long tclrand(void);
-
-
-/* Get a random number as double decimal based on uniform distribution.
- The return value is the random number equal to or greater than 0, and less than 1.0.
- This function uses the random number source device and generates a real random number if
- possible. */
-double tcdrand(void);
-
-
-/* Get a random number as double decimal based on normal distribution.
- `avg' specifies the average.
- `sd' specifies the standard deviation.
- The return value is the random number.
- This function uses the random number source device and generates a real random number if
- possible. */
-double tcdrandnd(double avg, double sd);
-
-
-/* Compare two strings with case insensitive evaluation.
- `astr' specifies a string.
- `bstr' specifies of the other string.
- The return value is positive if the former is big, negative if the latter is big, 0 if both
- are equivalent. */
-int tcstricmp(const char *astr, const char *bstr);
-
-
-/* Check whether a string begins with a key.
- `str' specifies the target string.
- `key' specifies the forward matching key string.
- The return value is true if the target string begins with the key, else, it is false. */
-bool tcstrfwm(const char *str, const char *key);
-
-
-/* Check whether a string begins with a key with case insensitive evaluation.
- `str' specifies the target string.
- `key' specifies the forward matching key string.
- The return value is true if the target string begins with the key, else, it is false. */
-bool tcstrifwm(const char *str, const char *key);
-
-
-/* Check whether a string ends with a key.
- `str' specifies the target string.
- `key' specifies the backward matching key string.
- The return value is true if the target string ends with the key, else, it is false. */
-bool tcstrbwm(const char *str, const char *key);
-
-
-/* Check whether a string ends with a key with case insensitive evaluation.
- `str' specifies the target string.
- `key' specifies the backward matching key string.
- The return value is true if the target string ends with the key, else, it is false. */
-bool tcstribwm(const char *str, const char *key);
-
-
-/* Calculate the edit distance of two strings.
- `astr' specifies a string.
- `bstr' specifies of the other string.
- The return value is the edit distance which is known as the Levenshtein distance. The cost is
- calculated by byte. */
-int tcstrdist(const char *astr, const char *bstr);
-
-
-/* Calculate the edit distance of two UTF-8 strings.
- `astr' specifies a string.
- `bstr' specifies of the other string.
- The return value is the edit distance which is known as the Levenshtein distance. The cost is
- calculated by Unicode character. */
-int tcstrdistutf(const char *astr, const char *bstr);
-
-
-/* Convert the letters of a string into upper case.
- `str' specifies the string to be converted.
- The return value is the string itself. */
-char *tcstrtoupper(char *str);
-
-
-/* Convert the letters of a string into lower case.
- `str' specifies the string to be converted.
- The return value is the string itself. */
-char *tcstrtolower(char *str);
-
-
-/* Cut space characters at head or tail of a string.
- `str' specifies the string to be converted.
- The return value is the string itself. */
-char *tcstrtrim(char *str);
-
-
-/* Squeeze space characters in a string and trim it.
- `str' specifies the string to be converted.
- The return value is the string itself. */
-char *tcstrsqzspc(char *str);
-
-
-/* Substitute characters in a string.
- `str' specifies the string to be converted.
- `rstr' specifies the string containing characters to be replaced.
- `sstr' specifies the string containing characters to be substituted.
- If the substitute string is shorter then the replacement string, corresponding characters are
- removed. */
-char *tcstrsubchr(char *str, const char *rstr, const char *sstr);
-
-
-/* Count the number of characters in a string of UTF-8.
- `str' specifies the string of UTF-8.
- The return value is the number of characters in the string. */
-int tcstrcntutf(const char *str);
-
-
-/* Cut a string of UTF-8 at the specified number of characters.
- `str' specifies the string of UTF-8.
- `num' specifies the number of characters to be kept.
- The return value is the string itself. */
-char *tcstrcututf(char *str, int num);
-
-
-/* Convert a UTF-8 string into a UCS-2 array.
- `str' specifies the UTF-8 string.
- `ary' specifies the pointer to the region into which the result UCS-2 codes are written. The
- size of the buffer should be sufficient.
- `np' specifies the pointer to a variable into which the number of elements of the result array
- is assigned. */
-void tcstrutftoucs(const char *str, uint16_t *ary, int *np);
-
-
-/* Convert a UCS-2 array into a UTF-8 string.
- `ary' specifies the array of UCS-2 code codes.
- `num' specifies the number of the array.
- `str' specifies the pointer to the region into which the result UTF-8 string is written. The
- size of the buffer should be sufficient. */
-void tcstrucstoutf(const uint16_t *ary, int num, char *str);
-
-
-/* Create a list object by splitting a string.
- `str' specifies the source string.
- `delim' specifies a string containing delimiting characters.
- The return value is a list object of the split elements.
- If two delimiters are successive, it is assumed that an empty element is between the two.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcstrsplit(const char *str, const char *delims);
-
-
-/* Create a string by joining all elements of a list object.
- `list' specifies a list object.
- `delim' specifies a delimiting character.
- The return value is the result string.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcstrjoin(TCLIST *list, char delim);
-
-
-/* Check whether a string matches a regular expression.
- `str' specifies the target string.
- `regex' specifies the regular expression string. If it begins with `*', the trailing
- substring is used as a case-insensitive regular expression.
- The return value is true if matching is success, else, it is false. */
-bool tcregexmatch(const char *str, const char *regex);
-
-
-/* Replace each substring matching a regular expression string.
- `str' specifies the target string.
- `regex' specifies the regular expression string for substrings. If it begins with `*', the
- trailing substring is used as a case-insensitive regular expression.
- `alt' specifies the alternative string with which each substrings is replaced. Each `&' in
- the string is replaced with the matched substring. Each `\' in the string escapes the
- following character. Special escapes "\1" through "\9" referring to the corresponding
- matching sub-expressions in the regular expression string are supported.
- The return value is a new converted string. Even if the regular expression is invalid, a copy
- of the original string is returned.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcregexreplace(const char *str, const char *regex, const char *alt);
-
-
-/* Get the time of day in seconds.
- The return value is the time of day in seconds. The accuracy is in microseconds. */
-double tctime(void);
-
-
-/* Get the Gregorian calendar of a time.
- `t' specifies the source time in seconds from the epoch. If it is `INT64_MAX', the current
- time is specified.
- `jl' specifies the jet lag of a location in seconds. If it is `INT_MAX', the local jet lag is
- specified.
- `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL',
- it is not used.
- `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL',
- it is not used. 1 means January and 12 means December.
- `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it
- is `NULL', it is not used.
- `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL',
- it is not used.
- `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL',
- it is not used.
- `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL',
- it is not used. */
-void tccalendar(int64_t t, int jl, int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp);
-
-
-/* Format a date as a string in W3CDTF.
- `t' specifies the source time in seconds from the epoch. If it is `INT64_MAX', the current
- time is specified.
- `jl' specifies the jet lag of a location in seconds. If it is `INT_MAX', the local jet lag is
- specified.
- `buf' specifies the pointer to the region into which the result string is written. The size
- of the buffer should be equal to or more than 48 bytes.
- W3CDTF represents a date as "YYYY-MM-DDThh:mm:ddTZD". */
-void tcdatestrwww(int64_t t, int jl, char *buf);
-
-
-/* Format a date as a string in RFC 1123 format.
- `t' specifies the source time in seconds from the epoch. If it is `INT64_MAX', the current
- time is specified.
- `jl' specifies the jet lag of a location in seconds. If it is `INT_MAX', the local jet lag is
- specified.
- `buf' specifies the pointer to the region into which the result string is written. The size
- of the buffer should be equal to or more than 48 bytes.
- RFC 1123 format represents a date as "Wdy, DD-Mon-YYYY hh:mm:dd TZD". */
-void tcdatestrhttp(int64_t t, int jl, char *buf);
-
-
-/* Get the time value of a date string.
- `str' specifies the date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). Decimal
- can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, and "d" for in
- days.
- The return value is the time value of the date or `INT64_MAX' if the format is invalid. */
-int64_t tcstrmktime(const char *str);
-
-
-/* Get the day of week of a date.
- `year' specifies the year of a date.
- `mon' specifies the month of the date.
- `day' specifies the day of the date.
- The return value is the day of week of the date. 0 means Sunday and 6 means Saturday. */
-int tcdayofweek(int year, int mon, int day);
-
-
-
-/*************************************************************************************************
- * filesystem utilities
- *************************************************************************************************/
-
-
-/* Get the canonicalized absolute path of a file.
- `path' specifies the path of the file.
- The return value is the canonicalized absolute path of a file, or `NULL' if the path is
- invalid.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcrealpath(const char *path);
-
-
-/* Read whole data of a file.
- `path' specifies the path of the file. If it is `NULL', the standard input is specified.
- `limit' specifies the limiting size of reading data. If it is not more than 0, the limitation
- is not specified.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned. If it is `NULL', it is not used.
- The return value is the pointer to the allocated region of the read data, or `NULL' if the
- file could not be opened.
- Because an additional zero code is appended at the end of the region of the return value, the
- return value can be treated as a character string. Because the region of the return value is
- allocated with the `malloc' call, it should be released with the `free' call when when is no
- longer in use. */
-void *tcreadfile(const char *path, int limit, int *sp);
-
-
-/* Read every line of a file.
- `path' specifies the path of the file. If it is `NULL', the standard input is specified.
- The return value is a list object of every lines if successful, else it is `NULL'.
- Line separators are cut out. Because the object of the return value is created with the
- function `tclistnew', it should be deleted with the function `tclistdel' when it is no longer
- in use. */
-TCLIST *tcreadfilelines(const char *path);
-
-
-/* Write data into a file.
- `path' specifies the path of the file. If it is `NULL', the standard output is specified.
- `ptr' specifies the pointer to the data region.
- `size' specifies the size of the region.
- If successful, the return value is true, else, it is false. */
-bool tcwritefile(const char *path, const void *ptr, int size);
-
-
-/* Copy a file.
- `src' specifies the path of the source file.
- `dest' specifies the path of the destination file.
- The return value is true if successful, else, it is false.
- If the destination file exists, it is overwritten. */
-bool tccopyfile(const char *src, const char *dest);
-
-
-/* Read names of files in a directory.
- `path' specifies the path of the directory.
- The return value is a list object of names if successful, else it is `NULL'.
- Links to the directory itself and to the parent directory are ignored.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcreaddir(const char *path);
-
-
-/* Expand a pattern into a list of matched paths.
- `pattern' specifies the matching pattern.
- The return value is a list object of matched paths. If no path is matched, an empty list is
- returned.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. */
-TCLIST *tcglobpat(const char *pattern);
-
-
-/* Remove a file or a directory and its sub ones recursively.
- `path' specifies the path of the link.
- If successful, the return value is true, else, it is false. False is returned when the link
- does not exist or the permission is denied. */
-bool tcremovelink(const char *path);
-
-
-/* Write data into a file.
- `fd' specifies the file descriptor.
- `buf' specifies the buffer to be written.
- `size' specifies the size of the buffer.
- The return value is true if successful, else, it is false. */
-bool tcwrite(int fd, const void *buf, size_t size);
-
-
-/* Read data from a file.
- `fd' specifies the file descriptor.
- `buf' specifies the buffer to store into.
- `size' specifies the size of the buffer.
- The return value is true if successful, else, it is false. */
-bool tcread(int fd, void *buf, size_t size);
-
-
-/* Lock a file.
- `fd' specifies the file descriptor.
- `ex' specifies whether an exclusive lock or a shared lock is performed.
- `nb' specifies whether to request with non-blocking.
- The return value is true if successful, else, it is false. */
-bool tclock(int fd, bool ex, bool nb);
-
-
-
-/*************************************************************************************************
- * encoding utilities
- *************************************************************************************************/
-
-
-/* Encode a serial object with URL encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- The return value is the result string.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call if when is no longer in use. */
-char *tcurlencode(const char *ptr, int size);
-
-
-/* Decode a string encoded with URL encoding.
- `str' specifies the encoded string.
- `sp' specifies the pointer to a variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the result.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-char *tcurldecode(const char *str, int *sp);
-
-
-/* Break up a URL into elements.
- `str' specifies the URL string.
- The return value is the map handle whose keys are the name of elements. The key "self"
- specifies the URL itself. The key "scheme" specifies the scheme. The key "host" specifies
- the host of the server. The key "port" specifies the port number of the server. The key
- "authority" specifies the authority information. The key "path" specifies the path of the
- resource. The key "file" specifies the file name without the directory section. The key
- "query" specifies the query string. The key "fragment" specifies the fragment string.
- Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported.
- Because the object of the return value is created with the function `tcmapnew', it should be
- deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcurlbreak(const char *str);
-
-
-/* Resolve a relative URL with an absolute URL.
- `base' specifies the absolute URL of the base location.
- `target' specifies the URL to be resolved.
- The return value is the resolved URL. If the target URL is relative, a new URL of relative
- location from the base location is returned. Else, a copy of the target URL is returned.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcurlresolve(const char *base, const char *target);
-
-
-/* Encode a serial object with Base64 encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- The return value is the result string.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call if when is no longer in use. */
-char *tcbaseencode(const char *ptr, int size);
-
-
-/* Decode a string encoded with Base64 encoding.
- `str' specifies the encoded string.
- `sp' specifies the pointer to a variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the result.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-char *tcbasedecode(const char *str, int *sp);
-
-
-/* Encode a serial object with Quoted-printable encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- The return value is the result string.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call if when is no longer in use. */
-char *tcquoteencode(const char *ptr, int size);
-
-
-/* Decode a string encoded with Quoted-printable encoding.
- `str' specifies the encoded string.
- `sp' specifies the pointer to a variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the result.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when
- it is no longer in use. */
-char *tcquotedecode(const char *str, int *sp);
-
-
-/* Encode a string with MIME encoding.
- `str' specifies the string.
- `encname' specifies the string of the name of the character encoding.
- `base' specifies whether to use Base64 encoding. If it is false, Quoted-printable is used.
- The return value is the result string.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcmimeencode(const char *str, const char *encname, bool base);
-
-
-/* Decode a string encoded with MIME encoding.
- `str' specifies the encoded string.
- `enp' specifies the pointer to the region into which the name of encoding is written. If it
- is `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes.
- The return value is the result string.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcmimedecode(const char *str, char *enp);
-
-
-/* Compress a serial object with Packbits encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the result object, else, it is `NULL'.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcpackencode(const char *ptr, int size, int *sp);
-
-
-/* Decompress a serial object compressed with Packbits encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `sp' specifies the pointer to a variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the result object, else, it is `NULL'.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. */
-char *tcpackdecode(const char *ptr, int size, int *sp);
-
-
-/* Compress a serial object with TCBS encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the result object, else, it is `NULL'.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcbsencode(const char *ptr, int size, int *sp);
-
-
-/* Decompress a serial object compressed with TCBS encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `sp' specifies the pointer to a variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the result object, else, it is `NULL'.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. */
-char *tcbsdecode(const char *ptr, int size, int *sp);
-
-
-/* Compress a serial object with Deflate encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the result object, else, it is `NULL'.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcdeflate(const char *ptr, int size, int *sp);
-
-
-/* Decompress a serial object compressed with Deflate encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `sp' specifies the pointer to a variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the result object, else, it is `NULL'.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. */
-char *tcinflate(const char *ptr, int size, int *sp);
-
-
-/* Compress a serial object with GZIP encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `sp' specifies the pointer to the variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the result object, else, it is `NULL'.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call when it is no longer in use. */
-char *tcgzipencode(const char *ptr, int size, int *sp);
-
-
-/* Decompress a serial object compressed with GZIP encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `sp' specifies the pointer to a variable into which the size of the region of the return
- value is assigned.
- If successful, the return value is the pointer to the result object, else, it is `NULL'.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. */
-char *tcgzipdecode(const char *ptr, int size, int *sp);
-
-
-/* Get the CRC32 checksum of a serial object.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- The return value is the CRC32 checksum of the object. */
-unsigned int tcgetcrc(const char *ptr, int size);
-
-
-/* Encode an array of nonnegative integers with BER encoding.
- `ary' specifies the pointer to the array of nonnegative integers.
- `anum' specifies the size of the array.
- `sp' specifies the pointer to a variable into which the size of the region of the return
- value is assigned.
- The return value is the pointer to the region of the result.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call if when is no longer in use. */
-char *tcberencode(const unsigned int *ary, int anum, int *sp);
-
-
-/* Decode a serial object encoded with BER encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `np' specifies the pointer to a variable into which the number of elements of the return value
- is assigned.
- The return value is the pointer to the array of the result.
- Because the region of the return value is allocated with the `malloc' call, it should be
- released with the `free' call if when is no longer in use. */
-unsigned int *tcberdecode(const char *ptr, int size, int *np);
-
-
-/* Escape meta characters in a string with the entity references of XML.
- `str' specifies the string.
- The return value is the pointer to the escaped string.
- This function escapes only `&', `<', `>', and `"'. Because the region of the return value
- is allocated with the `malloc' call, it should be released with the `free' call when it is no
- longer in use. */
-char *tcxmlescape(const char *str);
-
-
-/* Unescape entity references in a string of XML.
- `str' specifies the string.
- The return value is the unescaped string.
- This function restores only `&', `<', `>', and `"'. Because the region of the
- return value is allocated with the `malloc' call, it should be released with the `free' call
- when it is no longer in use. */
-char *tcxmlunescape(const char *str);
-
-
-/* Split an XML string into tags and text sections.
- `str' specifies the XML string.
- The return value is the list object whose elements are strings of tags or text sections.
- Because the object of the return value is created with the function `tclistnew', it should
- be deleted with the function `tclistdel' when it is no longer in use. Because this function
- does not check validation, it can handle also HTML and SGML. */
-TCLIST *tcxmlbreak(const char *str);
-
-
-/* Get the map of attributes of an XML tag.
- `str' specifies the pointer to the region of a tag string.
- The return value is the map object containing attribute names and their values which are
- unescaped. You can get the name of the tag with the key of an empty string.
- Because the object of the return value is created with the function `tcmapnew', it should
- be deleted with the function `tcmapdel' when it is no longer in use. */
-TCMAP *tcxmlattrs(const char *str);
-
-
-
-/*************************************************************************************************
- * bit operation utilities
- *************************************************************************************************/
-
-
-typedef struct { /* type of structure for a bit stream object */
- uint8_t *sp; /* start pointer */
- uint8_t *cp; /* current pointer */
- int idx; /* bit index */
- int size; /* size of used region */
-} TCBITSTRM;
-
-
-/* Create a bitmap object. */
-#define TCBITMAPNEW(TC_num) \
- tccalloc(((TC_num) >> 3) + 1, 1);
-
-
-/* Delete a bitmap object */
-#define TCBITMAPDEL(TC_bitmap) \
- do { \
- free((TC_bitmap)); \
- } while(false);
-
-
-/* Turn on a field of a bitmap object. */
-#define TCBITMAPON(TC_bitmap, TC_idx) \
- do { \
- (TC_bitmap)[(TC_idx)>>3] |= 0x1 << ((TC_idx) & 0x7); \
- } while(false);
-
-
-/* Turn off a field of a bitmap object. */
-#define TCBITMAPOFF(TC_bitmap, TC_idx) \
- do { \
- (TC_bitmap)[(TC_idx)>>3] &= ~(0x1 << ((TC_idx) & 0x7)); \
- } while(false);
-
-
-/* Check a field of a bitmap object. */
-#define TCBITMAPCHECK(TC_bitmap, TC_idx) \
- ((TC_bitmap)[(TC_idx)>>3] & 0x1 << ((TC_idx) & 0x7))
-
-
-/* Initialize a bit stream object as writer. */
-#define TCBITSTRMINITW(TC_bitstrm, TC_ptr) \
- do { \
- (TC_bitstrm).sp = (uint8_t *)(TC_ptr); \
- (TC_bitstrm).cp = (TC_bitstrm).sp; \
- *(TC_bitstrm).cp = 0; \
- (TC_bitstrm).idx = 3; \
- (TC_bitstrm).size = 1; \
- } while(false);
-
-
-/* Concatenate a bit to a bit stream object. */
-#define TCBITSTRMCAT(TC_bitstrm, sign) \
- do { \
- if((TC_bitstrm).idx >= 8){ \
- *(++(TC_bitstrm).cp) = 0; \
- (TC_bitstrm).idx = 0; \
- (TC_bitstrm).size++; \
- } \
- *(TC_bitstrm).cp |= (sign << (TC_bitstrm).idx); \
- (TC_bitstrm).idx++; \
- } while(false);
-
-
-/* Set the end mark to a bit stream object. */
-#define TCBITSTRMSETEND(TC_bitstrm) \
- do { \
- if((TC_bitstrm).idx >= 8){ \
- *(++(TC_bitstrm).cp) = 0; \
- (TC_bitstrm).idx = 0; \
- (TC_bitstrm).size++; \
- } \
- *(TC_bitstrm).sp |= (TC_bitstrm).idx & 7; \
- } while(false);
-
-
-/* Get the size of the used region of a bit stream object. */
-#define TCBITSTRMSIZE(TC_bitstrm) \
- ((TC_bitstrm).size)
-
-
-/* Initialize a bit stream object as reader. */
-#define TCBITSTRMINITR(TC_bitstrm, TC_ptr, TC_size) \
- do { \
- (TC_bitstrm).sp = (uint8_t *)(TC_ptr); \
- (TC_bitstrm).cp = (TC_bitstrm).sp; \
- (TC_bitstrm).idx = 3; \
- (TC_bitstrm).size = (TC_size); \
- } while(false);
-
-
-/* Read a bit from a bit stream object. */
-#define TCBITSTRMREAD(TC_bitstrm, TC_sign) \
- do { \
- if((TC_bitstrm).idx >= 8){ \
- (TC_bitstrm).cp++; \
- (TC_bitstrm).idx = 0; \
- } \
- (TC_sign) = (*((TC_bitstrm).cp) & (1 << (TC_bitstrm).idx)) > 0; \
- (TC_bitstrm).idx++; \
- } while(false);
-
-
-/* Get the number of bits of a bit stream object. */
-#define TCBITSTRMNUM(TC_bitstrm) \
- ((((TC_bitstrm).size - 1) << 3) + (*(TC_bitstrm).sp & 7) - 3)
-
-
-
-/*************************************************************************************************
- * features for experts
- *************************************************************************************************/
-
-
-#include <stdio.h>
-
-#define _TC_VERSION "1.2.5"
-#define _TC_LIBVER 306
-#define _TC_FORMATVER "1.0"
-
-
-/* Show error message on the standard error output and exit.
- `message' specifies an error message.
- This function does not return. */
-void *tcmyfatal(const char *message);
-
-
-/* Lock the global mutex object.
- If successful, the return value is true, else, it is false. */
-bool tcglobalmutexlock(void);
-
-
-/* Lock the global mutex object by shared locking.
- If successful, the return value is true, else, it is false. */
-bool tcglobalmutexlockshared(void);
-
-
-/* Unlock the global mutex object.
- If successful, the return value is true, else, it is false. */
-bool tcglobalmutexunlock(void);
-
-
-/* Encode a serial object with BWT encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `idxp' specifies the pointer to the variable into which the index of the original string in
- the rotation array is assigned.
- The return value is the pointer to the result object.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. */
-char *tcbwtencode(const char *ptr, int size, int *idxp);
-
-
-/* Decode a serial object encoded with BWT encoding.
- `ptr' specifies the pointer to the region.
- `size' specifies the size of the region.
- `idx' specifies the index of the original string in the rotation array is assigned.
- The return value is the pointer to the result object.
- Because an additional zero code is appended at the end of the region of the return value,
- the return value can be treated as a character string. Because the region of the return
- value is allocated with the `malloc' call, it should be released with the `free' call when it
- is no longer in use. */
-char *tcbwtdecode(const char *ptr, int size, int idx);
-
-
-/* Print debug information with a formatted string as with `printf'. */
-#if __STDC_VERSION__ >= 199901L
-#define TCDPRINTF(...) \
- do { \
- fprintf(stderr, "%s:%d:%s: ", __FILE__, __LINE__, __func__); \
- fprintf(stderr, __VA_ARGS__); \
- fprintf(stderr, "\n"); \
- } while(false);
-#else
-#define TCDPRINTF(TC_str) \
- do { \
- fprintf(stderr, "%s:%d:%s: %s\n", __FILE__, __LINE__, __func__, TC_str); \
- } while(false);
-#endif
-
-
-/* Print hexadecimal pattern of a binary region. */
-#define TCPRINTHEX(TC_ptr, TC_size) \
- do { \
- for(int TC_i = 0; TC_i < (TC_size); TC_i++){ \
- if(TC_i > 0) putchar(' '); \
- printf("%02X", ((unsigned char *)(TC_ptr))[TC_i]); \
- } \
- putchar('\n'); \
- } while(false);
-
-
-/* Print an extensible string object. */
-#define TCPRINTXSTR(TC_xstr) \
- do { \
- fwrite(tcxstrptr((TC_xstr)), tcxstrsize((TC_xstr)), 1, stdout); \
- putchar('\n'); \
- } while(false);
-
-
-/* Print all elements of a list object. */
-#define TCPRINTLIST(TC_list) \
- do { \
- for(int TC_i = 0; TC_i < tclistnum((TC_list)); TC_i++){ \
- int TC_size; \
- const char *TC_ptr = tclistval((TC_list), TC_i, &TC_size); \
- printf("%p\t", (void *)(TC_list)); \
- fwrite(TC_ptr, TC_size, 1, stdout); \
- putchar('\n'); \
- } \
- putchar('\n'); \
- } while(false);
-
-
-/* Print all records of a list object. */
-#define TCPRINTMAP(TC_map) \
- do { \
- TCLIST *TC_keys = tcmapkeys((TC_map)); \
- for(int TC_i = 0; TC_i < tclistnum(TC_keys); TC_i++){ \
- int TC_ksiz; \
- const char *TC_kbuf = tclistval(TC_keys, TC_i, &TC_ksiz); \
- int TC_vsiz; \
- const char *TC_vbuf = tcmapget((TC_map), TC_kbuf, TC_ksiz, &TC_vsiz); \
- printf("%p\t", (void *)(TC_map)); \
- fwrite(TC_kbuf, TC_ksiz, 1, stdout); \
- putchar('\t'); \
- fwrite(TC_vbuf, TC_vsiz, 1, stdout); \
- putchar('\n'); \
- } \
- putchar('\n'); \
- tclistdel(TC_keys); \
- } while(false);
-
-
-/* Alias of `tcmemdup'. */
-#if defined(_MYFASTEST)
-#define TCMALLOC(TC_res, TC_size) \
- do { \
- (TC_res) = malloc(TC_size); \
- } while(false)
-#else
-#define TCMALLOC(TC_res, TC_size) \
- do { \
- if(!((TC_res) = malloc(TC_size))) tcmyfatal("out of memory"); \
- } while(false)
-#endif
-
-/* Alias of `tccalloc'. */
-#if defined(_MYFASTEST)
-#define TCCALLOC(TC_res, TC_nmemb, TC_size) \
- do { \
- (TC_res) = calloc((TC_nmemb), (TC_size)); \
- } while(false)
-#else
-#define TCCALLOC(TC_res, TC_nmemb, TC_size) \
- do { \
- if(!((TC_res) = calloc((TC_nmemb), (TC_size)))) tcmyfatal("out of memory"); \
- } while(false)
-#endif
-
-/* Alias of `tcrealloc'. */
-#if defined(_MYFASTEST)
-#define TCREALLOC(TC_res, TC_ptr, TC_size) \
- do { \
- (TC_res) = realloc((TC_ptr), (TC_size)); \
- } while(false)
-#else
-#define TCREALLOC(TC_res, TC_ptr, TC_size) \
- do { \
- if(!((TC_res) = realloc((TC_ptr), (TC_size)))) tcmyfatal("out of memory"); \
- } while(false)
-#endif
-
-/* Alias of `tcmemdup'. */
-#define TCMEMDUP(TC_res, TC_ptr, TC_size) \
- do { \
- TCMALLOC((TC_res), (TC_size) + 1); \
- memcpy((TC_res), (TC_ptr), (TC_size)); \
- (TC_res)[TC_size] = '\0'; \
- } while(false)
-
-
-/* Alias of `tcxstrcat'. */
-#define TCXSTRCAT(TC_xstr, TC_ptr, TC_size) \
- do { \
- int TC_mysize = (TC_size); \
- int TC_nsize = (TC_xstr)->size + TC_mysize + 1; \
- if((TC_xstr)->asize < TC_nsize){ \
- while((TC_xstr)->asize < TC_nsize){ \
- (TC_xstr)->asize *= 2; \
- if((TC_xstr)->asize < TC_nsize) (TC_xstr)->asize = TC_nsize; \
- } \
- TCREALLOC((TC_xstr)->ptr, (TC_xstr)->ptr, (TC_xstr)->asize); \
- } \
- memcpy((TC_xstr)->ptr + (TC_xstr)->size, (TC_ptr), TC_mysize); \
- (TC_xstr)->size += TC_mysize; \
- (TC_xstr)->ptr[(TC_xstr)->size] = '\0'; \
- } while(false)
-
-
-/* Alias of `tcxstrptr'. */
-#define TCXSTRPTR(TC_xstr) \
- ((TC_xstr)->ptr)
-
-
-/* Alias of `tcxstrsize'. */
-#define TCXSTRSIZE(TC_xstr) \
- ((TC_xstr)->size)
-
-
-/* Alias of `tclistnum'. */
-#define TCLISTNUM(TC_list) \
- ((TC_list)->num)
-
-
-/* Alias of `tclistval' but not checking size and not using the third parameter. */
-#define TCLISTVALPTR(TC_list, TC_index) \
- ((void *)((TC_list)->array[(TC_index)+(TC_list)->start].ptr))
-
-
-/* Alias of `tclistval' but not checking size and returning the size of the value. */
-#define TCLISTVALNUM(TC_list, TC_index) \
- ((TC_list)->array[(TC_index)+(TC_list)->start].size)
-
-
-/* Add an element at the end of a list object. */
-#define TCLISTPUSH(TC_list, TC_ptr, TC_size) \
- do { \
- int TC_mysize = (TC_size); \
- int TC_index = (TC_list)->start + (TC_list)->num; \
- if(TC_index >= (TC_list)->anum){ \
- (TC_list)->anum += (TC_list)->num + 1; \
- TCREALLOC((TC_list)->array, (TC_list)->array, \
- (TC_list)->anum * sizeof((TC_list)->array[0])); \
- } \
- TCLISTDATUM *array = (TC_list)->array; \
- TCMALLOC(array[TC_index].ptr, TC_mysize + 1); \
- memcpy(array[TC_index].ptr, (TC_ptr), TC_mysize); \
- array[TC_index].ptr[TC_mysize] = '\0'; \
- array[TC_index].size = TC_mysize; \
- (TC_list)->num++; \
- } while(false)
-
-
-/* Alias of `tcmaprnum'. */
-#define TCMAPRNUM(TC_map) \
- ((TC_map)->rnum)
-
-
-
-__TCUTIL_CLINKAGEEND
-#endif /* duplication check */
-
-
-/* END OF FILE */
+++ /dev/null
-/*************************************************************************************************
- * IDL for bindings of scripting languages
- * Copyright (C) 2006-2008 Mikio Hirabayashi
- * This file is part of Tokyo Cabinet.
- * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
- * the GNU Lesser General Public License as published by the Free Software Foundation; either
- * version 2.1 of the License or any later version. Tokyo Cabinet 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 Tokyo
- * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA.
- *************************************************************************************************/
-
-
-/**
- * namespace of Tokyo Cabinet
- */
-module TokyoCabinet {
- //----------------------------------------------------------------
- // list of strings (substituted for by the native mechanism).
- //----------------------------------------------------------------
- interface List {
- string get(in long index);
- };
- //----------------------------------------------------------------
- // the error codes
- //----------------------------------------------------------------
- interface ECODE {
- const long ESUCCESS = 0;
- const long ETHREAD = 1;
- const long EINVALID = 2;
- const long ENOFILE = 3;
- const long ENOPERM = 4;
- const long EMETA = 5;
- const long ERHEAD = 6;
- const long EOPEN = 7;
- const long ECLOSE = 8;
- const long ETRUNC = 9;
- const long ESYNC = 10;
- const long ESTAT = 11;
- const long ESEEK = 12;
- const long EREAD = 13;
- const long EWRITE = 14;
- const long EMMAP = 15;
- const long ELOCK = 16;
- const long EUNLINK = 17;
- const long ERENAME = 18;
- const long EMKDIR = 19;
- const long ERMDIR = 20;
- const long EKEEP = 21;
- const long ENOREC = 22;
- const long EMISC = 9999;
- string errmsg(in long ecode);
- };
- //----------------------------------------------------------------
- // the hash database API
- //----------------------------------------------------------------
- interface HDB :ECODE {
- const long TLARGE = 1 << 0;
- const long TDEFLATE = 1 << 1;
- const long TTCBS = 1 << 2;
- const long OREADER = 1 << 0;
- const long OWRITER = 1 << 1;
- const long OCREAT = 1 << 2;
- const long OTRUNC = 1 << 3;
- const long ONOLCK = 1 << 4;
- const long OLCKNB = 1 << 5;
- long ecode();
- boolean tune(in long long bnum, in long apow, in long fpow, in long opts);
- boolean setcache(in long rcnum);
- boolean open(in string path, in long omode);
- boolean close();
- boolean put(in string key, in string value);
- boolean putkeep(in string key, in string value);
- boolean putcat(in string key, in string value);
- boolean putasync(in string key, in string value);
- boolean out(in string key);
- string get(in string key);
- long vsiz(in string key);
- boolean iterinit();
- string iternext();
- List fwmkeys(in string prefix, in long max);
- boolean sync();
- boolean optimize(in long long bnum, in long apow, in long fpow, in long opts);
- boolean vanish();
- boolean copy(in string path);
- string path();
- long long rnum();
- long long fsiz();
- };
- //----------------------------------------------------------------
- // the B+ tree database API
- //----------------------------------------------------------------
- interface BDB :ECODE {
- const long TLARGE = 1 << 0;
- const long TDEFLATE = 1 << 1;
- const long TTCBS = 1 << 2;
- const long OREADER = 1 << 0;
- const long OWRITER = 1 << 1;
- const long OCREAT = 1 << 2;
- const long OTRUNC = 1 << 3;
- const long ONOLCK = 1 << 4;
- const long OLCKNB = 1 << 5;
- long ecode();
- boolean tune(in long lmemb, in long nmemb,
- in long long bnum, in long apow, in long fpow, in long opts);
- boolean setcache(in long lcnum, in long ncnum);
- boolean open(in string path, in long omode);
- boolean close();
- boolean put(in string key, in string value);
- boolean putkeep(in string key, in string value);
- boolean putcat(in string key, in string value);
- boolean putdup(in string key, in string value);
- boolean putlist(in string key, in List values);
- boolean out(in string key);
- boolean outlist(in string key);
- string get(in string key);
- List getlist(in string key);
- long vnum(in string key);
- long vsiz(in string key);
- List range(in string bkey, in boolean binc, in string ekey, in boolean einc, in long max);
- List fwmkeys(in string prefix, in long max);
- boolean sync();
- boolean optimize(in long lmemb, in long nmemb,
- in long long bnum, in long apow, in long fpow, in long opts);
- boolean vanish();
- boolean copy(in string path);
- boolean tranbegin();
- boolean trancommit();
- boolean tranabort();
- string path();
- long long rnum();
- long long fsiz();
- };
- //----------------------------------------------------------------
- // the B+ tree cursor API
- //----------------------------------------------------------------
- interface BDBCUR {
- const long CPCURRENT = 0;
- const long CPBEFORE = 1;
- const long CPAFTER = 2;
- boolean first();
- boolean last();
- boolean jump(in string key);
- boolean prev();
- boolean next();
- boolean put(in string value, in long cpmode);
- boolean out();
- string key();
- string val();
- };
-};
-
-
-
-/* END OF FILE */
+++ /dev/null
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-datarootdir = @datarootdir@
-bindir=@bindir@
-libdir=@libdir@
-libexecdir=@libexecdir@
-includedir=@includedir@
-datadir=@datadir@
-
-Name: Tokyo Cabinet
-Description: a modern implementation of DBM
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -ltokyocabinet @LIBS@
-Cflags: -I${includedir}